Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Плавная прорисовка в canvas (https://javascript.ru/forum/events/71840-plavnaya-prorisovka-v-canvas.html)

smart-create 16.12.2017 20:44

Плавная прорисовка в canvas
 
Добрый вечер. Недавно начала изучать работу с canvas. Более и менее разобрался с простыми фигурами. Перешел вот к анимациями и получается скудновато.

Например, вот я нарисовал шестиугольник. Хочу что бы стороны рисовались плавно.

То есть линия первой стороны выходит из начальной точки и движется к своей конечно точке, от туда начинает рисоваться следующая сторона и так все по кругу.

Идея есть а с реализацией туго. Есть понимание как прямую линию или диагональ нарисовать плавно (начинать с x = 0, y = 0, и в цикле добавлять по одному), но с сложной фигурой это не особо выполнимо как по мне.

Прошу помощи, советом или делом, кому как не жалко)

рони 16.12.2017 21:01

Цитата:

Сообщение от smart-create
и в цикле добавлять по одному),

JS-Анимация

рони 16.12.2017 22:03

анимация canvas
 
smart-create,
документация по анимации по ссылке выше
более продвинутые варианты смотреть у Rise

<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">

  </style>
</head>

<body>
  <input id="go" name="" type="button" value="go" >
  <canvas id="canvas" width="300" height="300" ></canvas>

  <script>
function anim(a) {
    return function() {
        var d = performance.now();
        requestAnimationFrame(function e(b) {
            b = (b - d) / a.duration;
            1 <= b && (b = 1);
            var k = a.easing ? a.easing(b) : b;
            var y = a.from.y + (a.to.y - a.from.y) * k | 0;
            var x = a.from.x + (a.to.x - a.from.x) * k | 0;
            var ctx = a.elem.getContext("2d");
            ctx.beginPath();
            ctx.strokeStyle = a.color;
            ctx.lineWidth = a.width;
            ctx.moveTo(a.from.x, a.from.y);
            ctx.lineTo(x, y);
            ctx.stroke();
            b == 1 && a.callback && a.callback()
            1 > b && requestAnimationFrame(e)
        })
    }
}
function makeEaseInOut(timing) {
  return function(timeFraction) {
    if (timeFraction < .5)
      return timing(2 * timeFraction) / 2;
    else
      return (2 - timing(2 * (1 - timeFraction))) / 2;
  }
}
function circ(timeFraction) {
  return 1 - Math.sin(Math.acos(timeFraction))
}
var EaseInOut = makeEaseInOut(circ);


var canvas = document.querySelector("#canvas"),
    but = document.querySelector("#go"),
    obj = {
        easing: circ,
        color: "#FF0000",
        width: 5,
        from: {x : 20,y : 20},
        to: {x : 100,y : 200},
        duration: 3 * 1000,
        elem: canvas,
        callback: function() {
            anim(obj2)()
        }
    },
    obj2 = {
        easing: circ,
        color: "#FF0000",
        width: 5,
        from: {x : 100,y : 200},
        to: {x : 200,y : 20},
        duration: 3 * 1000,
        elem: canvas,
        callback: function() {
           anim(obj3)()
        }
    },
     obj3 = {
        easing: circ,
        color: "#FF0000",
        width: 5,
        from: {x : 200,y : 20},
        to: {x : 20,y : 20},
        duration: 2 * 1000,
        elem: canvas,
        callback: function() {
           alert("test")
        }
    }

    ;


but.addEventListener("mousedown", anim(obj));
</script>
</body>
</html>

smart-create 18.12.2017 12:33

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

Вот попытался сделать бесконечную простенькую анимацию, вот она (код прилагается)

И все бы хорошо, но где то после 5-7 цикла она начинает лажить и в итоге выдает ошибку "Uncaught RangeError: Maximum call stack size exceeded"

пытался менять requestAnimationFrame на setInterval с частотой 24. в этом случае лагов и ошибок нет но анимация не достаточно плавная, а если поменять 24 на 20 к примеру - анимация становится плавнее, но ошибки и лаги как и в случае с requestAnimationFrame.

Подскажите пожалуйста что не так я делаю в этом случае?

рони 18.12.2017 13:08

jquery animate svg
 
smart-create,
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
   <script>
$(function() {
  function a() {
    $({offset:100}).delay(400).animate({offset:0}, {duration:2000, step:function(a, b) {
      $(".data_gradient").attr(b.prop, a + "%");
    }, complete:a});
  }
  a();
});
  </script>
</head>

<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Слой_1" x="0px" y="0px" viewBox="0 0 1642 352" xml:space="preserve">
<path class="st0" d="M1011.8,345.1L955,288.4H458.8c-2-8.7-9.9-15.2-19.2-15.2c-10.9,0-19.7,8.8-19.7,19.7  c0,10.9,8.8,19.7,19.7,19.7c10.2,0,18.7-7.8,19.6-17.8h493.1l56.8,56.8H1641v-6.4H1011.8z M439.7,306.2c-7.3,0-13.3-6-13.3-13.3  c0-7.3,6-13.3,13.3-13.3c7.3,0,13.3,6,13.3,13.3C452.9,300.2,447,306.2,439.7,306.2z"/>
<path class="st1" d="M979,279l-59.7-59.7H683.5c-1.5-6-6.8-10.4-13.3-10.4c-7.5,0-13.7,6.1-13.7,13.7c0,7.5,6.1,13.7,13.7,13.7  c6.4,0,11.8-4.5,13.3-10.4h233.2l59.7,59.7H1641V279H979z M670.2,229.8c-4,0-7.2-3.2-7.2-7.2c0-4,3.2-7.2,7.2-7.2  c4,0,7.2,3.2,7.2,7.2C677.4,226.5,674.2,229.8,670.2,229.8z"/>
<path class="st2" d="M956,318.4l-54-54h-64.4v1.3c0-2.8-2.3-5.1-5.1-5.1c-2.8,0-5.1,2.3-5.1,5.1s2.3,5.1,5.1,5.1  c2.8,0,5.1-2.3,5.1-5.1v1.3H901l54,54h686v-2.6H956z"/>
<path class="st3" d="M1641,251h-619.9c-0.6-2.2-2.6-3.8-4.9-3.8c-2.8,0-5.1,2.3-5.1,5.1c0,2.8,2.3,5.1,5.1,5.1c2.4,0,4.4-1.7,5-3.9  H1641V251z"/>
<path class="st4" d="M1026.1,301.3l-52.8-52.8H761c-3.5,0-6.4-2.9-6.4-6.4l0,0H752v14h2.6v0c0-3.5,2.9-6.4,6.4-6.4h211.8l52.8,52.8  H1641v-1.3H1026.1z"/>
<polygon class="st5" points="962.1,222.9 937.7,198.5 806.7,198.5 806.7,195.5 801.6,195.5 801.6,204.1 806.7,204.1 806.7,201.1   936.6,201.1 961.1,225.5 1641,225.5 1641,222.9 "/>
<path class="test st6" fill="url(#linear-gradient)" d="M1009.1-0.1l-56.8,56.8H715.4c-1-10-9.4-17.8-19.6-17.8c-10.9,0-19.7,8.8-19.7,19.7c0,10.9,8.8,19.7,19.7,19.7  c9.3,0,17.1-6.5,19.2-15.2h240l56.8-56.8H1641v-6.4H1009.1z M695.8,71.8c-7.3,0-13.3-6-13.3-13.3s6-13.3,13.3-13.3  c7.3,0,13.3,6,13.3,13.3S703.1,71.8,695.8,71.8z"/>
<path class="st7" d="M976.3,71.1l-59.7,59.7H763.3c-1.5-6-6.8-10.4-13.3-10.4c-7.5,0-13.7,6.1-13.7,13.7c0,7.5,6.1,13.7,13.7,13.7  c6.4,0,11.8-4.5,13.3-10.4h156L979,77.6h662v-6.4H976.3z M750.1,141.2c-4,0-7.2-3.2-7.2-7.2c0-4,3.2-7.2,7.2-7.2  c4,0,7.2,3.2,7.2,7.2C757.3,138,754.1,141.2,750.1,141.2z"/>
<path class="st8" d="M905.4,35.6l-54,54h-80.8c-0.6-2.2-2.6-3.9-5-3.9c-2.8,0-5.1,2.3-5.1,5.1c0,2.8,2.3,5.1,5.1,5.1  c2.4,0,4.4-1.6,5-3.9h81.9l54-54H1641v-2.6H905.4z"/>
<path class="st9" d="M1641,102.9h-551.1c-0.6-2.2-2.6-3.9-5-3.9c-2.8,0-5.1,2.3-5.1,5.1c0,2.8,2.3,5.1,5.1,5.1  c2.4,0,4.4-1.6,4.9-3.8H1641V102.9z"/>
<polygon class="st10" points="1641,203.4 987.5,203.4 987.5,200 984.9,200 984.9,208.1 987.5,208.1 987.5,204.7 1641,204.7 "/>
<polygon class="st11" points="1054.2,131 1029.8,155.5 870.4,155.5 870.4,152.5 865.2,152.5 865.2,161 870.4,161 870.4,158   1030.9,158 1055.3,133.6 1641,133.6 1641,131 "/>
<polygon class="st12" points="1641,153.8 1090,153.8 1090,151.2 1084.8,151.2 1084.8,159.8 1090,159.8 1090,156.4 1641,156.4 "/>
<path class="st13" d="M1641,174.3H19.9c-1.4-4.1-5.2-7-9.7-7c-5.7,0-10.3,4.6-10.3,10.3c0,5.7,4.6,10.3,10.3,10.3c4.5,0,8.3-3,9.7-7  H1641V174.3z"/>
<linearGradient id="linear-gradient">
    <stop class="data_gradient" offset="100%" stop-color="transparent"></stop>
    <stop class="data_gradient" offset="100%" stop-color="gold"></stop>
  </linearGradient>
</svg>
</body>
</html>

MallSerg 18.12.2017 13:45

Цитата:

Сообщение от smart-create (Сообщение 473155)
Подскажите пожалуйста что не так я делаю в этом случае?

Ты создаешь замыкание передавая как параметр имя текущего функционального выражения (animate).
При следующем вызове снова создается замыкание которое имеем ссылку на текущее замыкание и так цепочка скопов растет пока не закончатся ресурсы системы. Работает почти как рекурсия.

И блин кешируйте выборки в jQuere не обязательно каждые 5 милисек. производить полный поиск по всему дереву объектов.

smart-create 18.12.2017 13:47

рони, то есть попытка применить requestAnimationFrame или setInterval для svg была ошибочная в корне?

smart-create 18.12.2017 13:55

MallSerg, большое спасибо за толкования. Но я видимо не корректно поставил вопрос. Корень возникновения проблемы мне приблизительно понятен. Но мне не известно решение. Так же я к сожалению не знаком с понятием "кешируйте выборки в jQuere". Буду очень признателен если поможете с этими моментами

рони 18.12.2017 14:05

Цитата:

Сообщение от smart-create
то есть попытка применить requestAnimationFrame или setInterval для svg была ошибочная в корне?

requestAnimationFrame - это правильно, смотрите сообщения №2 и №3, setInterval имхо: зло и нет ни одного кода, где бы он был необходим.
кеширование это один раз создать переменную var a = $(".data_gradient");
и потом использовать только a

рони 18.12.2017 14:12

smart-create,
вариант без кеширования
$(function() {
  function a() {
    $({offset:100}).delay(400).animate({offset:0}, {duration:2000, step:function(a, b) {
      $(".data_gradient").attr(b.prop, a + "%");  //каждый раз идёт поиск элементов ".data_gradient"
    }, complete:a});
  }
  a();
});


вариант с "кешем"
$(function() {
  var el = $(".data_gradient");  //поиск  всего 1 раз
  function a() {
    $({offset:100}).delay(400).animate({offset:0}, {duration:2000, step:function(a, b) {
      el.attr(b.prop, a + "%"); // поиска элементов нет
    }, complete:a});
  }
  a();
});

smart-create 18.12.2017 14:34

рони, в который раз - большое спасибо) С кеширование все оказалось крайне просто, я об этом даже не подумал.

Последний вопрос который меня мучает - что все таки я не так сделал в своем скрипте, почему он вылетал? Мне важно понять, потому как Ваш вариант безупречно работает с svg - спору нет. Но теперь благодаря Вам с svg я разобрался и хочу продолжить работать с canvas. А там мне нужно использовать requestAnimationFrame. Не хотелось бы и там повторять ошибку

рони 18.12.2017 15:26

Цитата:

Сообщение от smart-create
что все таки я не так сделал в своем скрипте, почему он вылетал?

MallSerg, описал вашу ошибку, вам нужно аккуратнее вызывать функции из функции


Часовой пояс GMT +3, время: 15:53.