You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在React中缓存大量重复KonvaJS图形的正确方法

KonvaJS批量图形缓存优化方案

你当前代码的核心问题是同一个ref被绑定到了所有Rect组件上,React的ref在循环中只会指向最后一个渲染的元素,所以只有最后一个矩形被执行了cache(),前面的999个都没生效,这就是缓存没起作用的原因。

下面是两种可行的优化方案:

方案一:每个图形实例独立缓存

创建一个封装好的缓存矩形组件,每个实例内部自行完成缓存操作:

import { Rect } from 'react-konva';
import { useRef, useEffect } from 'react';

const CachedAircraftRect = ({ x, y }) => {
  const rectRef = useRef(null);

  useEffect(() => {
    if (rectRef.current) {
      rectRef.current.cache();
    }
  }, []);

  return (
    <Rect
      ref={rectRef}
      width={120}
      height={40}
      fill={'red'}
      perfectDrawEnabled={false}
      hitStrokeWidth={0}
      shadowForStrokeEnabled={false}
      x={x}
      y={y}
    />
  );
};

export default function AircraftLayer() {
  const { aircrafts } = useAircraft();

  return (
    <Layer>
      {aircrafts.map((aircraft, index) => (
        <CachedAircraftRect 
          key={index} 
          x={aircraft.positionX} 
          y={aircraft.positionY} 
        />
      ))}
    </Layer>
  );
}

方案二:模板克隆(更高效)

因为所有图形样式完全一致,只需要缓存一个模板实例,然后通过克隆模板来生成所有图形,这种方式只需要执行一次缓存操作,性能最优:

import { Layer, Node } from 'react-konva';
import { useState, useEffect } from 'react';
import { useAircraft } from './your-path';

export default function AircraftLayer() {
  const { aircrafts } = useAircraft();
  const [cachedTemplate, setCachedTemplate] = useState(null);

  useEffect(() => {
    // 创建模板并缓存
    const template = new window.Konva.Rect({
      width: 120,
      height: 40,
      fill: 'red',
      perfectDrawEnabled: false,
      hitStrokeWidth: 0,
      shadowForStrokeEnabled: false,
    });
    template.cache();
    setCachedTemplate(template);
  }, []);

  return (
    <Layer>
      {cachedTemplate && aircrafts.map((aircraft, index) => {
        // 克隆模板并修改位置
        const clonedRect = cachedTemplate.clone();
        clonedRect.x(aircraft.positionX);
        clonedRect.y(aircraft.positionY);
        return <Node key={index} node={clonedRect} />;
      })}
    </Layer>
  );
}

额外性能优化建议

  • 必须给循环渲染的元素添加唯一key,避免React不必要的重渲染
  • 可以开启Layer的imageSmoothingEnabled={false}(如果不需要图形平滑效果),进一步提升渲染速度
  • 如果需要频繁更新位置,使用layer.batchDraw()批量处理重绘,减少渲染次数

内容的提问来源于stack exchange,提问作者Jordan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 04:10:09