SVG Rectangle неправильно вращает / перемещает группу при использовании функции преобразования SVG "matrix ()" - PullRequest
0 голосов
/ 06 мая 2020

Я пытаюсь оживить группу объектов SVG. Что должно произойти, так это то, что четырехцветный прямоугольник должен двигаться вправо, вращаясь вокруг своей центральной оси, но на самом деле происходит вращение вокруг точки 0,0 на экране. Может ли кто-нибудь помочь мне понять, что я делаю неправильно?

Вот HTML / SVG

<head></head>
<body>
    <button id="startBtn">START/STOP</button>
    <button id="resetBtn">RESET</button>

    <svg id="thesvg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1362.98 768">
        <g id="rectangle">
            <rect style="fill: red;" x="0" y="0" width="50" height="50" />
            <rect style="fill: green;" x="50" y="0" width="50" height="50" />
            <rect style="fill: yellow;" x="0" y="50" width="50" height="50" />
            <rect style="fill: blue;" x="50" y="50" width="50" height="50" />
        </g>
    </svg>

Для этого я запускаю следующую функцию

var timer = null;
var started = false;
var x = 0;
var y = 0;

// Center of rectangle
var cx=50, cy=50;
var angle = 0;

/**
* Ran every tick. Should make the rectangle move diagonally right/down 
* while spinning around it's center
*/
function running(){
  updateRectanglePosition();


    // Get the matrix of the parent element
    var rect = document.getElementById('rectangle');
    var ctm = rect.parentNode.getScreenCTM();
    var matrix = new DOMMatrix([ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f]);

    // Translate the center of the group to 0,0 of parent matrix
    matrix = matrix.translate(-(cx), -(cy));

    // Rotate around this point 
    matrix = matrix.rotate(angle % 360);

    // Translate to actual x,y position
    matrix = matrix.translate(x , y);

  rect.setAttribute('transform', matrix.inverse().toString());

  if(timer){
    timer = setTimeout(running, 100);
  }
}

// Updates rectangle position every frame
function updateRectanglePosition()
{
  x += 1;
  y += 1;
  angle = (angle + 10);
}

Пример https://codepen.io/comfydemon/pen/jObYXYL

Ответы [ 2 ]

0 голосов
/ 11 мая 2020

Мне пришлось изменить это, повернув вектор смещения на величину, противоположную той, на которую я повернул фигуру, чтобы «отменить» систему координат, которая была изменена вращением

// Translate the element to the x,y pos
let translation = new DOMMatrix();
let movement = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
// take the x and y translation values and rotate them to the opposite of the rotation of the shape 
// toRadians just converts deg to rad
translation = translation.translate(movement * Math.cos(toRadians(360 - angle)),movement * Math.sin(toRadians(360 - angle)));
0 голосов
/ 06 мая 2020

Исходный вопрос говорит, что 4 прямоугольника только вращаются, но не перемещаются. Копирование точного кода показало, что 4 ящика также фактически вращаются и перемещаются. Вы переводите его всего на 1 пиксель через 100 мс, что создает впечатление, что объект не движется. Попробуйте увеличить значение в пикселях, и, поскольку ваша система координат перевернута, вы должны использовать отрицательное значение для оси x, чтобы переместить объект вправо.

См. Ниже Рабочий код (желаемый результат):

<body>


    <button id="startBtn">START/STOP</button>


    <svg id="thesvg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1362.98 768">
        <g id="rectangle">
            <rect style="fill: red;" x="0" y="0" width="50" height="50" />
            <rect style="fill: green;" x="50" y="0" width="50" height="50" />
            <rect style="fill: yellow;" x="0" y="50" width="50" height="50" />
            <rect style="fill: blue;" x="50" y="50" width="50" height="50" />
        </g>

    </svg>
  
 <script>
 



var timer = null;
var started = false;
var x = 0;
var y = 0;

// Center of rectangle
var cx=50, cy=50;
var angle = 0;

/**
* Ran every tick. Should make the rectangle move diagonally right/down 
* while spinning around it's center
*/

function running(){
  updateRectanglePosition();


    // Get the matrix of the parent element
    var rect = document.getElementById('rectangle');
    var ctm = rect.parentNode.getScreenCTM();
    var matrix = new DOMMatrix([ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f]);

    // Translate the center of the group to 0,0 of parent matrix
    matrix = matrix.translate(50, 50);
	
    // Rotate around this point 
    matrix = matrix.rotate(angle % 360);
	matrix = matrix.translate(x, -250);
    // Translate to actual x,y position
    //matrix = matrix.translate(x , y);

  rect.setAttribute('transform', matrix.inverse().toString());

  if(timer){
    timer = setTimeout(running, 100);
  }
}

// Updates rectangle position every frame
function updateRectanglePosition()
{
  x -= 10;
  y += 1;
  angle = (angle + 10);
}

// Starts and stops the setTimeout timer that runs the animation
function startAnimation() {
  started = !started;
  if(started){
    if(timer){
      clearTimeout(timer);
    }
    timer = setTimeout(running, 100);
  }
  else {
    timer = clearTimeout(timer);
  }
}

// Resets the variables
function reset(){
  x = 0;
  y = 0;
  angle = 0;
}

 document.getElementById('startBtn').addEventListener('click', startAnimation);

  </script>

  
 </body> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...