【问题标题】:Konva.js is very laggy on mobile devicesKonva.js 在移动设备上非常滞后
【发布时间】:2018-10-02 05:16:24
【问题描述】:

我想开始使用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>

【问题讨论】:

  • 您的网站有错误,Uncaught TypeError: Cannot read property 'time' of undefined
  • @Derek 是的,我知道,这只是因为 setinterval 运行得比创建图像要快,但这不是问题。我可以解决它,但感谢您的评论

标签: javascript konvajs


【解决方案1】:

有很多方法可以提高性能。

你可以在这里阅读很多提示:https://konvajs.github.io/docs/performance/All_Performance_Tips.html

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

一些提示:

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

【讨论】:

  • 感谢您的回答。使用 requestAnimationFrame 对我来说是新信息,谢谢。我试过 layer.batchDraw()。而且我认为我使用了该网站的所有有用提示。我希望我将每个图像都放在单独的图层中。不幸的是它没有帮助。我不确定,我应该编辑问题并更新我的代码吗?
  • @Garenskilled 你可以分享更新的代码。您也可以尝试使用Konva.Tween 对象或node.to() 方法
  • 你说得对,我把所有的节点都放在一层就OK了……谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-13
  • 1970-01-01
相关资源
最近更新 更多