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);
      }

上面的实例就是创建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,
    });
    ...
缓存图形的渲染

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;
}

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

总结

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值