Konva Propagate events between layers - javascript

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();
}
}

Related

Konva Drag element from outside canvas onto stage

I have a Konva stage that currently displays a series of shapes. I would like to have a shapes panel, where I can drag shapes and insert into the canvas.
There are currently two ways of doing this:
Adding the Shapes Panel to the Konva stage as it's own layer and entity
Having the Shapes Panel as a standalone HTML element outside the Konva stage and implement a draggable js library to handle dragging behaviour
I'd rather option 2; being able to style the shapes panel with CSS and yield a number of other DOM related benefits is more attractive to me right now.
I have the dragging behaviour sorted, but there is one issue: even though I've implemented stage mouseover events, dragging an element that originates from outside the canvas to on top of the canvas doesn't actually trigger the stage event listeners.
Is there a way around this?
What's interesting is that if you click and hold the mouse outside the element and hover over the canvas, the event listeners fire. But, when you're actually dragging an element (text, image), the event listeners do not fire...
Take a look into this demo: https://konvajs.org/docs/sandbox/Drop_DOM_Element.html
var con = stage.container();
con.addEventListener('dragover', function(e) {
e.preventDefault(); // !important
});
con.addEventListener('drop', function(e) {
e.preventDefault();
// now we need to find pointer position
// we can't use stage.getPointerPosition() here, because that event
// is not registered by Konva.Stage
// we can register it manually (with private method):
stage.setPointersPositions(e);
// now you can add a shape. We will add an image
Konva.Image.fromURL('/assets/yoda.jpg', function(image) {
layer.add(image);
image.position(stage.getPointerPosition());
image.draggable(true);
layer.draw();
});
});

How can I change the color of a polygon on mouse hover in Cesium?

I need to make a polygon highlight on mouse hover and restore its color and appearance once the mouse is moved out of the polygon.
I tried this with ScreenSpaceEventType.MOUSE_MOVE event handler but I am not able to restore the appearance when mouse is moved out of polygon in this case.
I tried https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Apps/Sandcastle/gallery/Polygons.html (http://cesiumjs.org/Cesium/Apps/Sandcastle/gallery/polygons.html)
This file in Sancastle. It has inline comments like // For highlighting on mouseover in Sandcastle.
But it is not working as expected.
Is there any way in cesium to achieve this? or am I missing something?
Take a look at the "Picking" example in Sandcastle, and click on the button that says "Drill-down picking."
There are different ways to accomplish what you describe, but the above demo makes use of a Cesium CallbackProperty and provides a callback that will return either the polygon's normal color or the highlight color, depending on the "picked" status. Note that multiple overlapping polygons can be picked at the same time with this method.
The mouse move handler then just controls membership of the pickedEntities list, and the polygons choose appropriate colors for themselves based on their membership in that list.

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/

mouse drag on kml features with OpenLayers

Link: http://www1.qhoach.com/
When you drag, this map is panned... But if you drag on KML features (icon with circle), nothing happens
First of all,in your application there are four level of maps including the vector layer you mentioned with circle icons in your question.
0: "Đường Sá" ||---> Overlay Tiles
1: "Vệ Tinh" ||---> Overlay Tiles
2: "TMS Overlay" ||---> Markers ~ Icons
3: "KML" ||---> Vector
Analysis:
Starting with zero to last one,only vector seems to be the last one,others stays as overlay tiles.In order to come this problem we have to focus on marker layer,namely features (icons).
As you have seen on map,click event for map has been triggered when you try to drag the map around.You can't drag because event registration is working for marker layer first not for the map.That means in order to drag the map,moving mouse(drag) after click must follow.Since you're trying this on vector layer,there is no chance to pass the event to overlay layers.
Solution:
I propose you two ways to achieve this bug-type problem.
Let this be the long way
There is a control in OpenLayers known as SelectFeature inherited from Handler.Feature.This control generally allows vector feature from a given layer on click on hover.Which means this handler can respond to mouse event related to any drawn features.Only callbacks are associated with features,needing one of them click.Now all we have to do is to fall click event back to as we pan for overlay tiles.
var selectFeat = new OpenLayers.Control.SelectFeature(
vector, {toggle: true, clickout:false});
selectFeat.handlers['feature'].stopDown = false;
selectFeat.handlers['feature'].stopUp = false;
map.addControl(selectFeat);//instance of map
selectFeat.activate();
Once this control is activated you have to ensure your layers to pass events through another layer.To do that,simply
layer.events.fallThrough = true;//both for vector and marker layers
After all these actions we made so far,one last thing left to do:
That's switching the order of markers and kml layer.
And this should be the easiest way
That's z-index on layers.You can check in above sequence of layers that the layer which has highest id has also highest z-index.
layer.setZIndex(...any number...);
In addition to this solution,easy way allows only you to drag through map,when all sudden clicking features of icons may lost without long way,so it's your choice to leave them behind.
Mouse events do not want to propagate through an svg Vector overlay to layers underneath.
The solution above demands all marker HTML layers have higher zindex than all Vector SVG layers.
The following CSS provides a potential/partial work-around, propagating events through the svg element, but only where there is no vector elements within the svg overlay:
/** Hack so mouse events propagate(bubble) through svg elements, but not the
images within svg */
.olLayerDiv svg {
pointer-events: none;
}
.olLayerDiv svg * {
pointer-events: auto;
}
Combine the above CSS while adding fallThrough:true to all OpenLayers events objects within maps, layers, and controls.
// map events
var map = new OpenLayers.Map(div, { fallThrough:true } );
// layer events
var lvec = new OpenLayers.Layer.Vector( .... );
lvec.events.fallThrough = true
map.addLayers([lvec])
// all map controls
var ctrl = new OpenLayers.Control.SelectFeature( lvec, {...
fallThrough: true, autoActivate:true });
map.addControl( ctrl )

Categories