When the content goes outside the div, we use scrollbars to see it. How can I scroll the div content by grabbing and dragging its background? I've searched the solution but did not find what I need. Here is my fiddle:
https://jsfiddle.net/vaxobasilidze/xhn49e1j/
Drag any item to the right div and move it outside the container to the right or bottom. scrollbars appear to help you to scroll. Here is an example of what I want to achieve. See the first diagram on the link and drag it:
https://jsplumbtoolkit.com/
Any tips on how to do this?
You should just need to detect when the mouse is down and then when the mouse is moving afterwards you can store the previous mouse coordinates and reference the current coordinates. Finally you can scroll the div in question by an amount based on the difference in drag since the last mousemove call.
var mouseDown = false;
var prevCoords = { x: 0, y: 0 };
$("#mainDiv").mousedown(function() {
mouseDown = true;
}).mousemove(function(e) {
var currentScrollX = $('#mainDiv').scrollLeft();
var currentScrollY = $('#mainDiv').scrollTop();
if(mouseDown) {
$('#mainDiv').scrollLeft(currentScrollX + prevCoords.x - (e.clientX + currentScrollX))
$('#mainDiv').scrollTop(currentScrollY + prevCoords.y - e.clientY)
};
prevCoords.x = e.clientX + currentScrollX;
prevCoords.y = e.clientY;
}).mouseup(function() {
mouseDown = false;
});
https://jsfiddle.net/6rx30muh/
EDIT: Fixed bug with wiggling tables when dragging:
var mouseDown = false;
var prevCoords = { x: 0, y: 0 };
$("#mainDiv").mousedown(function() {
mouseDown = true;
}).mousemove(function(e) {
var currentScrollX = $('#mainDiv').scrollLeft();
var currentScrollY = $('#mainDiv').scrollTop();
if(mouseDown) {
$('#mainDiv').scrollLeft(currentScrollX + prevCoords.x - e.clientX)
$('#mainDiv').scrollTop(currentScrollY + prevCoords.y - e.clientY)
};
prevCoords.x = e.clientX;
prevCoords.y = e.clientY;
}).mouseup(function() {
mouseDown = false;
});
Check for mousemove between mousedown and mouseup on the body element is a good place to start.
element = $('body');
element.addEventListener("mousedown", function(){
flag = 0;
}, false);
element.addEventListener("mousemove", function(){
flag = 1;
}, false);
element.addEventListener("mouseup", function(){
if(flag === 0){
console.log("click");
}
else if(flag === 1){
console.log("drag");
}
}, false);
I have a rectangular div element on a page with image and text span inside.
Div has 2px border to make it actually visible.
Then I add dragstart event listener to my div element.
dragstart event fires always if I start dragging the image inside div but it is very problematic if I start dragging by clicking on text span or blank place:
In Google Chrome dragging is very unstable. It can work a few times then stops firing, then work again and so on.
In Mozilla Firefox it doesn't work at all.
How to fix it and allow drag by clicking on any point inside bound rect of my div?
<div class="item">
<img src="https://www.wigwam3d.com/previews/1f/1ffbf8da-a4d0-4e40-b9e1-0329220969dc.jpg">
<div>Element</div>
</div>
Plunker: http://plnkr.co/edit/673ytif50cViE5dTv3df?p=preview
Use this code , you can drag div anywhere on the window. Also fix width and height of the div.
$(function(){
$("#animation").css({"cursor":"move"})
// mousedown:fn(){dragging = true;}
var dragging = false;
var iX, iY;
$("#animation").mousedown(function(e) {
dragging = true;
iX = e.clientX - this.offsetLeft;
iY = e.clientY - this.offsetTop;
this.setCapture && this.setCapture();
return false;
});
// mouseover:fn(){dragging = tru;}
document.onmousemove = function(e) {
if (dragging) {
var e = e || window.event;
var oX = e.clientX - iX;
var oY = e.clientY - iY;
$("#animation").css({"left":oX + "px", "top":oY + "px"});
return false;
}
};
// mouseup:fn(){dragging = false;}
$('#animation').mouseup(function(e) {
dragging = false;
this.releaseCapture && this.releaseCapture();
e.cancelBubble = true;
})
})
Just found a simple solution: add attribute draggable=true on div element! That's all!
What I mean is that the user presses a mouse button at point xy on an HTML canvas and while the mouse button is pressed the rectangle can be resized according to the movement of the cursor with point xy fixed. Like how highlighting works.
This is what I've got so far but it doesn't seem to be working:
canvas.addEventListener('mousedown', function(e){
var rectx = e.clientX;
var recty = e.clientY;
canvas.onmousemove = function(e){
var df = e.clientX;
var fg = e.clientY;
};
context.rect(rectx, recty, df-rectx, fg-recty);
context.stroke();
}, false);
Assuming there are no transforms (scale, translate) on your canvas context.
Basic steps for having a resizable rectangle are as follows:
Create a mousedown listener that sets a flag indicating the use is holding down the mouse button, as well as sets the "anchor," or initial coordinates.
Create a mouseup listener that unsets the flag.
Create a mousemove listener that, if the flag indicates the mouse is down, redraws the canvas with the rectangle's size changed according to mouse coordinates.
An important note is that client coordinates in the event object are relative to the page, not to your canvas element. You will frequently need to convert clientX and clientY into canvas coordinates:
var getCanvasCoords = function (clientX, clientY) {
var rect = canvas.getBoundingClientRect();
return {
x: clientX - rect.left,
y: clientY - rect.top
};
};
The first two steps look something like this:
var anchorX;
var anchorY;
var mouseDown = false;
canvas.addEventListener('mousedown', function (event) {
var coords = getCanvasCoords(event.clientX, event.clientY);
anchorX = coords.x;
anchorY = coords.y;
mouseDown = true;
});
canvas.addEventListener('mouseup', function (event) {
mouseDown = false;
});
And the mousemove handler:
canvas.addEventListener('mousemove', function (event) {
var coords = getCanvasCoords(event.clientX, event.clientY);
var width = coords.x - anchorX;
var height = coords.y - anchorY;
// clear canvas for redrawing
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillRect(anchorX, anchorY, width, height);
});
Don't Render from mouse events!
The given answer is correct but it is not the best way to do this.
The are two reasons. First the mousemove event can fire up to 600+ times a second but the display only refreshes 60 times a second. Rendering from the input event is many time just a waste of CPU time as the results will be overwritten by the next mouse event before it is ever had a chance to be displayed.
The second reason is that dedicating an event listener to a single task makes it hard to add more functionality. You end up adding more and more code to the mousemove event to handle all the types of input, most of which can be ignored because of the high update speed of the mouse.
Mouse listeners
Mouse event listeners do the minimum possible. They just record the mouse state and no more. Also all mouse events return the mouse position. You should not ignore the mouse position for events like mouse down and up
The following function creates a mouse object for a element. The mouse object has the x,y position relative to the to left of the element, and the current button states for 3 buttons it is left to right button1, button2, button3.
Also when the mouse leaves the element and then releases the mouse button the mouse for the element will not see the mouseup event and not know the mouse button is up. To prevent the mouse buttons from getting stuck you turn off the buttons when the mouse leaves the element.
The best mouse listener is to the whole page as it can track mouse events that happen even when the mouse is outside the window/tab (if the window/tab has focus), but that is a little to complex for this answer.
Function to create a mouse for an element
function createMouse(element){
var mouse = {
x : 0,
y : 0,
button1 : false,
button2 : false,
button3 : false,
over : false,
};
function mouseEvent(event){
var bounds = element.getBoundingClientRect();
mouse.x = event.pageX - bounds.left - scrollX;
mouse.y = event.pageY - bounds.top - scrollY;
if(event.type === "mousedown"){
mouse["button"+event.which] = true;
} else if(event.type === "mouseup"){
mouse["button"+event.which] = false;
} else if(event.type === "mouseover"){
mouse.over = true;
} else if(event.type === "mouseout"){
mouse.over = false;
mouse.button1 = false; // turn of buttons to prevent them locking
mouse.button2 = false;
mouse.button3 = false;
}
event.preventDefault(); // stops default mouse behaviour.
}
var events = "mousemove,mousedown,mouseup,mouseout,mouseover".split(',');
events.forEach(eventType => element.addEventListener(eventType,mouseEvent));
mouse.remove = function(){
events.forEach(eventType => element.removeEventListener(eventType, mouseEvent));
}
return mouse;
}
Using the mouse
It is now just a matter of creating a mouse for the element
var canMouse = createMouse(canvas);
And then in your main render loop do the dragging.
var drag = {
x : 0,
y : 0,
x1 : 0,
y1 : 0,
dragging : false,
top : 0,
left : 0,
width : 0,
height : 0,
}
function mainLoop(){
if(canMouse.button1){ // is button down
if(!drag.dragging){ // is dragging
drag.x = canMouse.x;
drag.y = canMouse.y;
drag.dragging = true;
}
drag.x1 = canMouse.x;
drag.y1 = canMouse.y;
drag.top = Math.min(drag.y, drag.y1);
drag.left = Math.min(drag.x, drag.x1);
drag.width = Math.abs(drag.x - drag.x1);
drag.height = Math.abs(drag.y - drag.y1);
}else{
if(drag.dragging){
drag.dragging = false;
}
}
}
Putting it all together
function createMouse(element){
var mouse = {
x : 0,
y : 0,
button1 : false,
button2 : false,
button3 : false,
over : false,
};
function mouseEvent(event){
var bounds = element.getBoundingClientRect();
// NOTE getting the border should not be done like this as
// it will not work in all cases.
var border = Number(element.style.border.split("px")[0])
mouse.x = event.pageX - bounds.left - scrollX - border;
mouse.y = event.pageY - bounds.top - scrollY - border;
if(event.type === "mousedown"){
mouse["button"+event.which] = true;
} else if(event.type === "mouseup"){
mouse["button"+event.which] = false;
} else if(event.type === "mouseover"){
mouse.over = true;
} else if(event.type === "mouseout"){
mouse.over = false;
mouse.button1 = false; // turn of buttons to prevent them locking
mouse.button2 = false;
mouse.button3 = false;
}
event.preventDefault(); // stops default mouse behaviour.
}
var events = "mousemove,mousedown,mouseup,mouseout,mouseover".split(',');
events.forEach(eventType => element.addEventListener(eventType,mouseEvent));
mouse.remove = function(){
events.forEach(eventType => element.removeEventListener(eventType, mouseEvent));
}
return mouse;
}
var drag = {
x : 0,
y : 0,
x1 : 0,
y1 : 0,
dragging : false,
top : 0,
left : 0,
width : 0,
height : 0,
}
var ctx = canvas.getContext("2d");
ctx.strokeStyle = "black";
ctx.lineWidth = 1;
var mouse = createMouse(canvas);
function update(){
ctx.clearRect(0,0,canvas.width,canvas.height);
if(mouse.button1){ // is button down
if(!drag.dragging){ // is dragging
drag.x = mouse.x;
drag.y = mouse.y;
drag.dragging = true;
}
drag.x1 = mouse.x;
drag.y1 = mouse.y;
drag.top = Math.min(drag.y, drag.y1);
drag.left = Math.min(drag.x, drag.x1);
drag.width = Math.abs(drag.x - drag.x1);
drag.height = Math.abs(drag.y - drag.y1);
}else{
if(drag.dragging){
drag.dragging = false;
}
}
if(drag.dragging){
ctx.strokeRect(drag.left, drag.top, drag.width, drag.height);
}
requestAnimationFrame(update);
}
requestAnimationFrame(update);
canvas {
border : 1px solid black;
}
Click drag to draw rectangle.<br>
<canvas id="canvas" width= "512" height = "256"></canvas>
I'm playing a bit with AMI Medical Imaging (AMI) JS ToolKit. Is there a way to move the windowing to a mouse event like right click & move?
I know that it's possible to change window/level with the menus on the examples, but I would like to change the controller to do it moving the mouse.
Thanks!
To control the window/level by moving the mouse you will have to listen to the mousemouve event then update the stackHelper -> slice -> windowWidth/Center as you wish.
You could enable window/level if the user press shift:
var drag = {
x: null,
y: null
}
var shiftDown = false;
function onKeyPressed(event){
shiftDown = event.shiftKey;
if(!shiftDown){
drag.x = null;
drag.y = null;
}
}
container.addEventListener('keydown', onKeyPressed);
container.addEventListener('keyup', onKeyPressed);
Then update the window/level on mouse move:
function onMouseMove(event){
if(!shiftDown || !stack || !stackHelper){
return;
}
if(drag.x === null){
drag.x = event.offsetX;
drag.y = event.offsetY;
}
var threshold = 15;
var dynamicRange = stack.minMax[1] - stack.minMax[0];
dynamicRange /= container.clientWidth;
if(Math.abs(event.offsetX - drag.x) > threshold){
// window width
stackHelper.slice.windowWidth += dynamicRange * (event.offsetX - drag.x);
drag.x = event.offsetX;
}
if(Math.abs(event.offsetY - drag.y) > threshold){
// window center
stackHelper.slice.windowCenter -= dynamicRange * (event.offsetY - drag.y);
drag.y = event.offsetY;
}
}
container.addEventListener('mousemove', onMouseMove);
See a live demo at (shift + mouse move to control the window level):
http://jsfiddle.net/vabL3qo0/41/
As per the jQuery docs below code can be used to capture mouseup and mouse down events. But my requirement is bit different
$("#dic").mouseup(function () {
}).mousedown(function () {
});
But How can I calculate mouse moving co-ordinates between mousedown position to mouseup position. Please help me on this. How can I apply mousemove event between mousedown and mouseup
If you need to captue all points the mouse moves through during a drag, bind/unbind a new mousemove handler:
var allPoints = [];
$("#dic").mouseup(function (e) {
$(this).unbind("mousemove", trackPoints);
}).mousedown(function (e) {
$(this).bind("mousemove", trackPoints);
});
function trackPoints(e) {
allPoints.push({ x: e.pageX, y: e.pageY });
}
This way, trackPoints will start firing when the mouse is down and stop when it goes back up.
You may also want to add a if(e.which == 1) to the top of your mouseup and mousedown handlers so that they perform the bind for a left mouse button only, not middle or right buttons.
var X = [],
Y = [],
i = -1;
$("#dic").mouseup(function(e) {
++i;
X[i] = e.pageX;
Y[i] = e.pageY;
// reset everything on mouseup
X = [];
Y = [];
i = -1;
}).mousedown(function(e) {
++i;
X[i] = e.pageX;
Y[i] = e.pageY;
console.log(X);
}).mousemove(function(e) {
++i;
X[i] = e.pageX;
Y[i] = e.pageY;
});
DEMO
var x = [], y = [], i = 0;
$("#dic").mouseup(function (e) {
$('#status').html(e.pageX +', '+ e.pageY + ' up');
x[i] = e.pageX;
y[i++] = e.pageY;
console.log(x);
console.log(y);
});
$("#dic").mousedown(function (e) {
$('#status').html(e.pageX +', '+ e.pageY + ' down');
i = 0;
x[i] = e.pageX;
y[i++] = e.pageY;
});
$("#dic").mousemove(function (e) {
$('#status').html(e.pageX +', '+ e.pageY + ' move');
x[i] = e.pageX;
y[i++] = e.pageY;
});
This will begin recording mouse positions on mousedown and you can see the output on the console on mouseup. Then you can calculate the distance as thecodeparadox described with the first and last items of the arrays, or any other points in between the start and end.
Code on JSFiddle