SVG анимирует кривую Безье, чтобы она росла, следуя стрелке

Я пытаюсь создать стрелку, наконечник которой движется от начальной точки до цели. Перемещение наконечника стрелы было успешно выполнено с помощью подсказки @Robert Longson. Я хочу, чтобы конец древка также следовал за наконечником стрелы и рос на всю его длину. Код приведен ниже, и обратите внимание, что вал не растет вместе со стрелкой, а также заканчивается частичной длиной. Есть ли способ исправить это. Любая помощь будет оценена.

<svg xmlns = "http://www.w3.org/2000/svg" version = "1.1" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "5 0 100 45">
    <style>
        .wire {
            fill: none;
            stroke: red;
            stroke-width: 1px;

            /* Stroke-dasharray property to animate */
            stroke-dasharray: 100%;
            stroke-dashoffset: 100%;
            animation: move linear 5s;
        }

        @keyframes move {
            100% {
                stroke-dashoffset: 0;
            }
        }
    </style>
    <path d = "M10,10 C15,50 95,50 100,10" stroke = "blue" stroke-width = "2" id = "wire" class = "wire">
        <animate>
            <mpath xlink:href = "#wire" />
        </animate>
    </path>
    <!-- acceptable movement along the path but incorrect orientation -->
    <polygon points = "-5,-5 5,0 -5,5 -3,0" fill = "red">
        <animateMotion dur = "5s" repeatCount = "1" rotate = "auto" fill = "freeze">
            <mpath xlink:href = "#wire" />
        </animateMotion>
    </polygon> 
</svg>
Animista - анимация на ходу!
Animista - анимация на ходу!
Если вы веб-дизайнер или разработчик, вы знаете, что добавление анимации на ваш сайт может помочь сделать его более привлекательным и динамичным....
Повысьте уровень своего сайта с помощью анимации CSS и JavaScript: Пошаговое руководство
Повысьте уровень своего сайта с помощью анимации CSS и JavaScript: Пошаговое руководство
Если вы хотите добавить визуальный интерес к своему сайту, то внедрение анимации с помощью CSS и JavaScript может стать отличным способом сделать это....
3
0
372
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вот так я думаю. Обратите внимание, что вы могли бы сделать это и в SMIL.

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

Строка console.info показывает, откуда я взял номер.

console.info(document.getElementsByTagName("path")[0].getTotalLength())
<svg xmlns = "http://www.w3.org/2000/svg" version = "1.1" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "5 0 100 45">
    <style>
        .wire {
            fill: none;
            stroke: red;
            stroke-width: 1px;

            /* Stroke-dasharray property to animate */
            stroke-dasharray: 118.27912902832031;
            stroke-dashoffset: 118.27912902832031;
            animation: move linear 5s forwards;
        }

        @keyframes move {
            100% {
                stroke-dashoffset: 0;
            }
        }
    </style>
    <path d = "M10,10 C15,50 95,50 100,10" stroke = "blue" stroke-width = "2" id = "wire" class = "wire">
        <animate>
            <mpath xlink:href = "#wire" />
        </animate>
    </path>
    <!-- acceptable movement along the path but incorrect orientation -->
    <polygon points = "-5,-5 5,0 -5,5 -3,0" fill = "red">
        <animateMotion dur = "5s" repeatCount = "1" rotate = "auto" fill = "freeze">
            <mpath xlink:href = "#wire" />
        </animateMotion>
    </polygon> 
</svg>

Привет @Robert, я ценю ваш быстрый ответ, большое спасибо. Мне нравится результат, но я хотел бы знать, как вы получили число 118.27912902832031 для stroke-dasharray и stroke-dashoffset? Я хочу знать, как его рассчитать, потому что многие такие стрелки будут создаваться на лету, программно. Может ли это быть проще и лучше с помощью SMIL?

Velusamy Velu 10.12.2020 19:32

Привет, Роберт, пожалуйста, проигнорируй мой предыдущий комментарий. Большое спасибо за вашу помощь. Можно ли это сделать лучше с помощью SMIL без вычисления общей длины? Пожалуйста, дайте мне знать.

Velusamy Velu 10.12.2020 19:43

Вам все равно нужно знать общую длину.

Robert Longson 10.12.2020 19:59

Чтобы переместить курсор и линию одновременно:

  1. Необходимо синхронизировать обе анимации по времени запуска begin = "svg1.click" и длительности dur = "5s"

Максимальная длина кривой 118.3px так

stroke-dashoffset:118.3px;
stroke-dasharray:118.3px;

#wire {
stroke-dashoffset:118.3px;
stroke-dasharray:118.3px;
stroke:red;
stroke-width:2px;
fill:none;
}
<svg id = "svg1" xmlns = "http://www.w3.org/2000/svg" version = "1.1" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "5 0 100 45">
    <style>
       
    </style>
    <path id = "wire" d = "M10,10 C15,50 95,50 100,10" >  
       <!-- Curved path growth animation -->
        <animate
           attributeName = "stroke-dashoffset"
           begin = "svg1.click"
           dur = "5s"
           values = "118.3;0"
           calcMode = "linear"
           fill = "freeze"
           restart = "whenNotActive" /> 
        </animate>
    </path>
    <!-- Cursor -->
    <polygon points = "-5,-5 5,0 -5,5 -3,0" fill = "red">
          <!-- Animating cursor movement along a curved path -->
        <animateMotion begin = "svg1.click" dur = "5s" repeatCount = "1" calcMode = "linear" rotate = "auto" fill = "freeze">
            <mpath xlink:href = "#wire" />
        </animateMotion>
    </polygon>  
    <text x = "40" y = "20" font-size = "6px" fill = "dodgerblue">Click me</text>
</svg>  
<script>
var path = document.querySelector('#wire');
        var len = (path.getTotalLength() );
        console.info("Path length - " + len);
</script>       

ОБНОВЛЯТЬ

в качестве бонуса: Движение вперед - назад

  • Для управления направлением движения добавьте две кнопки и onclick событие
<div>
    <button onclick = "forward.beginElement()">forward</button>
    <button onclick = "back.beginElement()">back</button>
</div>  
  • Направление курсора управляется парой аргументов:
keyPoints = "0;1"
keyTimes = "0;1"
  • Анимация роста или падения линии зависит от значения stroke-dashoffset

values = "118.3;0" - рост линии values = "0;118.3" - линия убавок`

#wire {
stroke-dashoffset:118.3px;
stroke-dasharray:118.3px;
stroke:red;
stroke-width:2px;
fill:none;
}
svg {
width:50%;
height:50%;
}
<div>
    <button onclick = "forward.beginElement()">forward</button>
    <button onclick = "back.beginElement()">back</button>
</div>  
<svg id = "svg1" xmlns = "http://www.w3.org/2000/svg" version = "1.1" xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "5 0 100 45">
    <style>
       
    </style>
    <path id = "wire" d = "M10,10 C15,50 95,50 100,10" >  
       <!-- Animation of filling, growing a line (`forward`)-->
        <animate id = "strokeForward"
           attributeName = "stroke-dashoffset"
           begin = "forward.begin"
           dur = "5s"
           values = "118.3;0"
           calcMode = "linear"
           
           fill = "freeze"
           restart = "whenNotActive" /> 
          <!-- String decrease animation (`back`) -->
       <animate id = "strokeBack"
           attributeName = "stroke-dashoffset"
           begin = "back.begin"
           dur = "5s"
           values = "0;118.3"
           calcMode = "linear"
           fill = "freeze"
           restart = "whenNotActive" /> 
       
    </path>
    <!-- Cursor -->
    <polygon points = "-5,-5 5,0 -5,5 -3,0" fill = "red">
          <!-- Animating cursor movement along a curved path (`forward`) -->
    <animateMotion
          id = "forward"
          begin = "indefinite"
          dur = "5s"
          repeatCount = "1"
          calcMode = "linear"
          rotate = "auto"
          fill = "freeze"
          keyPoints = "0;1"
          keyTimes = "0;1"
          restart = "whenNotActive">
            <mpath xlink:href = "#wire" />
        </animateMotion>    
        <!-- Animating cursor movement along a curved path (`back`) -->
         <animateMotion
          id = "back"
          begin = "indefinite"
          dur = "5s"
          repeatCount = "1"
          calcMode = "linear"
          rotate = "auto"
          fill = "freeze"
          keyPoints = "1;0"
          keyTimes = "0;1"
          restart = "whenNotActive">
            <mpath xlink:href = "#wire" />
        </animateMotion>  
    </polygon>  
    </svg> 

@Velusamy Velu Добавлено несколько строк JS, показывающих максимальную длину строки в консоли.

Alexandr_TT 10.12.2020 20:24

@Alexander_TT - я ценю вашу помощь. Спасибо вам.

Velusamy Velu 10.12.2020 23:41

Другие вопросы по теме