What’s the most efficient method to drag/move objects simultaneously? - konvajs

This is more of a general design question than a specific question about a piece of code. Let me do an outline:
Imagine a canvas with a poly line consisting of 3 or more points. Each of those points has a circle object as draggable handle. The user can move the drag handle, the action updates a react context containing only those 3 coordinates. The new context triggers a redraw of the canvas, updating the poly line and the drag handle with new coordinates, while performing things like “snap to axis” and “snap to closest other vector” checks while dragging occurs.
I only use functional components (React.FC) and state is shared where needed using hooks.
I use requestAnimationFrame() on the drag handler to debounce updates as close as possible to the maximum refresh rate of the client. The goal is to stay at 60fps.
Questions:
Does a re-render of a component attached to a stage in react-konva always trigger a redraw of everything on the actual canvas or does react-konva keep track?
Would it be advisable to use vanilla Konva instead of react-konva abstraction in this case, to avoid excessive redraw, while only using the react context to persist state once a drag action ended?
Is there a more efficient way to handle this use case I currently am not aware of?

When you re-render a component it will trigger an internal update inside react-konva.
react-konva will update props of Konva nodes. It is trying to work smart, so if you re-rendered a component, but no props changed - Konva nodes will be not updated (and no canvas draws).
Any change of props will trigger layer (or stage) redraw.
You can use vanilla Konva instead of react-konva if you want to have full control and if you want to skip some react reconciler work. But it may be hard on large components.
Also, it is better to avoid using React.Context for frequent updates. Updating the context may trigger a lot of re-renders of components. So it is better to use plain state (or even mobx) for faster updates.

Related

Konva object snapping with transformer jitters

I'm trying to make an editor using Konva.js.
In the editor I show a smaller draw area which becomes the final image. For this I'm using a group with a clipFunc. This gives a better UX since the transform controls of the transformer can be used "outside" of the canvas (visible part for the user) and allow the user to zoom and drag the draw area around (imagine a frame in Figma).
I want to implement object snapping based on this: https://konvajs.org/docs/sandbox/Objects_Snapping.html. (just edges and center for now) However I want it to be able to work when having multiple elements selected in my Transformer.
The strategy I'm using is basically calculating the snapping based on the .back element created by the transformer. When I know how much to snap I apply it to every node within the transformer.
However when doing it, the items starts jittering when moving the cursor close to the snapping lines.
My previous implementation was having the draw area fill the entire Stage, which I did manage to get working with the same strategy. (no jitter)
I don't really know what the issue is and I hope some of you guys can point me in the right direction.
I created a codepen to illustrate my issue: https://codesandbox.io/s/konva-transformer-snapping-1vwjc2?file=/src/index.ts

Moving point with mouse

I drew a lot points in my program with webgl. Now I want to pick any point and move this point new position. The case is I don't know how to select point. So am I supposed to add actionlistener to each point?
WebGL is a rasterization library. It has no concept of movable, clickable position or points. It just draws pixels where you ask it to.
If you want to move things it's up to you to make your own data, use that data to decide if the mouse was clicked on something, update the data to reflect how the mouse changed it, and finally use WebGL to re-render something based on the data.
Notice none of those steps except the last one involve WebGL. WebGL has no concept of an actionlistener since WebGL has no actions you could listen to. It just draws pixels based on what you ask it to do. That's it. Everything else is up to you and outside the scope of WebGL.
Maybe you're using some library like three.js or X3D or Unity3d but in that case your question would be about that specific library as all input/mouse/object position related issues would be specific to that library (because again, WebGL just draws pixels)

In OpenLayers3 how would I prevent a feature from moving in front of other features when selected?

The hierarchy I'm using looks something like this:
FRONT
1 - layer with several features (e.g. point data)
2 - layer with several features (e.g. path data)
3 - layer with several features (e.g. region data)
BACK
When the user selects a feature in layer 3 based on an ol.interaction.Select the default behavior is to render the selected feature in front of layer 1. How can I prevent this re-ordering?
I had a nearly similiar problem, when i selected the region - the points and other vector geometries were hidden behind the selected feature. In my usecase an special styling with transparent filling was the solution.
If you want a solution based on the layer rendering i would suggest to handle it with the ZIndex. The ol.interaction.Select doesn't provide a setZIndex but if you take a look on the source code (https://github.com/openlayers/ol3/blob/v3.13.0/src/ol/interaction/selectinteraction.js) you can see that the interaction save the selected feature in an unmanaged Layer which you can access on different ways (map.getLayers().getArray().forEach .... or sth) and i'm sure there you can set the ZIndex. Note default zIndex is 0 and a higher Index will render the layer above and lower one.
Here's how the select interaction works in ol3. The selected feature is marked for being skipped in rendering. In other words, it disappears from the original layer it comes from upon re-rendering after being selected.
It is then added to an other layer that is actually not added to the map using the conventional map.addLayer method, but set to the map using layer.setMap. The layer ends up being drawn on top of all the others, resulting the "selected" feature to be on top of everything else.
This architecture was decided to improve performance. However, you can easily achieve what you want, i.e. have the clicked feature stay where it is and change its style, by simply using the map.forEachFeatureAtPixel method and implement your own concept of selection there. It would be slower, but simple enough to accomplish what you want.

iOs draw an intereactive map

I need to draw an interactive map for an iOs application. For example it can be the map of the US showing the states. It will need to show all the states in different colors ( I'll get this from a delegate colorForStateNo: ) It will need to allow the user to select a state by touching it, when the color will change, and a "stick out" effect should be shown, maybe even a symbol animated to appear over the selected state. Also the color of some states will need to change depending on external events. This color change will mean an animation like a circle starting in the middle of the state and progressing towards the edges changing the color from the current one to the one inside the circle.
Can this be done ,easily in core-graphics? Or is it only possible with Open GL ES? What is the easiest way to do this? I have worked with core graphics and it doesn't seem to handle animation very well, I just redraw the entire screen when something needed to move... Also how could I use an external image to draw the map? Setting up a lot of drawLineToPoint seems like , a lot of work to draw only one state let alone the whole map ...
You could create the map using vector graphics and then have that converted to OpenGL calls.
Displaying SVG in OpenGL without intermediate raster
EDIT: The link applies to C++, but you may be able to find a similar solution.

Is it possible to use animated icons with VirtualTreeView nodes?

I am using the awesome VirtualTreeView component with Delphi 2010. Currently, my nodes are setup with a standard image in a TImageList. What I'd like to do is to be able to show some type of spinning animated icon to show visually that a node is "busy".
Obviously the node won't be busy, but what the node represents to the user will actually be busy. Is there an easy way to do this?
The only way I can think of is to create add 8-10 images represent a spinning wheel to my current TImageList and then cycle through them for that node.
Does anyone have any suggestions?
Probably you can do the animation yourself. For example you could store the animation status in the node data. Then you could repeatedly (from a timer) iterate the whole tree (IterateSubTree) and from the callback check the node data and if the node should be animated call RepaintNode (to force repainting immediately) or InvalidateNode (to invalidate the node so it's painted in the next paint cycle). The actual painting could be done as usual from an OnGetImageIndex event handler, returning different image indexes for different stages of the animation cycle.

Resources