这几天一直在研究对象如何进行选中的实现,下文提供了非常好的一个思路。
聊聊canvas的元素选中 - 知乎

但是一直苦于不知道如何进行这部分的实现。后来灵光一闪似乎明白了如何实现。

第一步:索引转 style

  1. makeMaskStyleByIndex = (index: number) => {
  2. return this.makePathStyle({ type: 'fill', color: indexToHex(index) });
  3. };
  4. // indexToHex 方法
  5. export const indexToHex = (index: number): string => {
  6. let str = index.toString(16);
  7. if (str.length > 6) {
  8. throw Error('index is too large...');
  9. }
  10. if (str.length < 6) {
  11. const prefix = 6 - str.length;
  12. for (let i = 0; i < prefix; i++) {
  13. str = '0' + str;
  14. }
  15. }
  16. return '#' + str;
  17. };

第二步:生成对象

switch (layer.class) {
  case 'polygon':
    const path = davinci.getPathByPoints((layer as Polygon).points);

    layer.setFrame(path.getBounds());
    const polygonStyle = davinci.makeMaskStyleByIndex(i);
    davinci.drawPath(path, polygonStyle);

    break;
  case 'rectangle':
    const rectangleStyle = davinci.makeMaskStyleByIndex(i);
    davinci.drawRect(layer.frame, rectangleStyle);

    break;
  case 'ellipse':
    const ellipseStyle = davinci.makeMaskStyleByIndex(i);
    davinci.drawOval(layer.frame, ellipseStyle);
}

这样我们就有了 MaskStyle 的画布对象

第三步:添加 hover 态指针识别

{
  onPointerOver: e => {
    console.log('selectionPointerOver');

    window.davinci.pointer.isOver = true;
    window.davinci.pointer.x = e.offsetX;
    window.davinci.pointer.y = e.offsetY;
  },
  onPointerLeave: () => {
    console.log('selectionPointerLeave');
    window.davinci.pointer.isOver = false;
  },
  onPointerMove: e => {
    if (isPressed && x && y) {
      // console.log('selectionPointerMoved');

      const width = Math.abs(e.offsetX - x);
      const height = Math.abs(e.offsetY - y);

      window.davinci.selectionFrame = Davinci.makeRectByXYWH(x, y, width, height);
    } else {
      window.davinci.pointer.x = e.offsetX;
      window.davinci.pointer.y = e.offsetY;
    }
  }
}

第四步:添加选择判断

/**
 * 判断是否进行了选择
 */
const { isOver, y, x } = pointer;
if (isOver) {
  const rgba = canvas.readPixels(x, y, 1, 1);
  const color = Color.rgb(rgba);

  const index = davinci.getIndexFromMaskColor(color.hex());

  // 获取选中对象
  const layer = layers[index];
  if (layer && layer.id !== addingObjectId) {
    davinci.drawHoverBounds(layer.class, layer);
  }
}

这里需要对不同的对象分别做一些绘制方法判断,绘制都统一到drawHoverBounds 里了

第五步:绘制 HoverBounds

/**
 * 绘制 Hover 态的 BoundingBox
 */
drawHoverBounds = (type: ShapeClassType, layer: AnyLayer) => {
  const { preference } = window.davinci;

  const { hoverBorderWidth, hoverBorderColor } = preference.selectConfig;

  const style = this.makePathStyle({
    type: 'border',
    color: hoverBorderColor,
    borderWidth: hoverBorderWidth,
  });
  switch (type) {
    case 'ellipse':
      this.drawOval((layer as Ellipse).frame, style);
      break;
    case 'polygon':
      const path = this.getPathByPoints((layer as Polygon).points);

      this.drawPath(path, style);

      break;
    case 'rectangle':
      this.drawRect((layer as Rectangle).frame, style);
  }
};

最终效果

1.gif