Копировать преобразование из элемента SVG в группу SVG - PullRequest
0 голосов
/ 14 марта 2020

У меня есть элемент SVG, и мне нужно нарисовать точки трансформации вокруг. Я использую svg. js и часть его плагина изменения размера .

. Он работает для перемещения и вращения не преобразованного элемента, но не для элемента с преобразованием matrix.

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

Следующий фрагмент иллюстрирует, что я имею в виду. Кнопки с пометкой «Steps1..3» показывают шаги, а кнопка «Переключить функцию преобразования» изменяет функцию преобразования.

// transform function
const makeTransformTR = (bbox, el, nested) => {
      const elTransfrom = el.transform();
      let cx = bbox.width / 2;
      let cy = bbox.height / 2;

      let tx = bbox.x;
      let ty = bbox.y;
      let transfromAttr = `translate(${tx}, ${ty})`;
      let rotate = elTransfrom.rotate;
      if (rotate) {
        transfromAttr += `, rotate(${rotate}, ${cx}, ${cy} )`;
      }
      nested.attr('transform', transfromAttr);
    };

  const makeTransformRT = (bbox, el, nested) => {
    const elTransfrom = el.transform();
    let cx = bbox.cx;
    let cy = bbox.cy;
    let tx = bbox.x;
    let ty = bbox.y;

    let transfromAttr = ``;
    let rotate = elTransfrom.rotate;
    if (rotate) {
      transfromAttr += ` rotate(${rotate}, ${cx}, ${cy} )`;
    }
    transfromAttr += (transfromAttr ? ',' : '') + ` translate(${tx}, ${ty})`;
    nested.attr('transform', transfromAttr);

  };
  const makeTransformByMatrix = (bbox, el, nested) => {
    const matrix = new SVG.Matrix(el);
    const zeroMatrix = {
      a: 1,
      b: 0,
      c: 0,
      d: 1,
      e: 0,
      f: 0,
      originX: 0,
      originY: 0,
      rotate: 0,
      scaleX: 1,
      scaleY: 1,
      shear: 0,
      translateX: 0,
      translateY: 0
    };
    const elTransfrom = el.transform();
    let a = elTransfrom.rotate * Math.PI / 180 || 0;
    let cosA = Math.cos(a);
    let sinA = Math.sin(a);
    let cx = 1 * bbox.cx;
    let cy = 1 * bbox.cy;
    let tx = -1 * cx * cosA + cy * sinA + cx;
    let ty = -1 * cx * sinA - cy * cosA + cy;
    let newMatrix = new SVG.Matrix({
      a: cosA,
      b: sinA,
      c: -1 * sinA,
      d: cosA,
      e: tx,
      f: ty
    });
    nested.matrix(newMatrix);
    nested.translate(bbox.x, bbox.y);
  };
  const transformFuncs = {
    'makeTransformRT' : makeTransformRT,
    'makeTransformTR' : makeTransformTR,
    'makeTransformByMatrix' : makeTransformByMatrix
  }
  const getRect = () => {
    return SVG(document.getElementById('rect1'));
  };
  const getGroup = () => {
    return SVG(document.getElementById('g1'));
  };
  const reset = () => {
    const rect = getRect();
    const g = getGroup();
    rect.attr('transform', '');
    rect.width("108");
    g.attr('transform', '')
  };
  const funcs=Object.keys(transformFuncs);
  let fIndex = 0;

  // rotate the rect and get the transform from the group
  const step1 = () => {
    const rect = getRect();
    rect.attr('transform', 'matrix(0.5906056676199253,0.806960312143802,-0.806960312143802,0.5906056676199253,140.68774443238965,-45.31069334044855)')
  }

  const step2 = () => {
    transformFunction(getRect().bbox(), getRect(), getGroup());
  }

  // This might cause my issue
  const step3 = () => {
    const rect = getRect();    
    rect.width(2); // changing width
    transformFunction(rect.bbox(), rect, getGroup());
  }

  const log = (text) => {
    let t = document.getElementById('log').value;
    t+='\n'+text;
    document.getElementById('log').value = t;
  }

  const setTransformFunc=()=>{
    transformFunction = transformFuncs[ funcs[fIndex] ];
    log('new func: ' + funcs[fIndex]);
  }

  const switchToAlernative=() => {
    reset();

    if(fIndex>=funcs.length){
      fIndex = 0;
    }
    setTransformFunc();
    fIndex++;
  }

  switchToAlernative();
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/3.0.16/svg.js"></script>

<body>

<section  style="display: flex">
    <svg width="300" height="300" style="display: block;" xmlns="http://www.w3.org/2000/svg" version="1.1">

        <rect  x="61" y="62" width="108" height="108" fill="none" stroke="#000" stroke-width="2"
               id="rect1"
        ></rect>
        <g id="g1" >
            <rect width="108" height="108"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-7" y="-7"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="101" y="-7"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="101" y="101"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-7" y="101"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="47" y="-7"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="101" y="47"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="47" y="101"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-7" y="47"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="47" y="-27"></rect>
        </g>
    </svg>
    <div >
        <button onclick="step1()">Step1</button>
        <button onclick="step2()">Step2</button>
        <button onclick="step3()">Step3</button>
        <br><br>
        <div><button onclick="reset()">Reset</button><button onclick="switchToAlernative()">Switch transform function</button></div>

        <div><textarea cols="40" rows="30" id="log"></textarea> </div>

    </div>
</section>


<section >
    <svg width="300" height="300" style="display: block;" xmlns="http://www.w3.org/2000/svg" version="1.1">
       
        <rect  x="61" y="62" width="108" height="108" fill="none" stroke="#000" stroke-width="2"
              id="rect2"
              transform="matrix(0.5906056676199253,0.806960312143802,-0.806960312143802,0.5906056676199253,140.68774443238965,-45.31069334044855)"></rect>
        <g id="g2" transform=" rotate(53.80000000000001, 115, 116 ), translate(61, 62)">
            <rect width="108" height="108" class="svg_select_boundingRect"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-7" y="-7"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="101" y="-7"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="101" y="101"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-7" y="101"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="47" y="-7"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="101" y="47"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="47" y="101"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-7" y="47"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="47" y="-27"></rect>
        </g>
    </svg>
</section>


<section >
    <svg width="300" height="300" style="display: block;" xmlns="http://www.w3.org/2000/svg" version="1.1">

        <rect  x="61" y="62" width="2" height="108" fill="none" stroke="#000" stroke-width="2"
                id="rect3"
              transform="matrix(0.5906056676199253,0.806960312143802,-0.806960312143802,0.5906056676199253,140.68774443238965,-45.31069334044855)"></rect>
        <g id="g3" transform=" rotate(53.80000000000001, 62, 116 ), translate(61, 62)">
            <rect width="2" height="108" class="svg_select_boundingRect"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-7" y="-7"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-5" y="-7"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-5" y="101"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-7" y="101"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-6" y="-7"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-5" y="47"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-6" y="101"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-7" y="47"></rect>
            <rect width="14" height="14" stroke-width="3" stroke="#5ab3e4" fill="#ffffff" rx="3" ry="3" x="-6" y="-27"></rect>
        </g>
    </svg>
</section>
</body>
</html>

Я думаю, что функция "makeTransformTR" работает, как и ожидалось для шагов 1-2; «makeTransformRT» не должен работать для шагов 1-2; "makeTransformByMatrix" не работает, но перспективен.

Итак, у вас есть идея, как исправить функцию преобразования, чтобы правильно выполнить все шаги? Пожалуйста, помогите!

1 Ответ

0 голосов
/ 14 марта 2020

Хм ... в этих условиях задача сводится к тому, что она должна получить центральную точку вращения из матрицы. Как я понимаю, это невозможно в общем случае. Итак, проблема должна быть закрыта, и я решил свою проблему, изменив расчет матрицы для элемента svg на последовательность переводов и вращений

...