anseki / plain-draggable

The simple and high performance library to allow HTML/SVG element to be dragged.
https://anseki.github.io/plain-draggable/
MIT License
773 stars 99 forks source link

Draggable SVG collision #144

Closed MaksSTV closed 9 months ago

MaksSTV commented 9 months ago

I have a task in which there is a parent svg element that can be of any shape, and also inside it there are other svg elements of any shape. The task is to be able to move child elements inside the parent, and at the same time it was impossible to go beyond the border. I saw https://anseki.github.io/plain-draggable/#ex-040-stage , but here the child element is the simplest shape. And will the library's capabilities be enough if the child element is, for example, like a gear wheel? If so, what should I do to make it happen?

anseki commented 9 months ago

Hi @MaksSTV, thank you for the comment. Do you mean that the draggable element and its containment element are not rectangle? If so, you have to parse path data of those, and check intersection.

MaksSTV commented 9 months ago

do you have methods in your library that check for intersection?

anseki commented 9 months ago

No, the library has no method to check path data because this is used for dragging an element. You can use another library for handling SVG such as Snap.svg.

MaksSTV commented 9 months ago

Thanks for the information about Snap. Please do not close the issue yet, I will try to combine these libraries, maybe I will ask something.

anseki commented 9 months ago

Ok.

MaksSTV commented 9 months ago

Hello again. I dug into snap svg, but earlier I found a more convenient library for tracking intersections https://github.com/thelonious/kld-intersections and I used it in conjunction with the motion library https://github.com/svgdotjs/svg.draggable.js . In fact, it performs the same actions as your library.

But I ran into problems that when moving at the moment of finding the intersection, the shapes get stuck in my implementation. I came up with the idea that you can store the previous coordinates, and if there is an intersection when moving, then return to the previous coordinates, but this does not help. I have a suspicion that the event listeners do not have time to process each step and therefore the figure skips through some events and already finds itself inside another one.

`.on('dragmove', e => { const { handler, box } = e.detail e.preventDefault() const constraints = externalFig.bbox() console.log(constraints) let { x, y } = box

            function arrayToString(array) {
                return array
                    .map(([command, ...params]) => {
                        return command + params.join(' ')
                    })
                    .join(' ')
            }

            const intersections = Intersection.intersect(
                ShapeInfo.path(arrayToString(externalFig._array)),
                ShapeInfo.path(arrayToString(e.srcElement.instance._array))
            )
            if (intersections.status == 'Intersection') {
                console.log(CURRENT_COORD.x, CURRENT_COORD.y)
                console.log(x, y)

                if (CURRENT_COORD.y < y) {
                    y = CURRENT_COORD.y
                }
                if (CURRENT_COORD.y > y) {
                    y = CURRENT_COORD.y
                }
                if (CURRENT_COORD.x < x) {
                    x = CURRENT_COORD.x
                }
                if (CURRENT_COORD.x > x) {
                    x = CURRENT_COORD.x
                }
                handler.move(x, y)

                console.log('Intersec')
            } else {
                CURRENT_COORD.x = x
                CURRENT_COORD.y = y
                handler.move(x, y)
            }
        })`
anseki commented 9 months ago

Hi @MaksSTV, thank you for the comment. The animation frames skipping over a wall in Collision Detection is familiar topic. That is oftentimes called "Tunneling". Standard solutions are using "Key frames" that is not "Animation frames", adding transparency elements, controlling with "Physics engine", etc.

anseki commented 9 months ago

No reply came, then this abandoned issue is closed.

anseki commented 9 months ago

By the way, the algorithm is dependent on the shape of the containment. For example, a very easy case is detection whether a point is inside or outside of a polygon. https://jsfiddle.net/x04m9w1t/show Drag the blue ball.