Graffiti画布更新后形状没有重新渲染怎么办?

Mr-红芹 阅读 42

在React组件里用Graffiti的Canvas时,通过state更新了形状数据,但画布上的图形没有变化,这是为什么?

我按官方文档写了一个基础组件,用state保存图形数据,通过setShapes更新后控制台显示数据确实变了,但画布还是显示旧图形。尝试过强制更新组件也没用:


function GraffitiContainer() {
  const [shapes, setShapes] = useState([]);
  
  const handleAddShape = () => {
    const newShape = { type: 'rect', x: 50, y: 50 };
    setShapes([...shapes, newShape]); // 数据更新但没渲染
  };

  return (
    <Graffiti 
      width={800}
      height={600}
      shapes={shapes} // 这里传递了最新的shapes数组
    />
    <button onClick={handleAddShape}>添加矩形</button>
  );
}

查看Graffiti文档发现shapes属性是受控组件,但没找到需要手动触发重绘的说明。有没有可能因为React的更新机制导致Graffiti没接收到变化?或者需要给shapes添加key?

我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
Prog.郭云
这个问题大概率是React的渲染机制和Graffiti的内部实现没对齐导致的。React在更新数组或对象时,如果引用地址没变,子组件可能会认为props没变化,从而跳过更新。你试试给shapes加个key,强制让Graffiti重新渲染。

下面是改过的代码,复制过去试试:


function GraffitiContainer() {
const [shapes, setShapes] = useState([]);

const handleAddShape = () => {
const newShape = { type: 'rect', x: 50, y: 50, id: Date.now() }; // 加个唯一id
setShapes([...shapes, newShape]);
};

return (

width={800}
height={600}
shapes={shapes}
key={shapes.length} // 用shapes长度作为key,确保每次更新都改变key
/>


);
}


这里的关键点有两个:
1. 给每个形状加了个id字段,值是时间戳Date.now(),这样每个形状都有唯一标识,避免潜在的重复问题。
2. 在Graffiti组件上加了key属性,绑定了shapes.length。只要shapes数组长度变化,React就会认为这是个新组件,强制重新渲染。

如果还是不行,那就可能是Graffiti内部有自己的一套状态管理机制,需要手动触发重绘。可以查下它的API文档,看有没有类似forceUpdate或者refresh的方法。

实在搞不定的话,也可以换个思路,直接用ref操作Canvas的原生API,绕开这些坑。不过那是另一个话题了。
点赞 1
2026-02-14 23:19
令狐悦洋
你这个问题我之前也踩过。Graffiti 的 Canvas 组件虽然接收了 shapes 属性,但内部是否监听了 props 变化并触发重绘,这个是关键。

从你贴的代码看,shapes 是传进去了,但你少了一个关键操作:**通知 Graffiti 组件去 redraw**。

Graffiti 的官方文档里有个隐藏的点:当你用受控模式更新 shapes,必须调用 redraw() 方法才会触发重绘。否则它内部不会自动刷新。

你可以这样改:

function GraffitiContainer() {
const [shapes, setShapes] = useState([]);
const graffitiRef = useRef(null); // 用 ref 拿到实例

const handleAddShape = () => {
const newShape = { type: 'rect', x: 50, y: 50 };
setShapes(prev => [...prev, newShape]);

// 更新后立刻 redraw
if (graffitiRef.current) {
graffitiRef.current.redraw();
}
};

return (
<>
<Graffiti
ref={graffitiRef} // 关键!拿到实例
width={800}
height={600}
shapes={shapes}
/>
<button onClick={handleAddShape}>添加矩形</button>
</>
);
}


另外,shapes 不需要加 key,因为 Graffiti 并不是靠 key 来判断是否更新的。

总结下:React 的 state 更新没问题,但 Graffiti 不是自动重绘的 canvas,得手动调 redraw(),否则它就“睡着了”。这种手动刷新的机制在 canvas 类库中挺常见的。
点赞 6
2026-02-04 14:00