• Konva离屏缓存


    前言

    cache实例方法定义在Node基类上,通过该方法可以实现图形缓存,在Konva中Stage、Layer、Group、Shape等所有容器类和图形类都直接或间接继承了Node基类,故而都可以使用缓存方法。本篇文章就是探讨Konva背后的缓存机制,版本是v9.2.1。

    Konva离屏缓存

    就以下面的实例进行整体过程的分析:

          const stage = new Konva.Stage({
            container: 'root',
            width: window.innerWidth,
            height: window.innerHeight,
          });
          const layer = new Konva.Layer();
          const star = new Konva.Star({
            innerRadius: 20,
            outerRadius: 50,
            fill: 'red',
            stroke: 'black',
            strokeWidth: 5,
            numPoints: 5,
            x: 60,
            y: 60,
            shadowOffset: { x: 5, y: 5 },
            shadowColor: 'black',
            shadowBlur: 5,
            shadowOpacity: 0.5,
            shadowForStrokeEnabled: false,
          });
    
          star.cache()
          layer.add(star);
          stage.add(layer);
    
    	  // 创建10个Star
          let clone;
          for (var n = 0; n < 10; n++) {
            clone = star.clone({
              x: Math.random() * stage.width(),
              y: Math.random() * stage.height(),
            });
            clone.cache();
            layer.add(clone);
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    上面的实例就是创建11个Star图形,每个图形都会调用cache实例方法进行缓存。

    cache处理流程

    cache实例方法的处理逻辑如下:
    Cache处理逻辑
    当图形对象调用缓存方法cache时,其逻辑总结如下:

    • 首先内部会计算当前图形的包围框信息(大小以及位置),通过包围框的大小信息创建cachedSceneCanvas、cachedFilterCanvas、cachedHitCanvas三个Canvas图层,这三个图层不会挂载在页面上仅仅位于内存中
    • 然后将当前图形绘制到CachedSceneCanvas、CachedHitCanvas中
    • 最后会将相关包围框位置信息以及CachedCanvas保存到_cache实例属性中,用于后续的逻辑处理

    需要注意的是总会保存最新信息到_cache实例属性中,如果多次调用cache实例方法时会先删除_cache中存在的key,然后重新添加,逻辑如下:

    cache() {
    	...
    	this._cache.delete(CANVAS);
    	...
        this._cache.set(CANVAS, {
        	scene: cachedSceneCanvas,
        	ilter: cachedFilterCanvas,
            hit: cachedHitCanvas,
            x: x,
            y: y,
        });
        ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    缓存图形的渲染

    Konva是批量渲染图形的,在之前
    Konva批量渲染
    文章中就有较为详细的处理逻辑,缓存图形的渲染逻辑也包含在其中,只是之前并没有具体说明。实际上针对缓存图形的渲染处理具体逻辑如下:

    _drawCachedSceneCanvas(context) {
      context.save();
      ...
      var cacheCanvas = this._getCachedSceneCanvas();
      var ratio = cacheCanvas.pixelRatio;
      context.drawImage(cacheCanvas._canvas, 0, 0, cacheCanvas.width / ratio, cacheCanvas.height / ratio);
      context.restore();
    }
    drawScene(can, top) {
      ...
      if (cachedSceneCanvas) {
        context.save();
        ...
        this._drawCachedSceneCanvas(context);
        context.restore();
      } else {
        this._drawChildren('drawScene', canvas, top);
      }
      return this;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    核心逻辑就是drawImage方法,对于缓存的图形实际上就是使用drawImage将其保存的CachedCanvas绘制到SceneCanvas中,而不是调用Canvas API进行具体的绘制。

    总结

    Konva缓存本质上就是创建位于内存中的Canvas图层,将当前图形绘制到CachedCanvas中,之后渲染时使用drawImage将整个CachedCanvas绘制到场景中,从而减少向CPU发送操作指令进而实现性能的提升。

    从上面梳理逻辑知道每调用一次cache实例方法都会创建三个CachedCanvas并保存到对应属性中,如果图形很多,这是非常大的性能消耗,所以cache不能随便使用。实际上Konva官网也有cache的使用建议,可以去具体看看,这里就不再说明了。

  • 相关阅读:
    计算机毕业设计Java居民个人健康信息与个人健康服务综合平台(源码+mysql数据库+系统+lw文档)
    监控摄像头连接NAS,实现监控管理一体化
    web渗透测试----5、暴力破解漏洞--(1)SSH密码破解
    c++设计模式
    位逻辑运算符
    java-自定义数组的工具类
    FRP内网穿透
    多线程(pthread库)
    MySQL 增删改查获取资料等使用方法
    Geode安装管理指南
  • 原文地址:https://blog.csdn.net/s1879046/article/details/133347072