How to selectively pass mouse events to underlying svg elements - javascript

I have a scatterplot with a brush layer for zooming in the data and voronois for mouse hover snapping but the problem is that the voronoi paths don't let the click event fall through to brush layer or if keeping brush on top it doesn't allow hover event to fall through to voronoi layer
Brush layer needs click event
Voronoi layer needs hover event
How should I go about the setup, css only solutions preferable
keeping brush layer on top :
keeping voronoi layer on top :

I did this on voronoi hover keeping brush on bottom, but it flickers arround the edges
$("#visualization-main-container > svg > g.voronoiWrapper > path.voronoi-poly").css("pointer-events", "all");
setTimeout(function() {
$("#visualization-main-container > svg > g.voronoiWrapper > path.voronoi-poly.voronoi-movie-id-" + d.id).css("pointer-events", "none");
}, 10);
EDIT :
I finally end up using a hotkey "CTRL" to temporarily disable mouse events on voronoi layer when it is pressed down, it adds an extra step to the zoom process but it is much more smooth.

Related

Moving multiple objects simultaneously in createJS/easelJS

I've been using easelJS within the createJS framework for a project and have enjoyed it a lot until recently hitting a roadblock. I have multiple objects that I'd like to move simultaneously when one of the group is dragged. Here is my current situation:
What I'd like to do is when the red circle is moved, the red crosshairs would also move so that they appear to be "locked" to the circle. The same with the green circle.
I have been able to accomplish something very close to this by adding the circles and crosshairs to a container, as mentioned in the answers to this question:
Easeljs Scrollable Container
But the issue I encounter is that the container is actually a rectangle, such that I can click anywhere between the circle and crosshairs to move the various objects contained within the container. Instead I would like for the objects to be moved only when I click on a circle.
Does anyone have any idea how to accomplish this? Am I correct in thinking this can be accomplished somehow with easelJS containers?
Containers should be fine. You can turn off mouseEnabled on the cross-hair in order to make it ignore the mouse.
You could also just store the offset for each cross-hair/circle, and just set the cross-hair position when the circle moves.
Here is a quick demo:
http://jsfiddle.net/lannymcnie/kah9of6e/
// Set the offset when the circle is pressed
circle.on("mousedown", function(e) {
circle.offset = new createjs.Point(crosshair.x-circle.x, crosshair.y-circle.y);
});
// Add drag and drop to each shape
circle.on("pressmove", handleDrag);
crosshair.on("pressmove", handleDrag);
function handleDrag(e) {
// Move the target to the mouse
e.target.x = e.stageX; e.target.y = e.stageY;
// If the target is the circle, also move the cross-hair
if (e.target == circle) {
// Move the cross-hair
crosshair.x = circle.x + circle.offset.x;
x.y = circle.y + circle.offset.y;
}
}

d3 zoom with button and double click but don't zoom with with scroll wheel

I am using this example as a basis for zoom in my project but I would like to restrict the zoom to only the buttons and double clicking. Ideally, using the scroll wheel should just continue scrolling down the page and not zoom in on the svg when the mouse is over it. Any help is appreciated!
For D3 4.0, there're two ways to prevent d3 zoom from responding to wheel event.
A:
zoom.filter(function() { return !event.button && event.type !== 'wheel'; })
// the `!event.button` expression is from the default filter, according to
// doc for zoom.filter([filter])
B:
svg.on("wheel.zoom", null);
// according to doc for zoom(selection): Internally, the zoom behavior
// uses selection.on to bind the necessary event listeners for zooming.
// The listeners use the name .zoom
It's still possible to pan(translate) with mouse dragging.
You can achieve this by:
var svg = d3.select("body").select("svg")
.attr("width", width)
.attr("height", height)
.append("g")
//.call(zoom) //remove the zoom listener from the group.
.append("g");
Next attach doublclick listener on the circle and the rectangle for zooming.
d3.selectAll("rect").on('dblclick', zoomClick)
d3.selectAll("circle").on('dblclick', zoomClick)
working code here

Konva Propagate events between layers

I have a transparent drag layer on top of a shape layer. Works great to make interaction distinct so I can toggle what dragging does (between scrolling the view or editing the shape positions). However, unless I turn off drag mode (by hiding the intervening transparent Rect), none of the other mouseover events fire on the shape layer beneath it. I need to propogate the non-drag mouse events to the layer below it. There are A LOT of shapes with mouse over events.
Is there an easy way to propogate the mouse over events to the layer beneath it or do I need to write a custom handler to fire events for every shape?
I managed to solve this without having to propagate events between layers. I put a draggable surface behind the shapes on the shape layer only if a shape isn't clicked. Then to cover if a shape is clicked, on the shape dragstart event, if a layerdraggable flag is set, I do a stopDrag() on the shape and a startDrag() on the layer. This allowed me to toggle with a simple flag whether I want the whole layer dragging, or just the shape.
I had to clean up a little of the shape position on the dragend event, but alternatively you can do that with a dragbounds on the shape.
shape.on('dragstart', function () {
if (layerDraggable) {
shape.stopDrag();
shapeLayer.startDrag();
}
}

Nested zooms issue in D3

Please see my fiddle: http://jsfiddle.net/haiphong/BRjFE/
You can hold SHIFT and then drag and drop the rectangle to move it and the circle inside it around. You can hold SHIFT and zoom as well. This zoom/pan is done by d3.behavior.zoom(). Works well.
I want to zoom and pan the circle when NOT holding shift. So, I create another d3.behavior.zoom(). However, the circle can be zoomed but not panned. By debugging, I see that when I pan the circle, the handling code doesn't execute.
In sum, when binding a zoom to both the outer g element and the inner g element, the outer works well for zoom/pan; however, the inner only works for zoom. How to get it work for pan as well?
I found the solution for my answer. http://jsfiddle.net/haiphong/BRjFE/4/
When I pan the circle, its zoom event doesn't fire. However, its zoomstart event fires and it is fired before its parent's zoomstart. Somehow, when the parent's zoomstart fires, it eats the circle's event.
So, in the zoomstart of the circle, I force the event stop propagating when SHIFT isn't being hold. That makes the circle zoom fires.

create dblclick-to-select along with zoom in d3.js bubbles?

From the d3.js bubbles example I have added the zoom + pan functions. Now I want to allow users to select a bubble on desktops and touch-screens. The dblclick and touchstart seem to be consistent for this.
I know d3 provides a way to cancel an event from .zoom but then it is disabled and doesn't do anything.
.call(d3.behavior.zoom().on("zoom", zoom)).on("dblclick", null);
Link: http://bl.ocks.org/4163494
What I have above sort of works but you will notice that a dblclick doesn't zoom at first but then it is revealed if you cause another zoom event. I am looking for the right way to do this.
To fix I left the
.on("zoom", redraw)
function where it was but moved the dblclick down to the circle, text, and tspan elements. From there they call a function that first stops propagation and then selects the circle.
http://jsfiddle.net/nnzS9/

Categories