编程随想 · 2021 年 11 月 22 日 0

react 自定义渲染

本周参加了一次内部的技术分享,分享的主题是甘特图项目技术改造,将原来基于 DOM 的绘制改为基于 canvas 绘制,其采用 React 描述 canvas 的思想让人眼前一亮,大致架构分为了三层:
1. canvas 作为最底层支持
2. 基于 canvas api 封装形状、事件之类的绘图及交互 api
3. 封装 react 组件,管理各形状的绘制及事件监听

对于直接使用 react 组件的用户,几乎不需要感知 canvas 相关的 api,即可完成高性能的凸显绘制。

实现的本质是将 react 提供的自定义渲染接口桥接到了 canvas 绘制 api。

前段时间,在知乎上也看到了一个类似的应用,不过是将 react 写的 UI 渲染到了嵌入式液晶屏上:将 React 渲染到嵌入式液晶屏

得益于 React 的分层设计,react 描述与渲染器分离,我们可以实现 react-reconciler 定义的接口,完成自定义绘制,替换掉我们常用的 react-dom 即可。

说回到借助 react 绘制 canvas,今天在 GitHub 上发现了一个项目也做了类似的工作:react-konva,比如:

const App = () => {
  return (
    <Stage width={window.innerWidth} height={window.innerHeight}>
      <Layer>
        <Text text="Some text on canvas" fontSize={15} />
        <Rect
          x={20}
          y={50}
          width={100}
          height={100}
          fill="red"
          shadowBlur={10}
        />
        <Circle x={200} y={100} radius={50} fill="green" />
        <Line
          x={20}
          y={200}
          points={[0, 0, 100, 0, 100, 100]}
          tension={0.5}
          closed
          stroke="black"
          fillLinearGradientStartPoint={{ x: -50, y: -50 }}
          fillLinearGradientEndPoint={{ x: 50, y: 50 }}
          fillLinearGradientColorStops={[0, 'red', 1, 'yellow']}
        />
      </Layer>
    </Stage>
  );
};

声明式的图形绘制,更加直观。