前端使用 Konva 实现可视化设计器(22)- 绘制图形(矩形、直线、折线)

本章分享一下如何使用 Konva 绘制基础图形:矩形、直线、折线,希望大家继续关注和支持哈!

请大家动动小手,给我一个免费的 Star 吧~

大家如果发现了 Bug,欢迎来提 Issue 哟~

github源码

gitee源码

示例地址

矩形

先上效果!

在这里插入图片描述
在这里插入图片描述

实现方式基本和《前端使用 Konva 实现可视化设计器(21)- 绘制图形(椭圆)》是一致的,主要区别矩形的大小和椭圆形的大小设置方式不一样,特别是矩形无需设置 offset。其它就不再赘述了哈。

直线、折线

先上效果!

在这里插入图片描述
在这里插入图片描述

简单描述一下上面的交互:

首先,绘制一条直线,淡出画一条直线还是比较简单的,根据记录鼠标按下的位置和鼠标释放的位置,就很容易得到 Konva.Line 的 points 应该设定的值了。

然后,沿用绘制 椭圆形、矩形 的思路,它只有特定的 2 个“调整点”,分别代表 起点 和 终点。

// src/Render/graphs/Line.ts

// 略

/**
 * 直线、折线
 */
export class Line extends BaseGraph {
   
  // 略

  constructor(render: Types.Render, dropPoint: Konva.Vector2d) {
   
    super(render, dropPoint, {
   
      type: Types.GraphType.Line,
      // 定义了 2 个 调整点
      anchors: [{
    adjustType: 'start' }, {
    adjustType: 'end' }].map((o) => ({
   
        adjustType: o.adjustType // 调整点 类型定义
      })),
      linkAnchors: [
        {
    x: 0, y: 0, alias: 'start' },
        {
    x: 0, y: 0, alias: 'end' }
      ] as Types.AssetInfoPoint[]
    })

    // 新建 直线、折线
    this.line = new Konva.Line({
   
      name: 'graph',
      x: 0,
      y: 0,
      stroke: 'black',
      strokeWidth: 1,
      hitStrokeWidth: render.toStageValue(5)
    })

    // 给予 1 像素,防止导出图片 toDataURL 失败
    this.group.size({
   
      width: 1,
      height: 1
    })

    // 加入
    this.group.add(this.line)
    // 鼠标按下位置 作为起点
    this.group.position(this.dropPoint)
  }

  // 实现:拖动进行时
  override drawMove(point: Konva.Vector2d): void {
   
    // 鼠标拖动偏移量
    const offsetX = point.x - this.dropPoint.x,
      offsetY = point.y - this.dropPoint.y

    // 起点、终点
    const linkPoints = [
      [this.line.x(), this.line.y()],
      [this.line.x() + offsetX, this.line.y() + offsetY]
    ]

    // 直线、折线 路径
    this.line.points(_.flatten(linkPoints))

    // 更新 图形 的 调整点 的 锚点位置
    Line.updateAnchorShadows(this.group, this.anchorShadows, this.line)

    // 更新 图形 的 连接点 的 锚点位置
    Line.updateLinkAnchorShadows(this.group, this.linkAnchorShadows, this.line)

    // 重绘
    this.render.redraw([Draws.GraphDraw.name, Draws.LinkDraw.name, Draws.PreviewDraw.name])
  }

  // 实现:拖动结束
  override drawEnd(): void {
   
    if (this.line.width() <= 1 && this.line.height() <= 1) {
   
      // 加入只点击,无拖动

      // 默认大小
      const width = Line.size,
        height = width

      // 起点、终点
      const linkPoints = [
        [this.line.x(), this.line.y()],
        [this.line.x() + width, this.line.y() + height]
      ]

      // 直线、折线 位置大小
      this.line.points(_.flatten(linkPoints))
    }

    // 更新 调整点(拐点)
    Line.updateAnchor(this.render, this.group)

    // 更新 图形 的 调整点 的 锚点位置
    Line.updateAnchorShadows(this.group, this.anchorShadows, this.line)

    // 更新 图形 的 连接点 的 锚点位置
    Line.updateLinkAnchorShadows(this.group, this.linkAnchorShadows, this.line)

    // 对齐线清除
    this.render.attractTool.alignLinesClear()

    // 更新历史
    this.render.updateHistory()

    // 重绘
    this.render.redraw([Draws.GraphDraw.name, Draws.LinkDraw.name, Draws.PreviewDraw.name])
  }

  // 略
}

调整点,可以改变 直线、折线 的 起点、终点。

// 略

/**
 * 直线、折线
 */
export class Line extends BaseGraph {
   
  // 实现:更新 图形 的 调整点 的 锚点位置
  static override updateAnchorShadows(
    graph: Konva.Group,
    anchorShadows: Konva.Circle[],
    shape?: Konva.Line
  ): void {
   
    if (shape) {
   
      const points = shape.points()
      //
      for (const shadow of anchorShadows) {
   
        switch (shadow.attrs.adjustType) {
   
          case 'start':
            shadow.position({
   
              x: points[0],
              y: points[1]
            })
            break
          case 'end':
            shadow.position({
   
              x: points[points.length - 2],
              y: points[points.length - 1]
            })
            break
        }
      }
    }
  }
  
  // 略

  // 实现:生成 调整点
  static override createAnchorShapes(
    render: Types.Render
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值