JSFiddle - React, Tailwind, and code Playground
by mickeyvip
HTML
<div id='viewport' class='viewport'>
<div id='container' class='visuals-container'>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div class='visual'></div>
<div...
CSS
#viewport {
border: 1px solid green;
width: 400px;
height: 300px;
overflow: hidden;
position: relative;
}
#container {
border: 1px solid red;
background-color: #edd;
width: 500px;
height: 500px;
position: absolute;
}
.visual, .visual-big {
border: 1px solid blue;
background-color: #dde;
width: 55px;
height: 55px;
float: left;
margin-left: 5px;
margin-top: 5px;
}
.visual-big {
width: 100px;
height: 100px;
background-color: #ded;
border: 1px solid green;
position: absolute;
}
JavaScript
var viewport = $('#viewport');
var viewportWidth = viewport.width();
var viewportHeight = viewport.height();
var container = $('#container');
var containerWidth = container.outerWidth();
var containerHeight = container.outerHeight();
var horizontalDelta = containerWidth - viewportWidth;
var verticalDelta = containerHeight - viewportHeight;
var visualBig = container.find('.visual-big');
var draggingVisual = false;
visualBig.hide();
container.on('mousedown', function(e) {
console.log(e.type + ', target: ' + $(e.target).attr('class'));
var container = $(this);
var dragElement = $(e.target);
draggingVisual = false; dragElement.hasClass('visual');
console.log('dragging visual: ' + draggingVisual);
var isDragging = true;
var currentPosition = container.position();
var deltaX = currentPosition.left - e.pageX;
var deltaY = currentPosition.top - e.pageY;
var drag = function(e) {
//console.log(e.type + ', target: ' + $(e.target).attr('class'));
if(!isDragging) return;
draggingVisual = dragElement.hasClass('visual');
var newLeft = e.pageX + deltaX;
var newTop = e.pageY + deltaY;
if(newTop > 0) {
newTop = 0;
} else if(newTop < -verticalDelta) {
newTop = -verticalDelta;
}
if(newLeft > 0) {
newLeft = 0;
} else if(newLeft < -horizontalDelta) {
newLeft = -horizontalDelta;
}
container.css({
top: newTop,
left: newLeft
});
e.stopPropagation();
e.preventDefault();
return false;
};
var unset = function(e) {
console.log(e.type + ', target: ' + $(e.target).attr('class'));
isDragging = false;
container.off('mousemove', drag);
container.off('mouseup mouseleave', unset);
};
console.log('deltaX: ' + deltaX + ', deltaY: ' + deltaY);
...