I have a kinetic stage and some objects that each are draggable. (See fiddle for example.)
My goal is to allow the user to always be able to middle click to pan the entire stage whether or not he middle clicks on empty space or on any shape drawn to the stage. I need to do this in a way that doesn't break the drag events of existing shapes. Meaning I need the shape dragStart and dragEnd events to be processed normally, but only on left click drag.
I'm able to detect the middle click event on the stage and call dragStop() on the shape if the drag was initiated on one, but calling dragStop() means that the dragstop event is fired and processing occurs on the shape.
// let's pretend that a mouse doesn't have more than 9 buttons
var mouseDown = [0, 0, 0, 0, 0, 0, 0, 0, 0];
var mouseDownCount = 0;
document.body.onmousedown = function(evt) {
++mouseDown[evt.button];
++mouseDownCount;
}
document.body.onmouseup = function(evt) {
--mouseDown[evt.button];
--mouseDownCount;
}
stage.on('dragstart', function(e){
if(mouseDownCount){
if(mouseDown[0]){
// Left mouse button drag
if (e.target.nodeType == 'Stage'){
// stop the drag for left click
e.target.stopDrag();
}
} else if (mouseDown[1]){
// Middle mouse button drag
if (e.target.nodeType != 'Stage'){
// stop the drag of the object for left click
e.target.listening(false);
e.target.stopDrag();
e.target.listening(true);
// start the stage drag
e.target.getStage().startDrag()
}
}
}
});
Is there a way to cancel the dragStart event after it has been fired, or in some other way tell dragEnd to not fire? I've tried setting e.target.listening(false) prior to calling dragStop, but that doesn't seem to be working.
Any ideas?
Try to use latest version from GitHub. It has functionality only with left mouse button.
Related
I want to make a doodling application, drawing strokes when mouse is moving, in the mousemove event handler, below code works:
line(lastX, lastY, mouseX, mouseY);
lastX = mouseX;
lastY = mouseY;
However, when I wrap the codes into an if statement like:
if (mouseIsPressed) {
...
}
Nothing, if I move the codes into draw function and set that condition, it works. Why?
Thanks in advance.
From the mouseMoved() reference:
The mouseMoved() function is called every time the mouse moves and a mouse button is not pressed.
So the mouseMoved() function won't be called if you are pressing a mouse button. If you put some code into an if block like:
if (mouseIsPressed) {
...
}
and put that block into mouseMoved(), then that code will never be executed.
It's totally ok to put that if block directly in the draw() function. You don't have to use mouseMoved() in this case :)
I am implementing d3.js zoom behaviour on a svg, on the same svg I also need to capture mouse coordinate so I can set position of a tool tips that follow mouse cursor's position.
The problem is that my 'mousemove' event has override d3.js zoom behaviour.
With 'mousemove' event added, zoom behaviour stop working.
It is either I have 'mousemove' event or 'zoom' event, but not both. Any suggestion how to get around this? Thanks.
// bind zoom behavior
selection_svg.call(
d3.behavior.zoom()
.translate([0, 0])
.scale(1)
.scaleExtent([1, 14])
.on('zoom', ()=>{ selection_plotArea.attr('transform', 'translate('+d3.event.translate+')scale('+d3.event.scale+')'); })
);
// tool tip coordinate
const toolTipNode = selection_toolTip.node();
toolTipNode.style.position = 'absolute';
selection_svg.node().addEventListener('mousemove',function(evt){
const coord_client = {
x:evt.clientX,
y:evt.clientY,
}
toolTipNode.style.left = `${coord_client.x}px`;
toolTipNode.style.top = `${coord_client.y}px`;
}, false);
I have added the code for this problem to fiddle:
https://jsfiddle.net/apollotang/rt9t1vdj/
The problem seems to be related to tooltipNode catching mouse events. By adding some offset to coord_client your problem would be gone.
selection_svg.on('mousemove', function () {
const coord_client = {
x: d3.event.layerX + 10,
y: d3.event.layerY + 10
};
toolTipNode.style.left = `${coord_client.x}px`;
toolTipNode.style.top = `${coord_client.y}px`;
}, false);
Note: I also changed clientX and clientY to layerX and layerY since there was a bug when scrolling changed mouse position and tooltipNode would have been separated from mouse. Besides the event handling code changed to be handled by d3.
If you have a mousemove event attached to your svg, be sure you aren't calling d3.event.stopPropagation() within the mousemove event, or else you will prevent the zoom behavior.
I need something like GetKeyboardState() but for mouse. I do not need to handle an event when the mouse button pressed, just need to know if the buttons are up or down at some moment. This is for toy animation program.
if (GetAsyncKeyState(VK_LBUTTON) < 0)
{
// left button is down
}
if (GetAsyncKeyState(VK_RBUTTON) < 0)
{
// right button is down
}
I am working on a visualization project. Based on my data I am plotting hundreds of small circle on canvas. I want to add a mouse over event so that whenever a mouse is the enclosing area of a circle it will show some node property from my data as a tool tip or as text on the canvas.
My current drawCircle method
function drawCircle(canvas,x,y,r)
{
canvas.strokeStyle = "#000000";
canvas.fillStyle = "#FFFF00";
canvas.lineWidth = 2;
canvas.beginPath();
canvas.arc(x,y,r,0,Math.PI*2,true);
canvas.stroke();
canvas.fill();
canvas.closePath();
}
I have looked into kinetic.js
But can't figure it out how I can call my drawCircle [repetitively] method using their library.
Any help will be highly appreciated.
If you still want to use KineticJS, you would put the Kinetic shape stuff inside your drawCircle routine. This is basically pulled out of their tutorial and stripped down:
function drawCircle(stage,x,y,r) {
var circle = new Kinetic.Shape(function(){
var context = this.getContext();
// draw the circle here: strokeStyle, beginPath, arc, etc...
});
circle.addEventListener("mouseover", function(){
// do something
});
stage.add(circle);
}
If you don't want to use KineticJS after all, you will need to remember for yourself the positions and radii of every circle you drew, and then do something like this:
canvas.onmouseover = function onMouseover(e) {
var mx = e.clientX - canvas.clientLeft;
var my = e.clientY - canvas.clientTop;
// for each circle...
if ((mx-cx)*(mx-cx)+(my-cy)*(my-cy) < cr*cr)
// the mouse is over that circle
}
So here's what I want to do. I would like to be able to drag an element, and have it dynamically change it's default drag image to a different image when it's over the drop zone.
You are able to set the drag image using dataTransfer.setDragImage method. It exists in the event objects of all of the drag events, including the dragover event.
Some basic code would be:
dropElem.ondragover = function(e) {
if (e.stopPropagation) {
e.stopPropagation(); //Stops some browsers from redirecting.
}
var dragIcon = document.createElement('img');
dragIcon.src = 'image.png';
dragIcon.width = 100;
e.dataTransfer.setDragImage(dragIcon, 0, 0);
};