Анимация рисования пути на холсте HTML5 - PullRequest
0 голосов
/ 08 ноября 2018

Моя проблема в том, как анимировать рисунок пути между двумя точками.

Рассмотрим изогнутую линию или путь между двумя точками, A и B. Я могу легко нарисовать это на холсте, используя функции рисования линий в Konvajs.

Однако на самом деле я хочу анимировать раскрытие линии так, чтобы оно начиналось с точки А и постепенно приближалось к точке Б. Раскрытие должно быть анимированным, чтобы я мог применять приятные послабления.

В качестве сопоставимого примера см. Краткое видео на этом сайте https://coggle.it/, где на видео показано создание нового блока, и рисуется линия, соединяющая его со старым.

Ответы [ 3 ]

0 голосов
/ 09 ноября 2018

Мое решение с анимацией:

    var width = window.innerWidth;
    var height = window.innerHeight;

    // Set up the canvas / stage
    var stage = new Konva.Stage({
        container: 'container',
        width: width,
        height: height
    });

    // Add a layer
    var layer = new Konva.Layer({
        draggable: false
    });
    stage.add(layer);

    // show where the start of the path is.
    var circle = new Konva.Circle({
        x: 66,
        y: 15,
        radius: 5,
        stroke: 'red'
    })
    layer.add(circle);

    // draw a path.
    var path = new Konva.Path({
        x: 0,
        y: 0,
        data: 'M66 15 L75 100 L225 120 L100 17 L66 15',
        stroke: 'green'
    });

    // get the path length and set this as the dash and dashOffset. 
    var pathLen = path.getLength();
    path.dashOffset(pathLen);
    path.dash([pathLen]);

    // make some animation with stop
    var anim = new Konva.Animation(function (frame) {
        var dashLen = pathLen - frame.time / 5;
        path.dashOffset(dashLen);
        if (dashLen < 0) {
            anim.stop();
        }
    }, layer);

    anim.start();

    layer.add(path)
    stage.draw();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.5.1/konva.js"></script>
<div id='container' style="display: inline-block; width: 300px, height: 200px; background-color: silver; overflow: hidden; position: relative;"></div>
<div id='img'></div>
0 голосов
/ 10 ноября 2018

А вот альтернатива анимированной версии @ Roxane, но с использованием анимации.

var width = window.innerWidth;
    var height = window.innerHeight;

    // Set up the canvas / stage
    var stage = new Konva.Stage({
        container: 'container',
        width: width,
        height: height
    });

    // Add a layer
    var layer = new Konva.Layer({
        draggable: false
    });
    stage.add(layer);

    // show where the start of the path is.
    var circle = new Konva.Circle({
        x: 66,
        y: 15,
        radius: 5,
        stroke: 'red'
    })
    layer.add(circle);

    // draw a path.
    var path = new Konva.Path({
        x: 0,
        y: 0,
        data: 'M66 15 L75 100 L225 120 L100 17 L66 15',
        stroke: 'green'
    });

    // get the path length and set this as the dash and dashOffset. 
    var pathLen = path.getLength();
    path.dashOffset(pathLen);
    path.dash([pathLen]);

    layer.add(path);  // have to add to layer for tweening.
    
    // create the tween
    var tween = new Konva.Tween({
        node: path,
        dashOffset: 0,
        easing: Konva.Easings['BounceEaseOut'],
        duration: 1.5
    });
     tween.play(); // execute the tween

    stage.draw();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.5.1/konva.js"></script>
<div id='container' style="display: inline-block; width: 300px, height: 200px; background-color: silver; overflow: hidden; position: relative;"></div>
<div id='img'></div>
0 голосов
/ 09 ноября 2018

Вот потенциальный ответ (особая благодарность @ markov00 за ту же технику в SVG). Он работает путем манипулирования атрибутами пути dashOffset и dash. В посте Джейка Арчибальда есть отличное объяснение техники , которая также включает в себя интерактивный эксперимент со слайдерами, который я нашел очень полезным.

Я попытался сделать демонстрацию как можно более легкой и просто показать технику - хотя я добавил слайдер и некоторый пользовательский интерфейс, чтобы помочь понять процесс. Использование jquery только для частей пользовательского интерфейса, которые не нужны для техники.

Пара баллов:

  • Демо здесь использует путь из 3 прямых отрезков. Но я пробовал кривые и комбинации путей, и техника работает и в этих случаях - поэтому любой путь должен работать.
  • Я обнаружил, что использование команды close-path (z) на пути приводило к тому, что функция длины пути была короткой на истинном расстоянии. Это выглядит как количество пути, оставшегося заштрихованным или зазубренным с любого конца, причем размер зависит от перехода между первым и последним, чтобы закрыть путь.
  • Длина пути практически всегда будет десятичной, так что не пытайтесь делать все как целые числа, так как в конечном итоге вы обнаружите, что ваш штрих немного длинен или короток.

Чтобы применить это для анимации, замедления и т. Д., Возьмите пару строк из события смены ползунка и вставьте их в обратный вызов фрейма, манипулируя математикой в ​​соответствии с вашим случаем.

// Set up the canvas / stage
var stage = new Konva.Stage({container: 'container1', width: 320, height: 180});

// Add a layer
var layer = new Konva.Layer({draggable: false});
stage.add(layer);

// show where the start of the path is.
var circle = new Konva.Circle({
  x: 66,
  y: 15,
  radius: 5,
  stroke: 'red'
 })
 layer.add(circle);

// draw a path.
    var path = new Konva.Path({
      x: 0,
      y: 0,
      data: 'M66 15 L75 100 L225 120 L100 17 L66 15',
      stroke: 'green'
    });

// get the path length and set this as the dash and dashOffset. 
var pathLen = path.getLength();
path.dashOffset(pathLen);
path.dash([pathLen]);

layer.add(path)
stage.draw();

// Some UI bits
$('#dist').attr('max', parseInt(pathLen)); // set slider max to length of path
$('#pathLen').html('Path : ' + pathLen); // display path length

// jquery event listener on slider change
$('#dist').on('input', function(){

  // compute the new dash lenth as original path length - current slider value. 
  // Means that dashLen initially = path len and moves toward zero as slider val increases.
  var dashLen = pathLen - $(this).val();;
  path.dashOffset(dashLen);   // set new value
  layer.draw();               // refresh the layer to see effect

  // update the UI elements      
  $('#dashLen').html('Dash: ' + dashLen);
  $('#pathPC').html(parseInt(100-(100 * (dashLen/pathLen)), 10) + '%');

})
.info 
{
padding-left: 20px;

}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/2.5.1/konva.js"></script>
<div class="slidecontainer">
  <input class='slider' id='dist' type="range" min="0" max="100" value="0" class="slider" id="myRange"/>
  <span class='info' id='pathPC'></span>
  <span class='info' id='pathLen'></span>
  <span class='info' id='dashLen'></span>
</div>
<div id='container1' style="display: inline-block; width: 300px, height: 200px; background-color: silver; overflow: hidden; position: relative;"></div>
<div id='img'></div>
...