JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.js"></script>
<div class="zoom_outer">
<div id="zoom">
<div id="gridGame" class="image-glow" style="width: 100%;">
<table>
<tr>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
</tr>
<tr>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
</tr>
<tr>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
</tr>
<tr>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
<td class="sortableCards in-td"></td>
</tr>
</table>
</div>
</div>
</div>
<ul class="cards sortableCards" style="width: 100%;bottom: 0;padding: 10px;justify-content: center;">
<li class="card1">
<div class="card1-inner">
<div class="icon text-center">
DRAG ME
</div>
</div>
</li>
</ul>
CSS
:root {
--color-neon: hsl(0 0% 100% / 0.8);
--cell-width: 150px;
--cell-height: 150px;
--cell-card-width: 90px;
--cell-card-height: 90px;
--cell-card-inner-width: 74px;
--cell-card-inner-height: 74px;
}
.cards {
display: flex;
position: fixed!important;
}
.card1 {
display: inline-block;
background: white;
border-radius: 20px;
width: 250px;
z-index: 1;
}
.card1-inner {
background-color: #2067d9;
margin: 8px;
padding: 15px;
border-radius: 20px;
text-align:center;
}
.card1:not(:first-child) {
margin-left: -12rem;
}
.zoom_outer {
width: inherit;
height: inherit;
}
#zoom {
width: inherit;
height: inherit;
transform-origin: 0px 0px;
transform: scale(1) translate(0px, 0px);
}
#gridGame {
height: inherit;
display: flex;
align-items: center;
justify-content: center;
}
#gridGame > table .in-td {
width: var(--cell-width);
height: var(--cell-height);
max-width: var(--cell-width);
max-height: var(--cell-height);
display: inline-flex;
justify-content: center;
align-items: center;
overflow: hidden;
background-color: rgba(255,255,255, 0.2);
border: 1px solid #ccc;
/*filter: drop-shadow(0 0 10px var(--color-neon));*/
}
.card1:active, .in-td .card1 {
width: var(--cell-card-width);
height: var(--cell-card-height);
min-width: var(--cell-card-width);
min-height: var(--cell-card-height);
max-width: var(--cell-card-width);
max-height: var(--cell-card-height);
}
.card1:active .card1-inner, .in-td .card1 .card1-inner {
width: var(--cell-card-inner-width);
height: var(--cell-card-inner-height);
min-width: var(--cell-card-inner-width);
min-height: var(--cell-card-inner-height);
max-width: var(--cell-card-inner-width);
max-height: var(--cell-card-inner-height);
overflow: hidden;
padding-top: 5px;
}
.in-td .card1...
JavaScript
var scale = 1,
panning = false,
pointX = 0,
pointY = 0,
start = { x: 0, y: 0 },
zoom = $("#zoom")[0];
////////////////////////////
// THE ELEMENT TO FIX
////////////////////////////
$(".sortableCards").sortable({
connectWith: ".sortableCards",
containment: "window",
scroll: false,
placeholder: "sortable-placeholder",
items: ".card1",
forcePlaceholderSize: false,
receive: function(event, ui) {
if ($(ui.sender).hasClass('cards')) {
if ($(this).find('.card1').length > 2) {
$(ui.sender).sortable('cancel');
} else {
ui.item.clone().appendTo($(ui.sender));
}
}
}
});
////////////////////////////
////////////////////////////
$(document).on('mousemove', e => {
$('.cursor').show();
$('.cursor').attr("style", "top: "+(e.pageY - 10)+"px; left: "+(e.pageX - 10)+"px;")
})
$(document).on('mousedown', () => {
$('.cursor').addClass("hold");
});
$(document).on('mouseup', function() {
$('.cursor').removeClass("hold");
});
function setTransform() {
zoom.style.transform = "translate(" + pointX + "px, " + pointY + "px) scale(" + scale + ")";
}
zoom.onmousedown = function (e) {
e.preventDefault();
start = { x: e.clientX - pointX, y: e.clientY - pointY };
panning = true;
}
zoom.onmouseup = function (e) {
panning = false;
}
zoom.onmousemove = function (e) {
e.preventDefault();
var isRightMB = ("which" in e) ? (e.which == 3) : (("button" in e) ? (e.button == 2) : false);
if (!panning || !isRightMB) {
return;
}
pointX = (e.clientX - start.x);
pointY = (e.clientY - start.y);
setTransform();
}
// ZOOM
zoom.onwheel = function (e) {
e.preventDefault();
var xs = (e.clientX - pointX) / scale,
ys = (e.clientY - pointY) / scale,
delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);
(delta > 0) ? (scale *= 1.2) : (scale /= 1.2);
pointX = e.clientX - xs * scale;
pointY = e.clientY - ys * scale;
setTransform();
}