Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 05.12.2018, 13:20
Новичок на форуме
Отправить личное сообщение для Vad0k Посмотреть профиль Найти все сообщения от Vad0k
 
Регистрация: 30.11.2018
Сообщений: 8

Абсолютное (translate) смешение элемента <g> внутри SVG
Доброго времени суток, форумчане.
Подскажите, как правильно получить координаты элемента группы <g> и элементов вложенных в эту группу относительно SVG контейнера.

Пример кода:
<svg width="100%" height="100%" viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMin slice" x="0" y="0" class="canvas-svg" tabindex="1">
<g transform="translate(100 100)">
     <g transform="translate(100 100)"> 
          <circle r="50" cx="25" cy="25" fill="yellow" />
     </g>
</g>
<svg>

Хотелось бы получить абсолютные координаты окружности относительно родительского SVG, а не относительные относительно контейнера используя JS(ES6+ )<g>.

Может это поможет, что я имею ввиду.

Последний раз редактировалось Vad0k, 05.12.2018 в 17:32.
Ответить с цитированием
  #2 (permalink)  
Старый 05.12.2018, 14:03
Аватар для MallSerg
Профессор
Отправить личное сообщение для MallSerg Посмотреть профиль Найти все сообщения от MallSerg
 
Регистрация: 07.03.2011
Сообщений: 1,127

Так же как и всегда с помощью арифметики.
Посмотри какие X и Y у тебя есть и сложение каких даст нужный размер.
Ответить с цитированием
  #3 (permalink)  
Старый 05.12.2018, 14:11
Новичок на форуме
Отправить личное сообщение для Vad0k Посмотреть профиль Найти все сообщения от Vad0k
 
Регистрация: 30.11.2018
Сообщений: 8

Я забыл упомянуть, что необходимо использовать JS (ES6 >).

Последний раз редактировалось Vad0k, 05.12.2018 в 14:43.
Ответить с цитированием
  #4 (permalink)  
Старый 05.12.2018, 14:33
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,075

Сообщение от MallSerg
Так же как и всегда с помощью арифметики.
Посмотри какие X и Y у тебя есть и сложение каких даст нужный размер.
можно пример?
Ответить с цитированием
  #5 (permalink)  
Старый 05.12.2018, 15:20
Новичок на форуме
Отправить личное сообщение для Vad0k Посмотреть профиль Найти все сообщения от Vad0k
 
Регистрация: 30.11.2018
Сообщений: 8

Я понимаю, что можно использовать арифметику и парсить аттрибут transform="translate(x y)" рекурсивно к родителю, но есть некоторые сложности, что не всегда я перемещаю элементы через translate, а иногда на некоторых узлах используя атрибуты x, y или cx, cy, а может вообще быть path... .
let outputChanel = e.target; // наведенный элемент
let cx = +outputChanel.getAttributeNS(null, 'cx'); // получить [B]локальную[/B] координату относительно группы <g>, но т.к <g> может быть рекурсивное множество вложенных и относительно смещенных между собой.
let cy = +outputChanel.getAttributeNS(null, 'cy');
let cc = getAbsoluteCoords(outputChanel, cx, cy); // вот хотелось реализовать данную функцию, которая будет брать матрицу и смотреть её параметр смещения по осям (matrix.e и matrix.f), НО относительно родительского <SVG>

selectLineChanel.setAttributeNS(null, 'x2', cc.x);
selectLineChanel.setAttributeNS(null, 'y2', cc.y);

selectLineChanel = false;
console.log('endDrawLine (ok)', cc.cx, cc.cy, e.target);


а вот весь участок
// Перетаскивание элементов
(function () {
    let $document = $(document);

    const $svg = $('#main .canvas-svg'); // SVG

    // PC
    $document.on('mousedown', $svg, startDrag);
    $document.on('mousemove', $svg, drag);
    $document.on('mouseup', $svg, endDrag);
    $document.on('mouseleave', $svg, endDrag);

    // MOBILE
    $document.on('touchstart', $svg, startDrag);
    $document.on('touchmove', $svg, drag);
    $document.on('touchend', $svg, endDrag);
    $document.on('touchleave', $svg, endDrag);
    $document.on('touchcancel', $svg, endDrag);


    let selectedElement = false,
        offsetElement,
        transformElement;

    let selectLineChanel = false;


    function startDrag(e) {

        if (e.target.classList.contains('output-chanel')) { // при наведении на точку канала
            selectLineChanel = document.createElementNS('http://www.w3.org/2000/svg', 'line');
            //initialiseDragging(e, selectLineChanel);
            let outputChanel = e.target;
            let coord = getMousePosition(e);

            selectLineChanel.setAttributeNS(null, 'x1', coord.x);
            selectLineChanel.setAttributeNS(null, 'y1', coord.y);
            selectLineChanel.setAttributeNS(null, 'stroke-width', 5);
            selectLineChanel.setAttributeNS(null,'stroke', '#000');
            selectLineChanel.setAttributeNS(null,'stroke-linecap', 'round');

            let groupChanelLine = activeSVG.querySelector('.chanel-lines');
            groupChanelLine.appendChild(selectLineChanel);

            console.log('startDrawLine');
        } else if (e.target.classList.contains('draggable')) { // при наведении на элемент
            selectedElement = e.target;
            initialiseDragging(e, selectedElement);
            console.log('startDragElement')
        } else if (e.target.parentNode.classList.contains('draggable-group')) {
            selectedElement = e.target.parentNode;
            initialiseDragging(e, selectedElement);
            console.log('startDragElement');
        }
    }
    function drag(e) {
        e.preventDefault();
        if(selectLineChanel){
            let coord = getMousePosition(e);
            selectLineChanel.setAttributeNS(null, 'x2', coord.x);
            selectLineChanel.setAttributeNS(null, 'y2', coord.y);
            //console.log('drawLine: x =',coord.x, 'offsetElementX =', offsetElement.x, 'y =', coord.y, 'offsetElementY =', offsetElement.y);
        } else if (selectedElement) {
            let coord = getMousePosition(e);
            transformElement.setTranslate(coord.x - offsetElement.x, coord.y - offsetElement.y);
            console.log('drag');
        }
    }
    function endDrag(e) {
        if (selectLineChanel) {
            console.log(e.target);
            if (e.target.classList.contains('input-chanel')) {
                let outputChanel = e.target;
                let cx = +outputChanel.getAttributeNS(null, 'cx');
                let cy = +outputChanel.getAttributeNS(null, 'cy');
                let cc = getAbsoluteCoords(outputChanel, cx, cy);

                selectLineChanel.setAttributeNS(null, 'x2', cc.x);
                selectLineChanel.setAttributeNS(null, 'y2', cc.y);

                selectLineChanel = false;
                console.log('endDrawLine (ok)', cc.cx, cc.cy, e.target);
            } else {
                selectLineChanel.remove();
                selectLineChanel = false;
                console.log('endDrawLine (cancel)');
            }
        }
        if(selectedElement){
            selectedElement = false;
            console.log('endDragElement');
        }
    }


    function convertCoords(element, x, y) {
        let offset = activeSVG.getBoundingClientRect();
        let matrix = element.getScreenCTM();

        return {
            x: (matrix.a * x) + (matrix.c * y) + matrix.e - offset.left,
            y: (matrix.b * x) + (matrix.d * y) + matrix.f - offset.top
        };
    }

    function getAbsoluteCoords(element, x, y) {
        let offset = activeSVG.getBoundingClientRect();
        let matrix = element.getScreenCTM();

        return {
            x: (x + matrix.e),
            y: (y + matrix.f)
        };
    }



    function getMousePosition(e) {
        let CTM = activeSVG.getScreenCTM(); // Возвращает DOMMatrix, представляющую матрицу, которая преобразует систему координат текущего элемента в систему координат окна просмотра SVG для фрагмента документа SVG.
        if (e.touches) { e = e.touches[0]; } // iPhone
        return {
            x: (e.clientX - CTM.e) / CTM.a,
            y: (e.clientY - CTM.f) / CTM.d
        }
    }

    // инициализация положения перетаскиваемого элемента (блока)
    function initialiseDragging(e, element) {
        offsetElement = getMousePosition(e);
        
        let transforms = element.transform.baseVal;
        if (transforms.length === 0 || transforms.getItem(0).type !== SVGTransform.SVG_TRANSFORM_TRANSLATE) {
           
            let translate = activeSVG.createSVGTransform();
            translate.setTranslate(0, 0);
            element.transform.baseVal.insertItemBefore(translate, 0);
        }
      
        transformElement = transforms.getItem(0);
        offsetElement.x -= transformElement.matrix.e;
        offsetElement.y -= transformElement.matrix.f;
    }

})();

Последний раз редактировалось Vad0k, 05.12.2018 в 15:30.
Ответить с цитированием
  #6 (permalink)  
Старый 05.12.2018, 15:59
Аватар для MallSerg
Профессор
Отправить личное сообщение для MallSerg Посмотреть профиль Найти все сообщения от MallSerg
 
Регистрация: 07.03.2011
Сообщений: 1,127

Сообщение от рони Посмотреть сообщение
можно пример?
Не думаю что это поможет автору. К тому же в документации есть функция которая сама делает сложение и масштабирование для ленивых.
<body>
<svg width="100%" height="100%" viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMin slice" x="0" y="0" class="canvas-svg" tabindex="1">
<g transform="translate(100 100)">
     <g transform="translate(100 100)">
          <circle r="50" cx="25" cy="25" fill="yellow" />
     </g>
</g>
<svg>
<script>
_=(document.querySelector("g")).getCTM();
alert ( "x="+_.e+"   y="+_.f);
</script>

Последний раз редактировалось MallSerg, 05.12.2018 в 16:02.
Ответить с цитированием
  #7 (permalink)  
Старый 05.12.2018, 16:44
Новичок на форуме
Отправить личное сообщение для Vad0k Посмотреть профиль Найти все сообщения от Vad0k
 
Регистрация: 30.11.2018
Сообщений: 8

Я немного изучил характеристики данного примера
Физ. размер svg (x: 840px) в обозревателе, viewbox width: 1000px для svg => w:0.84 per 1px.
Значение отображается x: 84,0px относительно вложенной группы не учитывая другие вложенности.

По сути из примера я бы хотел бы получить значение: x: 100 + 100 + 25
независимо от уровня вложенности, без перевода viewbox в viewport.

Возможно, я не сумел объяснить, что мне нужно... мне просто бы хотелось получить физ. абсолютное позиционирование внутри SVG

<svg width="100%" height="100%" viewBox="0 0 1000 1000" preserveAspectRatio="xMidYMin slice" x="0" y="0" class="canvas-svg" tabindex="1">
<g transform="translate(100 100)">
     <g transform="translate(100 100)"> 
          <circle r="50" cx="25" cy="25" fill="yellow" />
     </g>
</g>
<svg>


function getAbsoluteCoords(element, x, y) {
        let matrix = element.getCTM();

        return {
            x: (x + matrix.e),
            y: (y + matrix.f)
        };
    }

но данный пример возвращает относительно вложенной выше группы родителя, тоесть x: 84px.

Последний раз редактировалось Vad0k, 05.12.2018 в 17:33.
Ответить с цитированием
  #8 (permalink)  
Старый 05.12.2018, 18:22
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,075

Vad0k,
здесь более демократичные правила общения, любой может задать вопрос или написать комментарий в созданной вами теме, я задал вопрос, получил ответ и поблагодарил, я ни коим образом не закрывал вашу тему.
Ответить с цитированием
  #9 (permalink)  
Старый 05.12.2018, 18:33
Новичок на форуме
Отправить личное сообщение для Vad0k Посмотреть профиль Найти все сообщения от Vad0k
 
Регистрация: 30.11.2018
Сообщений: 8

Я ни в коем случае не обвиняю никого. Я просто посчитал, что любой кто зайдет помочь, может увидеть сообщение "Спасибо", и подумать не вдаваясь в детали, что вопрос уже решен.
Помню, когда сидел на 4pda, не разрешали внутри темы создавать подтем вопросы(модерировали) (для меня это просто не привычно,... поймите меня тоже, правильно.).

На случай прикреплю ветку ещё вопроса, может, кому поможет, если будет искать подобное решение.
На случай спросил у англоязычной аудитории решение

Последний раз редактировалось Vad0k, 05.12.2018 в 18:37.
Ответить с цитированием
  #10 (permalink)  
Старый 05.12.2018, 18:34
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,075

Vad0k,
может чем поможет ...
http://www.codedread.com/dragtest2.svg
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Можно ли использовать анимацию svg внутри canvas? Negotiant Общие вопросы Javascript 0 30.08.2017 10:56
JS как изменить позицию SVG элемента? mkrichet Общие вопросы Javascript 2 09.12.2015 08:59
Создание SVG элемента и вставка на страницу FINoM Events/DOM/Window 3 13.09.2015 16:47
Event тега object после подгрузки svg контента внутри него Wahlberg Events/DOM/Window 8 26.01.2015 19:38
Обработка события элемента внутри создавшего его объекта pauluss Общие вопросы Javascript 10 10.09.2010 17:01