Konva.js在移动设备上非常滞后

时间:2018-04-21 19:20:01

标签: javascript konvajs

我想开始使用Konva.js库。它在我的PC上的浏览器(chrome)看起来非常棒,并且具有很棒的功能。我创建了一些代码来制作一些非常简单的动画(移动和旋转)。但是当我试图在移动设备上或甚至在Safari浏览器中运行我的网页时,它开始变得非常迟钝。此外,当我将四个对象(图像)设置为一个动作时,浏览器崩溃了。

我做了一些测试,并意识到即使是可拖动的对象在移动设备上也是滞后的。 (当我试图移动它们时,它们的动作非常缓慢而且不稳定)。

有没有办法优化它。 (我尝试过推荐的batchDraw()函数,但没有帮助)?如何使运动流畅?如果目前不可能,将来是否会有一些优化可能性?

这是我的代码......但显然你必须在手机上运行才能看到效果。要激活效果,请单击(触摸)图像。

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>

1 个答案:

答案 0 :(得分:0)

有很多方法可以改善效果。

您可以在此处阅读很多提示:https://konvajs.github.io/docs/performance/All_Performance_Tips.html

你的舞台看起来很简单,所以在移动设备上表现应该非常好。

一些提示:

  1. 请勿使用setInterval。使用requestAnimationFrame。动画会更顺畅
  2. 使用layer.batchDraw()
  3. 如果可能,尝试将动画对象移动到另一个图层,这样您就不需要重绘所有节点