16.12.2017, 20:44
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 157
|
|
Плавная прорисовка в canvas
Добрый вечер. Недавно начала изучать работу с canvas. Более и менее разобрался с простыми фигурами. Перешел вот к анимациями и получается скудновато.
Например, вот я нарисовал шестиугольник. Хочу что бы стороны рисовались плавно.
То есть линия первой стороны выходит из начальной точки и движется к своей конечно точке, от туда начинает рисоваться следующая сторона и так все по кругу.
Идея есть а с реализацией туго. Есть понимание как прямую линию или диагональ нарисовать плавно (начинать с x = 0, y = 0, и в цикле добавлять по одному), но с сложной фигурой это не особо выполнимо как по мне.
Прошу помощи, советом или делом, кому как не жалко)
|
|
16.12.2017, 21:01
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
Сообщение от smart-create
|
и в цикле добавлять по одному),
|
JS-Анимация
|
|
16.12.2017, 22:03
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
анимация 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>
|
|
18.12.2017, 12:33
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 157
|
|
рони, большое спасибо. Я посидел по разбирался, в итоге решил учится не на canvas а на svg, его я больше пока понимаю.
Вот попытался сделать бесконечную простенькую анимацию, вот она (код прилагается)
И все бы хорошо, но где то после 5-7 цикла она начинает лажить и в итоге выдает ошибку "Uncaught RangeError: Maximum call stack size exceeded"
пытался менять requestAnimationFrame на setInterval с частотой 24. в этом случае лагов и ошибок нет но анимация не достаточно плавная, а если поменять 24 на 20 к примеру - анимация становится плавнее, но ошибки и лаги как и в случае с requestAnimationFrame.
Подскажите пожалуйста что не так я делаю в этом случае?
|
|
18.12.2017, 13:08
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
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>
|
|
18.12.2017, 13:45
|
|
Профессор
|
|
Регистрация: 07.03.2011
Сообщений: 1,138
|
|
Сообщение от smart-create
|
Подскажите пожалуйста что не так я делаю в этом случае?
|
Ты создаешь замыкание передавая как параметр имя текущего функционального выражения (animate).
При следующем вызове снова создается замыкание которое имеем ссылку на текущее замыкание и так цепочка скопов растет пока не закончатся ресурсы системы. Работает почти как рекурсия.
И блин кешируйте выборки в jQuere не обязательно каждые 5 милисек. производить полный поиск по всему дереву объектов.
|
|
18.12.2017, 13:47
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 157
|
|
рони, то есть попытка применить requestAnimationFrame или setInterval для svg была ошибочная в корне?
|
|
18.12.2017, 13:55
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 157
|
|
MallSerg, большое спасибо за толкования. Но я видимо не корректно поставил вопрос. Корень возникновения проблемы мне приблизительно понятен. Но мне не известно решение. Так же я к сожалению не знаком с понятием "кешируйте выборки в jQuere". Буду очень признателен если поможете с этими моментами
|
|
18.12.2017, 14:05
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
Сообщение от smart-create
|
то есть попытка применить requestAnimationFrame или setInterval для svg была ошибочная в корне?
|
requestAnimationFrame - это правильно, смотрите сообщения №2 и №3, setInterval имхо: зло и нет ни одного кода, где бы он был необходим.
кеширование это один раз создать переменную var a = $(".data_gradient");
и потом использовать только a
|
|
18.12.2017, 14:12
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,112
|
|
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();
});
|
|
|
|