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);
    
   ...