Basically what I want to achieve is to drag some div within another container div. Inner div should stop when it reaches the boundaries of the container div. I managed to do the most parts. But the problem is that if I drag inner div slowly & carefully it stops where it is supposed to be on the edges, however if I drag it faster, it sometimes overflow the edges or stops way before the edges. What is the problem here? What should I do to fix this?
Here is full code
function mouseMove(e) {
e.preventDefault();
console.log("mouse moving");
if(isMouseDown > 0 && currentElement) {
mouseX = e.clientX;
mouseY = e.clientY;
var diffX = mouseX - lastMouseX;
var diffY = mouseY - lastMouseY;
if(diffX + lastElementX + elementWidth < rightLimit && diffX + lastElementX > leftLimit) {
lastElementX += diffX;
lastMouseX = mouseX;
}
if(diffY + lastElementY + elementHeight < bottomLimit && diffY + lastElementY > topLimit) {
lastElementY += diffY;
lastMouseY = mouseY;
}
setCurrentElementPosition(lastElementX, lastElementY);
}
}
Above code runs on mouse move event changing inner div's position.
Here's my solution for you, I've programmed video games before, and you run into this problem a lot.
You're checking if it'll go out, but not doing anything if it does! If it goes outside, you have to set it to the edge.
https://jsfiddle.net/7btv7oqy/3/
var lastElementX = 0; //last X position of element
var lastElementY = 0; //last Y position of element
var lastMouseX = 0; //last X position of mouse
var lastMouseY = 0;//last Y position of mouse
var mouseX = 0; //current mouse position X
var mouseY = 0; //current mouse position Y
var currentElement = null; //currently selected div
var elementWidth = 0;
var elementHeight = 0;
var container = null; //container div
var isMouseDown = 0; //if greater than zero, mouse is down
//limits of container div
var bottomLimit = 0;
var topLimit = 0;
var leftLimit = 0;
var rightLimit = 0;
function init() {
container = document.getElementsByClassName("container")[0];
topLimit = container.getBoundingClientRect().top;
bottomLimit = container.getBoundingClientRect().bottom;
leftLimit = container.getBoundingClientRect().left;
rightLimit = container.getBoundingClientRect().right;
document.addEventListener("mousedown", function mouseDown(e) {
e.preventDefault();
++isMouseDown;
document.addEventListener("mousemove", mouseMove);
setCurrentElement(getElementUnderMouse(e)); //set current element
currentElement.style.position = "absolute";
lastElementX = currentElement.getBoundingClientRect().left;
lastElementY = currentElement.getBoundingClientRect().top;
lastMouseX = e.clientX;
lastMouseY = e.clientY;
});
document.addEventListener("mouseup", function mouseUp(e) {
e.preventDefault();
--isMouseDown;
setCurrentElement(null);
document.removeEventListener("mousemove", mouseMove);
});
}
function mouseMove(e) {
e.preventDefault();
console.log("mouse moving");
// report(e);
if(isMouseDown > 0 && currentElement) {
mouseX = e.clientX;
mouseY = e.clientY;
var diffX = mouseX - lastMouseX;
var diffY = mouseY - lastMouseY;
if(diffX + lastElementX + elementWidth < rightLimit && diffX + lastElementX > leftLimit) {
lastElementX += diffX;
} else {
//without this, the location wouldn't update at all:
//check if it would go off the right edge, set to right edge
if (diffX + lastElementX + elementWidth >= rightLimit) {
lastElementX = rightLimit - elementWidth;
}
//check if it would go off the left edge, set to left edge
if(diffX + lastElementX <= leftLimit) {
lastElementX = leftLimit;
}
}
//this will always happen:
lastMouseX = mouseX;
if(diffY + lastElementY + elementHeight < bottomLimit && diffY + lastElementY > topLimit) {
lastElementY += diffY;
} else {
//without this, the location wouldn't update at all:
//check if it would go off the bottom edge, set to bottom edge
if(diffY + lastElementY + elementHeight >= bottomLimit) {
lastElementY = bottomLimit - elementHeight;
}
//check if it would go off the top edge, set to top edge
if(diffY + lastElementY <= topLimit) {
lastElementY = topLimit;
}
}
//this will always happen:
lastMouseY = mouseY;
setCurrentElementPosition(lastElementX, lastElementY);
}
}
function setCurrentElementPosition(left = null, top = null) {
if(currentElement) {
currentElement.style.top = top + 'px'
currentElement.style.left = left + 'px';
}
}
function setCurrentElement(element) {
currentElement = element;
if(element) {
elementWidth = currentElement.offsetWidth;
elementHeight = currentElement.offsetHeight;
} else {
elementWidth = 0;
elementHeight = 0;
}
}
function hasClass(element, cls) {
return ("" + element.className + "").indexOf("" + cls + "") > -1;
}
function getElementUnderMouse(e) {
var x = e.clientX;
var y = e.clientY;
return document.elementFromPoint(x, y);
}
function report(e) {
console.log("isMouseDown: " + isMouseDown);
console.log("mouseX: " + e.clientX);
console.log("mouseY: " + e.clientY);
console.log("currentElement: " + currentElement);
console.log("currentElement top: " + currentElement.getBoundingClientRect().top);
console.log("currentElement bottom: " + currentElement.getBoundingClientRect().bottom);
console.log("container top: " + container.getBoundingClientRect().top);
console.log("container bottom: " + container.getBoundingClientRect().bottom);
}
init();
EDIT: Not sure why it's missing by one pixel at the right and bottom, you'll have to do some investigation on that front. Seems like it's not taking into consideration the border, despite you using offsetWidth. Good luck!
Here's my take; I've decoupled the element's movement from diffX/diffY:
https://jsfiddle.net/ttyrtjez/
// in onmousedown
offsetX = e.clientX - lastElementX;
offsetY = e.clientY - lastElementY;
// in onmousemove
var newElementX = mouseX - offsetX;
var newElementY = mouseY - offsetY;
if (newElementX + elementWidth >= rightLimit - 1) newElementX = rightLimit - elementWidth - 2;
if (newElementX < leftLimit) newElementX = leftLimit;
if (newElementY + elementHeight >= bottomLimit - 1) newElementY = bottomLimit - elementHeight - 2;
if (newElementY < topLimit) newElementY = topLimit;
setCurrentElementPosition(newElementX, newElementY);
Related
I have written the code but it's for drawing a rectangle, i need to draw triangle shape by dragging the mouse while onClick, like in windows paint App. how to drag the mouse so that triangle forms automatically?
initDraw(document.getElementById('canvas'));
function initDraw(canvas) {
var mouse = {
x: 0,
y: 0,
startX: 0,
startY: 0
};
function setMousePosition(e) { // setting the postion for mouse
var ev = e || window.event;
if (ev.pageX) {
mouse.x = ev.pageX + window.pageXOffset;
mouse.y = ev.pageY + window.pageYOffset;
} else if (ev.clientX) {
mouse.x = ev.clientX + document.body.scrollLeft;
mouse.z = ev.clientZ + document.body.scrollLeft;
} };
var element = null;
canvas.onmousemove = function (e) {// on move
setMousePosition(e);
if (element !== null) {
element.style.width = Math.abs(mouse.x - mouse.startX) + 'px';
element.style.height = Math.abs(mouse.y - mouse.startY) + 'px';
element.style.left = (mouse.x - mouse.startX < 0) ? mouse.x + 'px' : mouse.startX + 'px';
element.style.top = (mouse.y - mouse.startY < 0) ? mouse.y + 'px' : mouse.startY + 'px';
}}};
canvas.onclick = function (e) {// on click function
if (element !== null) {
element = null;
canvas.style.cursor = "default";
console.log("finsihed.");
} else {
console.log("begun.");
mouse.startX = mouse.x;
mouse.startY = mouse.y;
element = document.createElement('div');
element.className = 'triangle'
element.style.left = mouse.x + 'px';
element.style.top = mouse.y + 'px';
canvas.appendChild(element)
canvas.style.cursor = "crosshair";
}}}
I want to add 4 text boxes which will give me the coordinates of a rectangle and if I manually edit the coordinates it should change /alter the rectangle as well.
Please tell me how to proceed with this solution.
In my example if you click ROI it will draw a rectangle I want the upper and lower X and Y coordinates of the same.
the working fiddle is http://jsfiddle.net/qf6Ub/2/
// references to canvas and context
var oImageBuffer = document.createElement('img');
var oCanvas = document.getElementById("SetupImageCanvas");
var o2DContext = oCanvas.getContext("2d");
// set default context states
o2DContext.lineWidth = 1;
o2DContext.translate(0.50, 0.50); // anti-aliasing trick for sharper lines
// vars to save user drawings
var layers = [];
var currentColor = "black";
// vars for dragging
var bDragging = false;
var startX, startY;
// vars for user-selected status
var $roiCheckbox = document.getElementById("btnROI");
var $layersCheckbox = document.getElementById("btnLAYER");
var $patches = document.getElementById('txtPatchCount');
var $mouse = document.getElementById("MouseCoords");
var roiIsChecked = false;
var layersIsChecked = false;
var patchCount = 0;
// listen for mouse events
oCanvas.addEventListener('mousedown', MouseDownEvent, false);
oCanvas.addEventListener('mouseup', MouseUpEvent, false);
oCanvas.addEventListener('mousemove', MouseMoveEvent, false);
oCanvas.addEventListener('mouseout', MouseOutEvent, false);
$("#txtPatchCount").keyup(function () {
getStatus();
// clear the canvas
o2DContext.clearRect(0, 0, oCanvas.width, oCanvas.height);
// redraw all previously saved line-pairs and roi
for (var i = 0; i < layers.length; i++) {
var layer = layers[i];
if (layer.patchCount > 0) {
layer.patchCount = patchCount;
}
draw(layer);
}
});
// mouse event handlers
function MouseDownEvent(e) {
e.preventDefault();
startX = e.clientX - this.offsetLeft;
startY = e.clientY - this.offsetTop;
currentColor = randomColor();
getStatus();
bDragging = true;
}
function MouseUpEvent(e) {
if (!bDragging) {
return;
}
e.preventDefault();
bDragging = false;
mouseX = e.clientX - this.offsetLeft;
mouseY = e.clientY - this.offsetTop;
layers.push({
x1: startX,
y1: startY,
x2: mouseX,
y2: mouseY,
color: currentColor,
drawLayer: layersIsChecked,
patchCount: patchCount,
});
}
function MouseOutEvent(e) {
MouseUpEvent(e);
}
function MouseMoveEvent(e) {
if (!bDragging) {
return;
}
var mouseX = e.clientX - this.offsetLeft;
var mouseY = e.clientY - this.offsetTop;
// clear the canvas
o2DContext.clearRect(0, 0, oCanvas.width, oCanvas.height);
// redraw all previously saved line-pairs and roi
for (var i = 0; i < layers.length; i++) {
draw(layers[i]);
}
// create a temporary layer+roi object
var tempLayer = {
x1: startX,
y1: startY,
x2: mouseX,
y2: mouseY,
color: currentColor,
drawLayer: layersIsChecked,
patchCount: patchCount,
};
// draw the temporary layer+roi object
draw(tempLayer);
// Display the current mouse coordinates.
$mouse.innerHTML = "(" + mouseX + "," + mouseY + ")" + patchCount;
}
function draw(layer) {
if (layer.drawLayer) {
// set context state
o2DContext.lineWidth = 0.50;
o2DContext.strokeStyle = layer.color;
// draw parallel lines
hline(layer.y1);
hline(layer.y2);
}
if (layer.patchCount > 0) {
// set context state
o2DContext.lineWidth = 1.5;
o2DContext.strokeStyle = '#0F0';
// draw regions
o2DContext.strokeRect(layer.x1, layer.y1, (layer.x2 - layer.x1), (layer.y2 - layer.y1));
var w = layer.x2 - layer.x1;
o2DContext.beginPath();
for (var i = 1; i < layer.patchCount; i++) {
var x = layer.x1 + i * w / layer.patchCount;
o2DContext.moveTo(x, layer.y1);
o2DContext.lineTo(x, layer.y2);
}
o2DContext.stroke();
}
}
function getStatus() {
roiIsChecked = $roiCheckbox.checked;
layersIsChecked = $layersCheckbox.checked;
patchCount = $patches.value;
if (!roiIsChecked || !patchCount) {
patchCount = 0;
}
}
function randomColor() {
return ('#' + Math.floor(Math.random() * 16777215).toString(16));
}
function hline(y) {
o2DContext.beginPath();
o2DContext.moveTo(0, y);
o2DContext.lineTo(oCanvas.width, y);
o2DContext.stroke();
}
document.getElementById("MouseCoords").innerHTML = "(" + x + "," + y + "); "
+"("+ oPixel.x + "," + oPixel.y + "); "
+"("+ oCanvasRect.left + "," + oCanvasRect.top + ")";
}
Ok, I went back to the drawing board and came up with this FIDDLE.
It provides the dimensions of the div and its location from the top and left of the container.
You can calculate the exact coordinates from those numbers.
JS
var divwidth = $('.coord').width();
var divheight = $('.coord').height();
var pos = $('.coord').offset();
$('#divdimensions').html(divwidth + ',' + divheight);
$('#divposition').html( pos.left + ',' + pos.top );
I've been searching for a script that creates a cursor text trail moving in a circular motion for quite a while. I feel like such things were everywhere just five years ago on kitschy blog sites.
The only code(s) I've been able to find are authored by Tim Tilton,
with variations found
here and here
and repeated on a few other sites.
This code seems a bit heavy in that it separates and gives each character of the message it's own div and then use equations to place and move those divs around the cursor.
It's there another way to go about creating such a feature?
A bit of the heavy code here:
if (!window.addEventListener && !window.attachEvent || !document.createElement) return;
msg = msg.split('');
var n = msg.length - 1, a = Math.round(size * diameter * 0.208333), currStep = 20,
ymouse = a * circleY + 20, xmouse = a * circleX + 20, y = [], x = [], Y = [], X = [],
o = document.createElement('div'), oi = document.createElement('div'),
b = document.compatMode && document.compatMode != "BackCompat"? document.documentElement : document.body,
mouse = function(e){
e = e || window.event;
ymouse = !isNaN(e.pageY)? e.pageY : e.clientY; // y-position
xmouse = !isNaN(e.pageX)? e.pageX : e.clientX; // x-position
},
makecircle = function(){ // rotation/positioning
if(init.nopy){
o.style.top = (b || document.body).scrollTop + 'px';
o.style.left = (b || document.body).scrollLeft + 'px';
};
currStep -= rotation;
for (var d, i = n; i > -1; --i){ // makes the circle
d = document.getElementById('iemsg' + i).style;
d.top = Math.round(y[i] + a * Math.sin((currStep + i) / letter_spacing) * circleY - 15) + 'px';
d.left = Math.round(x[i] + a * Math.cos((currStep + i) / letter_spacing) * circleX) + 'px';
};
},
drag = function(){ // makes the resistance
y[0] = Y[0] += (ymouse - Y[0]) * speed;
x[0] = X[0] += (xmouse - 20 - X[0]) * speed;
for (var i = n; i > 0; --i){
y[i] = Y[i] += (y[i-1] - Y[i]) * speed;
x[i] = X[i] += (x[i-1] - X[i]) * speed;
};
makecircle();
},
init = function(){ // appends message divs, & sets initial values for positioning arrays
if(!isNaN(window.pageYOffset)){
ymouse += window.pageYOffset;
xmouse += window.pageXOffset;
} else init.nopy = true;
for (var d, i = n; i > -1; --i){
d = document.createElement('div'); d.id = 'iemsg' + i;
d.style.height = d.style.width = a + 'px';
d.appendChild(document.createTextNode(msg[i]));
oi.appendChild(d); y[i] = x[i] = Y[i] = X[i] = 0;
};
o.appendChild(oi); document.body.appendChild(o);
setInterval(drag, 25);
},
ascroll = function(){
ymouse += window.pageYOffset;
xmouse += window.pageXOffset;
window.removeEventListener('scroll', ascroll, false);
};
o.id = 'outerCircleText'; o.style.fontSize = size + 'px';
if (window.addEventListener){
window.addEventListener('load', init, false);
document.addEventListener('mouseover', mouse, false);
document.addEventListener('mousemove', mouse, false);
if (/Apple/.test(navigator.vendor))
window.addEventListener('scroll', ascroll, false);
}
else if (window.attachEvent){
window.attachEvent('onload', init);
document.attachEvent('onmousemove', mouse);
};
I have a sample code:
javascript:
function bootstrap(id) {
this.id = id;
this.init = function() {
document.getElementById(this.id).onmousemove = positionButton;
}
function positionButton(e) {
e = e || window.event;
var cursor = {x:0, y:0};
if (e.pageX || e.pageY) {
cursor.x = e.pageX;
cursor.y = e.pageY;
} else {
cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
cursor.y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
}
var elem = document.getElementById(this.id);
elem.style.position = 'absolute';
elem.style.top = cursor.y - 10 + 'px';
elem.style.left = cursor.x - 30 + 'px';
}
}
In html:
<div id="button" style="position: absolute; opacity: 1; z-index: 100; width:27px; height:20px; overflow:hidden">
test test
</div>
<script type="text/javascript" src="script.js"></script>
<script>
var bootstrap = new bootstrap('button');
bootstrap.init();
</script>
When I run code, result not run event mousemove, how to fix it?
The style of the button.
Your code:
width:27px;height:20px;
I change to
width:60px;height:50px;
I try it on IE9.It works.
Run this jsFiddle that I created with a slight modification of your code:
function bootstrap(id) {
this.id = id;
this.init = function() {
document.getElementById(this.id).onmousemove = positionButton;
};
function positionButton(e) {
e = e || window.event;
var cursor = {
x: 0,
y: 0
};
if (e.pageX || e.pageY) {
cursor.x = e.pageX;
cursor.y = e.pageY;
} else {
cursor.x = e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
cursor.y = e.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
}
var elem = document.getElementById(this.id);
elem.style.position = 'absolute';
elem.style.top = cursor.y - 10 + 'px';
elem.style.left = cursor.x - 30 + 'px';
}
}
var bootstrap = new bootstrap('button');
bootstrap.init();
It works correctly with Chrome, Safari and FFX.
Have you any error in your browser console?
Is script.js correctly downloaded?
What browser are you using?
I'm trying to detect the distance the mouse has moved, in pixels. I am currently using:
$(document).mousemove(function(event) {
var startingTop = 10,
startingLeft = 22,
math = Math.abs(((startingTop - event.clientY) + (startingLeft - event.clientX)) + 14) + 'px';
$('span').text('From your starting point(22x10) you moved: ' + math);
});
However, I don't feel like this is the right way to do this, or is it? It doesn't feel to consistent to me.
Here is a demo of how it is working right now: http://jsfiddle.net/Em4Xu/1/
Extra Details:
I'm actually developing a drag & drop plugin and I want to create a feature called distance, like draggable has it, where you have to pull your mouse a certain amount of pixels before it drags. I'm not 100% sure how to do this, so first I need to get the pixels that the mouse has moved from the startingTop and startingLeft position.
Does anyone have any suggestions?
Here's a version that meters distance that mouse travels:
var totalDistance = 0;
var lastSeenAt = {x: null, y: null};
$(document).mousemove(function(event) {
if(lastSeenAt.x) {
totalDistance += Math.sqrt(Math.pow(lastSeenAt.y - event.clientY, 2) + Math.pow(lastSeenAt.x - event.clientX, 2));
$('span').text('So far your mouse ran this many pixels: ' + Math.round(totalDistance));
}
lastSeenAt.x = event.clientX;
lastSeenAt.y = event.clientY;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span></span>
You got your math wrong. Here's improved version: http://jsfiddle.net/stulentsev/Em4Xu/26/
$(document).mousemove(function(event) {
var startingTop = 10,
startingLeft = 22,
math = Math.round(Math.sqrt(Math.pow(startingTop - event.clientY, 2) +
Math.pow(startingLeft - event.clientX, 2))) + 'px';
$('span').text('From your starting point(22x10) you moved: ' + math);
});
Came up with the something similiar to Sergio, but this will calculate disatance from the point the mouse has been held down, and like jfriend said the distance between two points,
d = ( (x1-x2)^2 + (y1-y2)^2 )^(1/2)
var totalMovement = 0;
var lastX = -1;
var lastY = -1;
var startX = -1;
var startY = -1;
$(document).mousemove(function(event) {
if (startX == -1) {
return;
}
if (startY == -1) {
return;
}
totalMovement += Math.sqrt(Math.pow(lastY - event.clientY, 2) + Math.pow(lastX - event.clientX, 2));
$('span').text('From your starting point (' + startX + 'x' + startY + ') you moved: ' + totalMovement);
lastX = event.clientX;
lastY = event.clientY;
});
$(document).mousedown(function(event) {
startX = event.clientX;
startY = event.clientY;
lastX = event.clientX;
lastY = event.clientY;
});
$(document).mouseup(function(event) {
startX = -1;
startY = -1;
totalMovement = 0;
lastX = 0;
lastY = 0;
});