github/gitee Star 终于有几个了!
从这章开始,难度算是(或者说细节较多)升级,是不是值得更多的 Star 呢?!
继续求 Star ,希望大家多多一键三连,十分感谢大家的支持~
创作不易,Star 50 个,创作加速!
github源码
gitee源码
示例地址
选择框
准备工作
想要拖动一个元素,可以考虑使用节点的 draggable 属性。
不过,想要拖动多个元素,可以使用 transformer,官网也是简单的示例 Basic demo。
按设计思路统一通过 transformer 移动/缩放所选,也意味着,元素要先选后动。
先准备一个 group、transformer、selectRect:
// 多选器层
groupTransformer: Konva.Group = new Konva.Group()
// 多选器
transformer: Konva.Transformer = new Konva.Transformer({
shouldOverdrawWholeArea: true,
borderDash: [4, 4],
padding: 1,
rotationSnaps: [0, 45, 90, 135, 180, 225, 270, 315, 360]
})
// 选择框
selectRect: Konva.Rect = new Konva.Rect({
id: 'selectRect',
fill: 'rgba(0,0,255,0.1)',
visible: false
})
先说 transformer,设置 shouldOverdrawWholeArea 为了选择所选的空白处也能拖动;rotationSnaps 就是官方提供的 rotate 时的磁贴交互。
然后,selectRect 就是选择框,参考的就是上面提到的 Basic demo。
最后,上面的 group 比较特别,它承载了上面的 transformer 和 selectRect,且置于第一章提到的 layerCover。
// 辅助层 - 顶层
this.groupTransformer.add(this.transformer)
this.groupTransformer.add(this.selectRect)
this.layerCover.add(this.groupTransformer)
selectRect 不应该被“交互”,所以加个排查判断:
// 忽略非素材
ignore(node: Konva.Node) {
// 素材有各自根 group
const isGroup = node instanceof Konva.Group
return !isGroup || node.id() === 'selectRect' || this.ignoreDraw(node)
}
选择
准备一些状态变量:
// selectRect 拉动的开始和结束坐标
selectRectStartX = 0
selectRectStartY = 0
selectRectEndX = 0
selectRectEndY = 0
// 是否正在使用 selectRect
selecting = false
选择开始,处理 stage 的 mousedown 事件:
mousedown: (e: Konva.KonvaEventObject<GlobalEventHandlersEventMap['mousedown']>) => {
// 略
if (e.target === this.render.stage) {
// 点击空白处
// 清除选择
// 外部也需要此操作,统一放在 selectionTool中
// 后面会提到
this.render.selectionTool.selectingClear()
// 选择框
if (e.evt.button === Types.MouseButton.左键) {
const pos = this.render.stage.getPointerPosition()
if (pos) {
// 初始化状态值
this.selectRectStartX = pos.x
this.selectRectStartY = pos.y
this.selectRectEndX = pos.x
this.selectRectEndY = pos.y
}
// 初始化大小
this.render.selectRect.width(0)
this.render.selectRect.height(0)
// 开始选择
this.selecting = true
}
} else if (parent instanceof Konva.Transformer) {
// transformer 点击事件交给 transformer 自己的 handler
} else if (parent instanceof Konva.Group) {
// 略
}
}
接着,处理 stage 的 mousemove 事件:
mousemove: () => {
// stage 状态
const stageState = this.render.getStageState()
// 选择框
if (this.selecting) {
// 选择区域中
const pos = this.render.stage.getPointerPosition()
if (pos) {
// 选择移动后的坐标
this.selectRectEndX