I have some code which demonstrates the issue.
I have an element which can be dragged around which works fine. I have included a button which allows the user to "zoom" in. This is when it goes wrong.
The issue this has is , after you click the zoom button, the containment
part of draggable
no longer obeys left/top/width and height the constraint of the parent. It is still constrained but by an unexpected boundary location.
<body style="padding:50px">
<button id="btn">Zoom in</button>
<div id="wrapper" style="background-color:aliceblue;padding:50px;">
<div id="innerWrapper" style="background-color: ivory; min-height: 200px; width: 400px; ">
<div id="draggable" style="background-color:burlywood;max-width:100px;">Move me</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js" integrity="sha256-lSjKY0/srUM9BE3dPm+c4fBo1dky2v27Gdjm2uoZaL0=" crossorigin="anonymous"></script>
<script>
$("#draggable").draggable({containment:"#innerWrapper"});
const btn = document.getElementById("btn");
btn.addEventListener("click", zoom);
function zoom() {
document.getElementById("innerWrapper").style.transform = "scale(1.2,1.2)";
}
</script>
</body>
In fact, each time you click the zoom button provided, it changes the containment boundary.
I have tried to add the drag
event callback within the draggable but still unable to see how I can fix this
This occurs because of the scale()
, it acts strange in some compositions, and one of them is when you have a draggable element inside a containment, and that containment is scaled
, so the element inside doesn't update the actual size of it, even if you destroy
or disable
and enable
the draggable element.
So what you can do is calculate yourself the containment size:
const draggableElement = $("#draggable")
let containmentArea = $("#innerWrapper");
let percent = 1
draggableElement.draggable({
cursor: "move",
drag: dragFix,
});
function dragFix(event, ui) {
var contWidth = containmentArea.width(),
contHeight = containmentArea.height();
ui.position.left = Math.max(0, Math.min(ui.position.left / percent, contWidth - ui.helper.width()));
ui.position.top = Math.max(0, Math.min(ui.position.top / percent, contHeight - ui.helper.height()));
}
function setScale(scalePercentage) {
percent = scalePercentage;
$("#innerWrapper").css({
'transform': 'scale(' + percent + ')',
'-moz-transform': 'scale(' + percent + ')',
'-webkit-transform': 'scale(' + percent + ')',
'-ms-transform': 'scale(' + percent + ')'
})
}
const btn = document.getElementById("btn");
btn.addEventListener("click", function() {
setScale(1.2)
});
#wrapper {
width: 100%;
height: 300px;
overflow: auto;
}
#innerWrapper {
width: 250px;
height: 250px;
position: relative;
-webkit-transform-origin: 0 0;
-moz-transform-origin: 0 0;
transform-origin: 0 0;
-ms-transform-origin: 0 0;
}
#draggable {
display: inline;
position: absolute;
top: 10px;
left: 10px;
}
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<button id="btn">Zoom in</button>
<div id="wrapper" style="background-color:aliceblue;padding:50px;">
<div id="innerWrapper" style="background-color: ivory; min-height: 200px; width: 400px; ">
<div id="draggable" style="background-color:burlywood;max-width:100px;">Move me</div>
</div>
</div>
Notes:
1 - You can use only tranform
and transform-only
, I did this to show you can do with all the transform
types
2 - For not having glitches when clicking the draggable element you need to make it absolute
and the wrapper relative