Konva.js 在移动设备上非常滞后
Konva.js is very laggy on mobile devices
我想开始使用 Konva.js
库。它在我的电脑上的浏览器 (chrome) 中看起来非常棒,并且具有很棒的功能。我创建了代码来制作一些非常简单的动画(移动和旋转)。但是,当我尝试 运行 在移动设备上什至在 Safari 浏览器中访问我的网页时,它开始变得非常缓慢。而且,当我将四个对象(图像)设置为一个运动时,浏览器崩溃了。
我做了一些测试,发现即使是可拖动的对象在移动设备上也有延迟。 (当我试图移动它们时,它们的移动非常缓慢且不稳定)。
有没有办法优化一下。 (我已经尝试了推荐的batchDraw()
功能,但没有帮助)?怎样才能让动作流畅?如果目前做不到,以后会不会有一些优化的可能?
这是我的代码...但显然您必须 运行 在手机上 phone 才能看到效果。要激活效果,请单击(触摸)图像。
http://bannerteam.tode.cz/konvaAnim/
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Konva animace</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
<script src="https://cdn.rawgit.com/konvajs/konva/2.0.3/konva.min.js"></script>
</head>
<body>
<div id="container"></div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
var lengthOfAnim = 60;
var pos = [{x: 50, y: 50, p: 'A'}, {x: 250, y: 50, p: 'B'}, {x: 450, y: 50, p: 'C'},
{x: 50, y: 250, p: 'D'}, {x: 250, y: 250, p: 'E'}, {x: 450, y: 250, p: 'F'},
{x: 50, y: 450, p: 'G'}, {x: 250, y: 450, p: 'I'}, {x: 450, y: 450, p: 'J'},
{x: 50, y: 650, p: 'K'}, {x: 250, y: 650, p: 'F'}];
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var imageObj = [];
var img = new Image();
var doAnimations = function(i){
switch(i){
case 0:
imageObj[i].img.opacity(1 - imageObj[i].time/lengthOfAnim);
break;
case 1:
if(imageObj[i].time === lengthOfAnim -1)
imageObj[i].img.y(imageObj[i].img.y() + (lengthOfAnim-1)*2);
else
imageObj[i].img.y(imageObj[i].img.y() - 2);
break;
case 2:
imageObj[i].img.opacity(1 - imageObj[i].time/lengthOfAnim);
if(imageObj[i].time === lengthOfAnim -1)
imageObj[i].img.y(imageObj[i].img.y() + (lengthOfAnim-1)*2);
else
imageObj[i].img.y(imageObj[i].img.y() - 2);
break;
case 3:
var parent = imageObj[i].img.getParent();
parent.clipFunc(function(ctx) {
ctx.rect(imageObj[i].img.x() - 75, imageObj[i].img.y() - 75, 75*(1 - imageObj[i].time/lengthOfAnim), 150);
ctx.rect(imageObj[i].img.x() + 75 - 75*(1 - imageObj[i].time/lengthOfAnim) , imageObj[i].img.y() - 75, 75*(1 - imageObj[i].time/lengthOfAnim), 150);
});
break;
case 4:
var parent = imageObj[i].img.getParent();
parent.clipHeight(150*(1 - imageObj[i].time/lengthOfAnim));
break;
case 5:
imageObj[i].img.opacity(1 - imageObj[i].time/lengthOfAnim);
imageObj[i].img.rotation(90*(imageObj[i].time/lengthOfAnim));
break;
case 6:
imageObj[i].img.opacity(1 - imageObj[i].time/lengthOfAnim);
var pom = (1 - imageObj[i].time/lengthOfAnim);
imageObj[i].img.scale({x: pom, y: pom});
break;
case 7:
if(imageObj[i].time === lengthOfAnim -1)
imageObj[i].img.x(imageObj[i].img.x() - (lengthOfAnim-1)*2);
else
imageObj[i].img.x(imageObj[i].img.x() + 2);
imageObj[i].img.move({x: 0, y: 10*(Math.sin(6*Math.PI*(imageObj[i].time/lengthOfAnim)))});
break;
case 8:
imageObj[i].img.rotation(20*Math.sin(6*Math.PI*(imageObj[i].time/lengthOfAnim)));
break;
case 9:
imageObj[i].img.opacity(0.5 + Math.abs((imageObj[i].time/lengthOfAnim-0.5)));
break;
case 10:
imageObj[i].img.draggable(true);
break;
}
}
img.onload = function() {
for(let i = 0; i < pos.length; i++){
var layer = new Konva.Layer();
var yoda = new Konva.Image({
x: pos[i].x + 75,
y: pos[i].y + 75,
image: img,
width: 150,
height: 150,
offset: {
x: 75,
y: 75
}
});
imageObj.push({img: yoda, layer: layer, time: 0});
var charac = new Konva.Text({
x: pos[i].x + 50,
y: pos[i].y + 160,
text: pos[i].p,
fontSize: 30,
fontFamily: 'Calibri',
fill: 'black'
});
if(i === 3){
var group = new Konva.Group({clipFunc:function(ctx) {
ctx.rect(pos[i].x, pos[i].y, 150, 150)
},});
group.add(yoda);
layer.add(group);
}else if(i === 4){
var group = new Konva.Group({clip: {
x : pos[i].x,
y : pos[i].y,
width : 150,
height : 150
},});
group.add(yoda);
layer.add(group);
}else
layer.add(yoda);
layer.add(charac);
stage.add(layer);
yoda.on('click tap', function() {
if(imageObj[i].time === 0)
imageObj[i].time = lengthOfAnim;
});
}
setInterval(function(){
for(var i = 0; i < pos.length; i++){
if(imageObj[i].time > 0){
imageObj[i].time--;
doAnimations(i);
imageObj[i].layer.draw();
}
}
}, 40);
}
img.src = './castle.png';
</script>
<body>
</html>
有很多方法可以提高性能。
您可以在这里阅读很多提示:https://konvajs.github.io/docs/performance/All_Performance_Tips.html
你的舞台看起来很简单,所以在移动设备上表现应该很好。
一些提示:
- 不要使用
setInterval
。使用 requestAnimationFrame
。动画会更流畅
- 使用
layer.batchDraw()
- 如果可能,尝试将动画对象移动到另一层,这样您就不需要重绘所有节点
我想开始使用 Konva.js
库。它在我的电脑上的浏览器 (chrome) 中看起来非常棒,并且具有很棒的功能。我创建了代码来制作一些非常简单的动画(移动和旋转)。但是,当我尝试 运行 在移动设备上什至在 Safari 浏览器中访问我的网页时,它开始变得非常缓慢。而且,当我将四个对象(图像)设置为一个运动时,浏览器崩溃了。
我做了一些测试,发现即使是可拖动的对象在移动设备上也有延迟。 (当我试图移动它们时,它们的移动非常缓慢且不稳定)。
有没有办法优化一下。 (我已经尝试了推荐的batchDraw()
功能,但没有帮助)?怎样才能让动作流畅?如果目前做不到,以后会不会有一些优化的可能?
这是我的代码...但显然您必须 运行 在手机上 phone 才能看到效果。要激活效果,请单击(触摸)图像。
http://bannerteam.tode.cz/konvaAnim/
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Konva animace</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #F0F0F0;
}
</style>
<script src="https://cdn.rawgit.com/konvajs/konva/2.0.3/konva.min.js"></script>
</head>
<body>
<div id="container"></div>
<script>
var width = window.innerWidth;
var height = window.innerHeight;
var lengthOfAnim = 60;
var pos = [{x: 50, y: 50, p: 'A'}, {x: 250, y: 50, p: 'B'}, {x: 450, y: 50, p: 'C'},
{x: 50, y: 250, p: 'D'}, {x: 250, y: 250, p: 'E'}, {x: 450, y: 250, p: 'F'},
{x: 50, y: 450, p: 'G'}, {x: 250, y: 450, p: 'I'}, {x: 450, y: 450, p: 'J'},
{x: 50, y: 650, p: 'K'}, {x: 250, y: 650, p: 'F'}];
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height
});
var imageObj = [];
var img = new Image();
var doAnimations = function(i){
switch(i){
case 0:
imageObj[i].img.opacity(1 - imageObj[i].time/lengthOfAnim);
break;
case 1:
if(imageObj[i].time === lengthOfAnim -1)
imageObj[i].img.y(imageObj[i].img.y() + (lengthOfAnim-1)*2);
else
imageObj[i].img.y(imageObj[i].img.y() - 2);
break;
case 2:
imageObj[i].img.opacity(1 - imageObj[i].time/lengthOfAnim);
if(imageObj[i].time === lengthOfAnim -1)
imageObj[i].img.y(imageObj[i].img.y() + (lengthOfAnim-1)*2);
else
imageObj[i].img.y(imageObj[i].img.y() - 2);
break;
case 3:
var parent = imageObj[i].img.getParent();
parent.clipFunc(function(ctx) {
ctx.rect(imageObj[i].img.x() - 75, imageObj[i].img.y() - 75, 75*(1 - imageObj[i].time/lengthOfAnim), 150);
ctx.rect(imageObj[i].img.x() + 75 - 75*(1 - imageObj[i].time/lengthOfAnim) , imageObj[i].img.y() - 75, 75*(1 - imageObj[i].time/lengthOfAnim), 150);
});
break;
case 4:
var parent = imageObj[i].img.getParent();
parent.clipHeight(150*(1 - imageObj[i].time/lengthOfAnim));
break;
case 5:
imageObj[i].img.opacity(1 - imageObj[i].time/lengthOfAnim);
imageObj[i].img.rotation(90*(imageObj[i].time/lengthOfAnim));
break;
case 6:
imageObj[i].img.opacity(1 - imageObj[i].time/lengthOfAnim);
var pom = (1 - imageObj[i].time/lengthOfAnim);
imageObj[i].img.scale({x: pom, y: pom});
break;
case 7:
if(imageObj[i].time === lengthOfAnim -1)
imageObj[i].img.x(imageObj[i].img.x() - (lengthOfAnim-1)*2);
else
imageObj[i].img.x(imageObj[i].img.x() + 2);
imageObj[i].img.move({x: 0, y: 10*(Math.sin(6*Math.PI*(imageObj[i].time/lengthOfAnim)))});
break;
case 8:
imageObj[i].img.rotation(20*Math.sin(6*Math.PI*(imageObj[i].time/lengthOfAnim)));
break;
case 9:
imageObj[i].img.opacity(0.5 + Math.abs((imageObj[i].time/lengthOfAnim-0.5)));
break;
case 10:
imageObj[i].img.draggable(true);
break;
}
}
img.onload = function() {
for(let i = 0; i < pos.length; i++){
var layer = new Konva.Layer();
var yoda = new Konva.Image({
x: pos[i].x + 75,
y: pos[i].y + 75,
image: img,
width: 150,
height: 150,
offset: {
x: 75,
y: 75
}
});
imageObj.push({img: yoda, layer: layer, time: 0});
var charac = new Konva.Text({
x: pos[i].x + 50,
y: pos[i].y + 160,
text: pos[i].p,
fontSize: 30,
fontFamily: 'Calibri',
fill: 'black'
});
if(i === 3){
var group = new Konva.Group({clipFunc:function(ctx) {
ctx.rect(pos[i].x, pos[i].y, 150, 150)
},});
group.add(yoda);
layer.add(group);
}else if(i === 4){
var group = new Konva.Group({clip: {
x : pos[i].x,
y : pos[i].y,
width : 150,
height : 150
},});
group.add(yoda);
layer.add(group);
}else
layer.add(yoda);
layer.add(charac);
stage.add(layer);
yoda.on('click tap', function() {
if(imageObj[i].time === 0)
imageObj[i].time = lengthOfAnim;
});
}
setInterval(function(){
for(var i = 0; i < pos.length; i++){
if(imageObj[i].time > 0){
imageObj[i].time--;
doAnimations(i);
imageObj[i].layer.draw();
}
}
}, 40);
}
img.src = './castle.png';
</script>
<body>
</html>
有很多方法可以提高性能。
您可以在这里阅读很多提示:https://konvajs.github.io/docs/performance/All_Performance_Tips.html
你的舞台看起来很简单,所以在移动设备上表现应该很好。
一些提示:
- 不要使用
setInterval
。使用requestAnimationFrame
。动画会更流畅 - 使用
layer.batchDraw()
- 如果可能,尝试将动画对象移动到另一层,这样您就不需要重绘所有节点