Взаимодействовать с JS, перетаскивать элементы SVG внутрь SVG-представления

Моя проблема, когда я перетаскиваю элементы, элемент находится далеко за курсором, так что, похоже, это проблема отношения?

Код:

    interact('.element', {
        context: '.lipstick__plane'
    })
        .draggable({
            snap: {
                targets: [
                    interact.createSnapGrid({x: 10, y: 10})
                ],
                range: Infinity
            },
            inertia: true,
            restrict: {
                restriction: '#lipstick__plane__main',
                elementRect: {top: 0, left: 0, bottom: 1, right: 1},
                endOnly: true
            }
        })
        .on('dragmove', function (event) {
            $scope.$apply(function () {
                var target = event.target,
                    x = (parseFloat(target.getAttribute('x')) || 0) + ((1020 / window.outerWidth) * event.dx),
                    y = (parseFloat(target.getAttribute('y')) || 0) + ((1020 / window.outerHeight) * event.dy);

                var indx = event.target.getAttribute('data-index');

                _.set($scope.stage.elements[indx], 'meta.XCord', x);
                _.set($scope.stage.elements[indx], 'meta.YCord', y);
            });
        });

Я ныряю там, что приблизило его к курсору, но я могу пробовать цифры целый день ...

Мой блок инициализации svg:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 1024" width="1024px" height="1024px" xml:space="preserve" id="lipstick__plane__main">

Одна вещь, я думаю, может быть проблемой, но я сомневаюсь, что Angular Digest происходит после запроса, чтобы получить новыйx а такжеy атрибут?

 Marais Rossouw17 июл. 2016 г., 13:46
Ну естьwidth: calc(100vw - 200px) применяется к оболочке div, иdisplay: block; width: 100%; height: auto; к самому элементу SVG.
 philipp17 июл. 2016 г., 13:46
Вы проверили, применяется ли какое-либо преобразование в SVG? Похоже, что перевод масштабируется, что может быть вызвано группой обёрток, у которой есть преобразование ....
 Marais Rossouw17 июл. 2016 г., 13:52
@ philipp это имеет смысл, но мне нужно, чтобы svg масштабировался до правильной ширины, есть ли способ запуститьdx, dy через алгоритм может быть ??
 Marais Rossouw17 июл. 2016 г., 13:51
Вот svg на экранеcopy+paste, outerHTML pastebin.com/fNtpjDXm
 philipp17 июл. 2016 г., 13:50
Тогда это проблема масштабирования. Попробуйте svg с размером 1024 пикселя, и он должен работать. Если это так, вы должны использовать матрицу преобразования экрана для масштабирования вектора перевода

Ответы на вопрос(2)

Решение Вопроса

поскольку внутренняя настройка SVG установлена ​​на 1024 пикселя по ширине и высоте, но отображается в другом размере, меньшем в этом случае, поэтому примененный перевод от перетаскивания уменьшается, и элемент выглядит как медленнее, чем курсор.

Чтобы решить эту проблему, вам необходимо соответствующим образом масштабировать вектор перевода. Один из способов получить коэффициенты масштабированияsx а такжеsy может быть:

запросить получившуюся ограничивающую рамкуbb из SVGgetClientBoudingRectsx = bb.width / 1024 // (original size), same for sy

Или, если вы можете получить доступ кsvg элемент, который вы можете использовать.getScreenCTM() чтобы получить матрицу преобразования. Который должен выглядеть так:

| a  c  e |
| b  d  f |
| 0  0  1 |

a должен представлятьsx а такжеd sy.

редактировать

Я настроил небольшую скрипкуВот который показывает основной подход. В общем, решение - это матричное преобразование вектора, и задача состоит в том, чтобы найти правильную матрицу. Так как любой элемент svg может иметь свое собственное преобразование или как дочерний элемент группы, может получить преобразование от своих родителей, недостаточно использовать корень<svg>«sCомер текущегоTransformationMAtrix. Вот почему каждыйSVGElement реализуетSVGLocatable Интерфейс, который позволяет получить преобразование от корня<svg> кSVGElement (getCTM) или документ кSVGElement (GetScreenCTM ()). Противоположное направление описывается обратной матрицей. (объяснение на SO)

let svg   = document.querySelector('svg'),
    e     = svg.querySelector('.myelement'),
    ctm   = e.getScreenCTM(),
    point = svg.createSVGPoint(),
    point2;

point.x = …;
point.y = …;

point2 = point.matrixTransform(ctm);

В заключение: использование матрицы преобразования должно быть предпочтительным способом, поскольку она (по крайней мере, должна) принимать во внимание все преобразования, которые могут быть применены к svg с помощью css, такие как вращения, 3d-преобразования и так далее. Чем более вы конкретны, то есть чем больше вы знаете, какой элемент вы хотите преобразовать, тем выше будет точность.

 Marais Rossouw18 июл. 2016 г., 01:20
Если у меня есть этот масштабирующий вектор, могу ли я использовать его какx += sx а такжеy += sy координаты, когда мышь движется?

1 с вашими координатами SVG. Поэтому вам нужно преобразовать координаты мыши / экрана в координаты SVG, чтобы получить правильную позицию для перетаскиваемого объекта.

Смотрите этот вопрос о том, как сделать преобразование.

Как конвертировать экранные координаты в пространство документа в масштабированном SVG?

Ваш ответ на вопрос