Javascript Путь изменения кривой SVG при C - PullRequest
1 голос
/ 08 июля 2020
Заранее спасибо. Я пытаюсь переместить элемент кривой SVG в html, используя javascript. Я хотел бы изменить путь моего svg так, чтобы моя синяя кривая трансформировалась как красная кривая, но с переходом, чтобы увидеть смещение кривой. Я понимаю, как получить или создать элемент, но я не уверен, как установить атрибут «d», например, изменять каждый «c» в пути.

alert(document.getElementById('s3').getAttribute('d'));
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>


    <svg viewBox="0 0 990 180" height="200" width="1100" id="mySVG">

        <g> 
            <path id="s2" d="M 241,128 C 272,113 293,152 369,125 C 434,80 471,72 580,114  " 
            fill="none" stroke="red" stroke-width="5px" />

            <path id="s3" d="M 241,128 C266,131 298,100 369,125 C 441,150 482,151 580,114  " 
            fill="none" stroke="blue" stroke-width="5px" />
           

        </g>

    </svg>
    <script src="app.js"></script>
</body>
</html>

1 Ответ

1 голос
/ 08 июля 2020

Надеюсь, я понял ваш вопрос: если вы хотите анимировать от одной кривой к другой, вы можете использовать анимацию SMIL.

Поскольку пути в вашем коде имеют одинаковое количество и тот же тип команд, что и вы может использовать элемент <animate> для анимации атрибута d.

Атрибут values представляет собой список значений, разделенных точкой с запятой (;) Первое и последнее значение - это атрибут d кривой. Второе значение - это атрибут d другого.

В моем коде продолжительность анимации составляет 5 секунд: dur="5s

<svg viewBox="235 80 350 70" width="300" id="mySVG">

  <g>
    <path id="s2" d="M 241,128 
             C 272,113 293,152 369,125 
             C 434,80 471,72 580,114" fill="none" stroke="red" stroke-width="5px">

    </path>

    <path id="s3" d="M 241,128 
             C266,131 298,100 369,125 
             C 441,150 482,151 580,114" fill="none" stroke="blue" stroke-width="5px">
      <animate attributeName="d" attributeType="XML" values="M 241,128 
             C266,131 298,100 369,125 
             C 441,150 482,151 580,114;    
                 
             M 241,128 
             C 272,113 293,152 369,125 
             C 434,80 471,72 580,114;
                 
             M 241,128 
             C266,131 298,100 369,125 
             C 441,150 482,151 580,114; " dur="5s" repeatCount="indefinite" />
    </path>

  </g>
</svg>

ОБНОВЛЕНИЕ

OP комментирует:

могу ли я сделать это в javascript?

Сделать это в javascript сложнее. Вам нужно будет установить массив значений и массив целевых значений и пересчитывать каждое значение кривой с каждым кадром анимации. Далее идет пример анимации синей кривой при нажатии:

Пожалуйста, прочтите комментарии в коде.

//I've hard coded the values and the target array
//you may want to do it dimamicaly from the d attribute

let vals = [
  ["M", 241, 128],
  ["C", 272, 113, 293, 152, 369, 125],
  ["C", 434, 80, 471, 72, 580, 114]
];

let target = [
  ["M", 241, 128],
  ["C", 266, 131, 298, 100, 369, 125],
  ["C", 441, 150, 482, 151, 580, 114]
];

//the request animation id
let rid = null;
//build the memory array used for the animation
let memory = [];
for (let i = 0; i < vals.length; i++) {
  memory[i] = [];
  memory[i][0] = target[i].slice();
  memory[i][1] = vals[i].slice();
}

function Frame() {
  rid = window.requestAnimationFrame(Frame);
  updateValues();
  updatePath();
}

window.addEventListener("load", updatePath, false);


// I'm animating the curve on click
svg.addEventListener(
  "mousedown",
  function () {
  // if there is an animation running stop it before start another one
    if (rid) {
      window.cancelAnimationFrame(rid);
      rid = null;
    }
    
    //reverse the animation
    for (let i = 0; i < memory.length; i++) {
      memory[i].reverse();
      target[i] = memory[i][1].slice();
    }
    //call the Frame function
    Frame();
  },
  false
);

function updateValues() {
//a function to update all the values of the curve except the move to part that is not changing anyway
  for (let i = 1; i < vals.length; i++) {
    for (let j = 1; j < vals[i].length; j++) {
      let dist = target[i][j] - vals[i][j];
      let vel = dist / 10;
      vals[i][j] += vel;
    }
  }
}
//a function to reset the value of the d attribute
function updatePath() {
  let d = `M${vals[0][1]},${vals[0][2]}`;
  for (let i = 1; i < vals.length; i++) {
    d += `C${vals[i][1]},${vals[i][2]},${vals[i][3]},${vals[i][4]},${vals[i][5]},${vals[i][6]}`;
  }
  s3.setAttributeNS(null, "d", d);
}
svg{border:1px solid}
<svg id="svg" viewBox="235 80 350 70" width="300" id="mySVG">
  <g>
    <path id="s2" d="M 241,128 
             C 272,113 293,152 369,125 
             C 434,80 471,72 580,114" fill="none" stroke="red" stroke-width="5px">
    </path>
    <path id="s3" d="M 241,128 
             C266,131 298,100 369,125 
             C 441,150 482,151 580,114" fill="none" stroke="blue" stroke-width="5px">    
    </path>
  </g>
</svg>
...