The desired result that I'm looking for is for the red square to follow the mouse smoothly, and not flicker back to the original position. Basically, I want to click the red square, drag it to an area, and then release to have that be the new location. Why is it flickering, and how can I achieve a simple drag and follow?
html
<div style="height:500px; width:500px; background-color:#ccc;">
<div id="custom-front" style="width:100%; height:100%;">
<div id="custom-content" style="z-index:200; position:absolute; text-align:center; background-color:red; width:50px; height:50px;">
</div>
</div>
js
window.onload = addListeners();
function addListeners(){
document.getElementById('custom-content').addEventListener('mousedown', mouseDown, false);
window.addEventListener('mouseup', mouseUp, false);
}
function mouseUp()
{
window.removeEventListener('mousemove', divMove, true);
}
function mouseDown(e){
window.addEventListener('mousemove', divMove, true);
}
function divMove(e){
document.getElementById('custom-content').style.top = e.offsetY + 'px';
document.getElementById('custom-content').style.left = e.offsetX + 'px';
}
https://jsfiddle.net/703kc43a/1/
i have just changed your javascript code, may be this help you, check this....
interact('.draggable')
.draggable({
// enable inertial throwing
inertia: true,
// keep the element within the area of it's parent
restrict: {
restriction: "parent",
endOnly: true,
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},
// call this function on every dragmove event
onmove: dragMoveListener,
// call this function on every dragend event
onend: function (event) {
var textEl = event.target.querySelector('p');
textEl && (textEl.textContent =
'moved a distance of '
+ (Math.sqrt(event.dx * event.dx +
event.dy * event.dy)|0) + 'px');
}
});
function dragMoveListener (event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
// this is used later in the resizing demo
window.dragMoveListener = dragMoveListener;
<script src="http://code.interactjs.io/interact-1.2.4.min.js"></script>
<div style="height:500px; width:500px; background-color:#ccc;">
<div id="custom-front" style="width:100%; height:100%;">
<div id="custom-content" class="draggable" style="z-index:5; position:absolute; text-align:center; background-color:red; width:50px; height:50px;">
</div>
</div>
</div>
Related
my dragitem initially appears in the upper left. I want to give a space of 100 pixels from the top and left at the opening. but I have to do this with interactjs own code, not css. because if i do it with css the scroll setting is broken
interact('.dragitem')
.draggable({
inertia: true,
modifiers: [
interact.modifiers.restrictRect({
restriction: 'parent',
endOnly: true
})
],
autoScroll: true,
listeners: {
move: dragMoveListener
}
})
function dragMoveListener (event) {
var target = event.target
var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy
target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
target.setAttribute('data-x', x)
target.setAttribute('data-y', y)
}
window.dragMoveListener = dragMoveListener
.drag-container {
width:1000px;
height:1000px;
background:red;
}
.dragitem {
width:100px;
height:100px;
background:blue;
}
<script src="https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js"></script>
<div class="drag-container">
<div class="dragitem">drag me</div>
</div>
You have to edit the starting position in style, data-x and data-y directly in HTML
<div class="dragitem" style="transform: translate(100px, 100px);" data-x="100" data-y="100">drag me</div>
interact('.dragitem')
.draggable({
inertia: true,
modifiers: [
interact.modifiers.restrictRect({
restriction: 'parent',
endOnly: true
})
],
autoScroll: true,
listeners: {
move: dragMoveListener
}
})
function dragMoveListener (event) {
var target = event.target
var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx
var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy
target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
target.setAttribute('data-x', x)
target.setAttribute('data-y', y)
}
window.dragMoveListener = dragMoveListener
.drag-container {
width:1000px;
height:1000px;
background:red;
}
.dragitem {
width:100px;
height:100px;
background:blue;
}
<script src="https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js"></script>
<div class="drag-container">
<div class="dragitem" style="transform: translate(100px, 100px);" data-x="100" data-y="100">drag me</div>
</div>
I have a div which I want to resize from all sides and corners, i.e. nw, n, ne, e, w, sw, s, se. I have tried jquery ui's resizable plugin but in my code that is not working. I have removed complexity from my code and placed it in a very basic fiddle.
I have tried to resize only north-west corner of a div and put that logic in fiddle. Logic seems correct to me but mouse interaction is working in a weird way.
Can you guys tell me what am I doing wrong here? If I get it correct for top left corner I can manage for the remaining ones. Thanks.
HTML:
<div id="box">
<div id="nw"></div>
<div id="n"></div>
<div id="ne"></div>
<div id="w"></div>
<div id="e"></div>
<div id="sw"></div>
<div id="s"></div>
<div id="se"></div>
</div>
<p class="one"></p>
<p class="two"></p>
CSS:
#box{border:1px solid #000;width:100px;height:100px;background-color:red;position:absolute;top:100px;left:100px}
#box > div{height:10px;width:10px;background-color:#000;position:absolute}
#nw{top:-5px;left:-5px;cursor:nw-resize}
#n{top:-5px;left:45px;cursor:n-resize}
#ne{top:-5px;right:-5px;cursor:ne-resize}
#w{top:45px;left:-5px;cursor:w-resize}
#e{top:45px;right:-5px;cursor:e-resize}
#sw{bottom:-5px;left:-5px;cursor:sw-resize}
#s{bottom:-5px;left:45px;cursor:s-resize}
#se{bottom:-5px;right:-5px;cursor:se-resize}
p{margin-top:250px;font-size:8px}
JS:
$(function(){
var mousepress = false;
$("#box > div").mousedown(function(e){
mousepress = true;
});
$("#box > div").mousemove(function(e){
if(mousepress) {
var boxX = $("#box").position().left;
var boxY = $("#box").position().top;
var boxW = $("#box").width();
var boxH = $("#box").height();
var x = boxX - e.pageX;//$(this).position().left;
var y = boxY - e.pageY;//$(this).position().top;
$("p.two").append("x: "+x+"<br />");
$(this).css({
"top":y+"px",
"left":x+"px"
});
$("#box").css({
"top":(boxY+y-5)+"px",
"left":(boxX+x-5)+"px",
"width":(boxW+x)+"px",
"height":(boxH+y)+"px",
});
}
});
$("#box > div").mouseup(function(){
mousepress = false;
});
});
**JSFIDDLE: **http://jsfiddle.net/ashwyn/v8qoLj76/2/
I didn't quite understand how you calculated the size and position of the box, without knowing which of the inside divs the user pressed.
I have changed it to use the mouse event position.
I also moved the mousemove and mouseup events to the document, because when dragging using the mouse, it may move faster then the DOM and got out of the box.
I also changed positions of inside divs to use 50% so it will always be in the middle. You may need to add a bit of margin to have it better centered. (See north vs south - I added margin-left to one of them)
This works fine for me.
http://jsfiddle.net/v8qoLj76/4/
var prev_x = -1;
var prev_y = -1;
var dir = null;
$("#box > div").mousedown(function(e){
prev_x = e.clientX;
prev_y = e.clientY;
dir = $(this).attr('id');
});
$(document).mousemove(function(e){
if (prev_x == -1)
return;
var boxX = $("#box").position().left;
var boxY = $("#box").position().top;
var boxW = $("#box").width();
var boxH = $("#box").height();
var dx = e.clientX - prev_x;
var dy = e.clientY - prev_y;
//Check directions
if (dir.indexOf('n') > -1) //north
{
boxY += dy;
boxH -= dy;
}
if (dir.indexOf('s') > -1) //south
{
boxH += dy;
}
if (dir.indexOf('w') > -1) //west
{
boxX += dx;
boxW -= dx;
}
if (dir.indexOf('e') > -1) //east
{
boxW += dx;
}
$("#box").css({
"top":(boxY)+"px",
"left":(boxX)+"px",
"width":(boxW)+"px",
"height":(boxH)+"px",
});
prev_x = e.clientX;
prev_y = e.clientY;
});
$(document).mouseup(function(){
prev_x = -1;
prev_y = -1;
});
Is it something that you need (see the snippet below)?
$(function() {
var ORIGINAL_TOP = 100, ORIGINAL_LEFT = 100, ORIGINAL_WIDTH = 100, ORIGINAL_HEIGHT = 100, OFFSET = 5;
$('.top').css({top: (ORIGINAL_TOP - OFFSET) + 'px'});
$('.left').css({left: (ORIGINAL_LEFT - OFFSET) + 'px'});
$('.bottom').css({top: (ORIGINAL_TOP + ORIGINAL_HEIGHT - OFFSET) + 'px'});
$('.right').css({left: (ORIGINAL_LEFT + ORIGINAL_WIDTH - OFFSET) + 'px'});
$('.control-element').css({height: (2 * OFFSET) + 'px', width: (2 * OFFSET) + 'px'});
var moveMiddleControls = function(top, left, width, height) {
['top', 'bottom'].forEach(function(coordinate) {
$('#' + coordinate).css({left: (left + width / 2 - OFFSET) + 'px'});
});
['left', 'right'].forEach(function(coordinate) {
$('#' + coordinate).css({top: (top + height / 2 - OFFSET) + 'px'});
});
};
var resizeBox = function(top, left, width, height) {
$('#box').css({
top: top + 'px',
left: left + 'px',
width: width + 'px',
height: height + 'px'
});
};
var updateStatus = function(top, left, width, height) {
$('#status-top').html(Math.round(top));
$('#status-left').html(Math.round(left));
$('#status-width').html(Math.round(width));
$('#status-height').html(Math.round(height));
};
var updatePosition = function(top, left, width, height) {
resizeBox(top, left, width, height);
moveMiddleControls(top, left, width, height);
updateStatus(top, left, width, height);
};
var update = function() {
updatePosition(
$('#top').position().top + OFFSET,
$('#left').position().left + OFFSET,
$('#right').position().left - $('#left').position().left,
$('#bottom').position().top - $('#top').position().top
);
};
update();
var activeElement;
$('.control-element').mousedown(function(e) {
activeElement = this;
e.preventDefault();
return false;
});
$(document).mousemove(function(e) {
if(activeElement !== undefined) {
['top', 'bottom'].forEach(function(className) {
if($(activeElement).hasClass(className)) {
$('.' + className).css({top: e.pageY + 'px'});
}
});
['left', 'right'].forEach(function(className) {
if($(activeElement).hasClass(className)) {
$('.' + className).css({left: e.pageX + 'px'});
}
});
update();
}
});
$(document).mouseup(function() {
activeElement = undefined;
});
});
#box {
border:1px solid #000;
background-color:red;
position: fixed;
}
.control-element {
background-color: #000;
position: fixed;
}
#top-left {
cursor: nw-resize;
}
#top {
cursor:n-resize;
}
#top-right {
cursor:ne-resize;
}
#left {
cursor:w-resize;
}
#right {
cursor:e-resize;
}
#bottom-left {
cursor:sw-resize;
}
#bottom {
cursor:s-resize;
}
#bottom-right {
cursor: se-resize;
}
.status {
position:fixed;
right: 5px;
bottom: 10px;
width: 80px;
height: 80px;
z-index: 999;
font-size:8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="box"></div>
<div id="top-left" class="control-element top left"></div>
<div id="top" class="control-element top"></div>
<div id="top-right" class="control-element top right"></div>
<div id="right" class="control-element right"></div>
<div id="bottom-right" class="control-element bottom right"></div>
<div id="bottom" class="control-element bottom"></div>
<div id="bottom-left" class="control-element bottom left"></div>
<div id="left" class="control-element left"></div>
<div class="status">
<div>top: <span id="status-top"></span>px</div>
<div>left: <span id="status-left"></span>px</div>
<div>width: <span id="status-width"></span>px</div>
<div>height: <span id="status-height"></span>px</div>
</div>
I'm have trouble with cloning an object using interact.js. I can do drag and drop, but there is no way to get clone from the objects.
I put here drag and drop code. Can someone modify it to clone objects?
#drag-1, #drag-2 {
width: 20%;
height: 10%;
min-height: 6.5em;
margin: 10%;
background-color: #29e;
color: white;
border-radius: 0.75em;
padding: 4%;
-webkit-transform: translate(0px, 0px);
transform: translate(0px, 0px);
}
#drag-me::before {
content: "#" attr(id);
font-weight: bold;
}
top:35px; left:40px; width:50px; height:50px;
z-index:99; background-color:#44ebfa;
}
<html>
<head>
<title>test 1 </title>
<!--<script type="text/javascript" src="d3-js/d3.min.js"></script>-->
<script type="text/javascript" src="www.googledrive.com/host/0B4A7r4wXVSe-SDdVdlNtbnhFZ2s"></script>
<link rel="stylesheet" type="text/css" href="test1_css1.css">
</head>
<body>
<script>
// target elements with the "draggable" class
interact('.draggable')
.draggable({
// enable inertial throwing
inertia: true,
// keep the element within the area of it's parent
restrict: {
restriction: "parent",
endOnly: true,
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},
// call this function on every dragmove event
onmove: dragMoveListener,
// call this function on every dragend event
onend: function (event) {
var textEl = event.target.querySelector('p');
textEl && (textEl.textContent =
'moved a distance of '
+ (Math.sqrt(event.dx * event.dx +
event.dy * event.dy)|0) + 'px');
}
});
function dragMoveListener (event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
// this is used later in the resizing demo
window.dragMoveListener = dragMoveListener;
</script>
<div id="drag-1" class="draggable">
<p> You can drag one element </p>
</div>
<div id="drag-2" class="draggable">
<p> with each pointer </p>
</div>
</body>
</html>
Try this code sample
interact('.draggable').draggable({
inertia: true,
restrict: {
restriction: "#visualizer-panel",
endOnly: true,
elementRect: { top: 0, left: 0, bottom: 1, right: 1 }
},
onmove: function (event) {
var target = event.target;
var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.webkitTransform =
target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
},
onend: function(event) {
console.log(event);
}
}).on('move', function (event) {
var interaction = event.interaction;
if (interaction.pointerIsDown && !interaction.interacting() && event.currentTarget.getAttribute('clonable') != 'false') {
var original = event.currentTarget;
var clone = event.currentTarget.cloneNode(true);
var x = clone.offsetLeft;
var y = clone.offsetTop;
clone.setAttribute('clonable','false');
clone.style.position = "absolute";
clone.style.left = original.offsetLeft+"px";
clone.style.top = original.offsetTop+"px";
original.parentElement.appendChild(clone);
interaction.start({ name: 'drag' },event.interactable,clone);
}
});
I want to append div based on dragend event coordinates. This is what I have tried:
$(document).ready(function () {
var mouseX;
var mouseY;
$(document).mousemove(function (e) {
mouseX = e.pageX;
mouseY = e.pageY;
});
var i =1;
$(".ic_table").on("dragend", function (e, ui)
{
console.log(mouseX + " " + mouseY);
var editName = "Edit Name";
$('#datamodelArea').append('<div id="divDT' + i++ + '" class="dataModelTable ui-draggable ui-draggable-handle style="left:' + mouseX + 'px' + '; top:' + mouseY + 'px' + ';"><div class="dataTableName">' + editName + '</div><div class="widget"><div class="widget-head"> <i></i> Attributes <div class="widget-body attributesBody" id="widget-body1"></div></div></div><div class="widget-body attributesBody" id="widget-body1"><ul></ul></div></div>');
$('.form-control').val('');
});
});
Html:
<body>
<div id="datamodelArea"></div>
<button class="ic_table" draggable="true">Submit</button>
</body>
Its appending only to top:0px and left:0px even though the mouse coordinates are different on dragend
Set your position properties explicitly to relative for the container and absolute for the dropped.
I'm trying to create my own click and drag function in JavaScript without the use of jquery. I know that jquery is easy to implement, but I prefer my own code. What I have, as i click the div, then move the mouse, the div moves to the same spot and doesn't implement a "dragging" look to it. I'm not sure why this is. I want my outcome to be able to move the div over the image that way I can "crop" the image based on the div, etc. My code is:
index.js
function _(element) {
return document.getElementById(element);
}
index.css
body {
background-color: rgb(33, 66, 99);
margin: 0px;
padding: 0px;
}
img {
position:absolute;
}
.selection {
width: 200px;
height: 200px;
background-color: rgb(255,255,255);
position: absolute;
}
index.php
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8"/>
<title>Image Cropping</title>
<link rel = "stylesheet" href = "index.css"/>
<script src = "index.js"></script>
</head>
<body>
<div class = "image">
<img src = "model.jpg" alt = "Model" id = "theImage"/>
<div class = "selection" id = "selection"/>
</div>
<script>
_("theImage").ondragstart = function() { return false; };
var m = _("selection");
m.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mouseup", mouseUp, false);
function mouseUp() {
window.removeEventListener("mousemove", move, true);
}
function mouseDown(e) {
window.addEventListener("mousemove", move, true);
}
function move(e) {
var x = m.style.left;
var y = m.style.top;
var mouseX = e.clientX;
var mouseY = e.clientY;
m.style.top += (mouseX - x) + "px";
m.style.left += (mouseY - y) + "px";
// Also tried: m.style.top = (mouseX - x) + "px";
// And : m.style.left = (mouseY - y) + "px";
}
</script>
</body>
</html>
To add the "dragging look to it", you can:
change the cursor (cursor: move;)
keep the cursor's offset relative to the mouse
For the second one, I reused a function I created for one of my projects, for which I implemented drag and drop for mobile, not wanting to use a big library:
/*
* Returns the given element's offset relative to the document.
*/
function realOffset(elem) {
var top = 0, left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop, 10);
left = left + parseInt(elem.offsetLeft, 10);
elem = elem.offsetParent;
}
return { top: top, left: left };
}
Using this function, the math becomes simple:
m.style.left = (mouseX - offset.left) + "px";
m.style.top = (mouseY - offset.top) + "px";
Full demo
_("theImage").ondragstart = function () { return false; };
var m = _("selection"), offset;
m.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mouseup", mouseUp, false);
function mouseUp() { window.removeEventListener("mousemove", move, true); }
function mouseDown(e) {
// SAVE THE OFFSET HERE
offset = {
left: e.pageX - realOffset(m).left,
top: e.pageY - realOffset(m).top
};
window.addEventListener("mousemove", move, true);
}
function move(e) {
// REUSE THE OFFSET HERE
m.style.left = (e.pageX - offset.left) + "px";
m.style.top = (e.pageY - offset.top) + "px";
}
/*
* Returns the given element's offset relative to the document.
*/
function realOffset(elem) {
var top = 0, left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop, 10);
left = left + parseInt(elem.offsetLeft, 10);
elem = elem.offsetParent;
}
return { top: top, left: left };
}
function _(element) { return document.getElementById(element); }
body {
background-color: rgb(33, 66, 99);
margin: 0px;
padding: 0px;
}
img {
position:absolute;
}
.selection {
width: 200px;
height: 200px;
background-color: rgba(255,255,255,.5);
position: absolute;
cursor: move;
}
<div class="image">
<img src="http://i.imgur.com/vxkljMP.jpg" alt="Model" id="theImage" />
<div class="selection" id="selection"></div>
</div>