前端使用 Konva 实现可视化设计器(17)- 素材嵌套 - 生成阶段

本章主要实现素材的嵌套(生成阶段)这意味着可以拖入画布的对象,不只是图片素材,还可以是嵌套的图片和图形。在未来的章节中,应该可以实现素材成组/解散的效果。

最近难以抽出时间继续本示例更新,以至于拖到今天才更新这一章…

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

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

github源码

gitee源码

示例地址

一些调整和优化

1、原本分散在各处的不同层的 draw 方法调用,现在基本上统一调用 render 的 redraw 方法,简化代码逻辑(暂未发现明显的性能问题)。
2、修复右键无法删除连接线的问题,主要是 stage 的 contextmenu 事件实测 target 无法得到指向的 Line 实例,目前使用 Konva.Util.haveIntersection 处理,以下是该逻辑的代码片段:

// src/Render/draws/ContextmenuDraw.ts
            const linkGroup = this.render.layerCover.find(
              `.${
     Draws.LinkDraw.name}`
            )[0] as Konva.Group

            // 右键目标可能为 连接线
            let lineSelection: Konva.Node | null = null

            if (linkGroup) {
   
              const linkLines = linkGroup.find('.link-line')

              for (const line of linkLines) {
   
                if (
                  Konva.Util.haveIntersection({
    ...pos, width: 1, height: 1 }, line.getClientRect())
                ) {
   
                  // 右键目标为 连接线
                  lineSelection = line
                  break
                }
              }
            }

            if (pos.x === this.state.lastPos.x || pos.y === this.state.lastPos.y) {
   
              // 右键 连接线/其它目标
              this.state.target = lineSelection ?? e.target
            } else {
   
              this.state.target = null
            }

3、原来的对齐逻辑没有考虑目标被 rotate 后的情况,现已经修复支持了,实现方式还是使用三角函数计算:

在这里插入图片描述

红框是 rotate 后的占用区域,通过旋转角度就可以计算该区域的宽高,left、right、top、bottom 也是用于计算占用区域的 x,y 坐标:
在这里插入图片描述

// src/Render/tools/AlignTool.ts
  calcNodeRotationInfo(node: Konva.Node) {
   
    const rotate = node.rotation()
    const offsetLeft = node.height() * Math.sin((rotate * Math.PI) / 180)
    const offsetRight = node.width() * Math.cos((rotate * Math.PI) / 180)
    const offsetTop = node.height() * Math.cos((rotate * Math.PI) / 180)
    const offsetBottom = node.width() * Math.sin((rotate * Math.PI) / 180)

    const width = Math.abs(offsetLeft) + Math.abs(offsetRight)
    const height = Math.abs(offsetTop) + Math.abs(offsetBottom)

    let x = node.x()
    if ((rotate >= 0 && rotate < 90) || (rotate >= -360 && rotate < -270)) {
   
      x = x - Math.abs(offsetLeft)
    } else if ((rotate >= 90 && rotate < 180) || (rotate >= -270 && rotate < -180)) {
   
      x = x - width
    } else if ((rotate >= 180 && rotate < 270) || (rotate >= -180 && rotate < -90)) {
   
      x = x - Math.abs(offsetRight)
    } else if ((rotate >= 270 && rotate < 360) || (rotate >= -90 && rotate < 0)) {
   
      // 无需处理
    }

    let y = node.y()
    if ((rotate >= 0 && rotate < 90) || (rotate >= -360 && rotate < -270)) {
   
      // 无需处理
    } else if ((rotate >= 90 && rotate < 180
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值