拖动图片支持实时预览节点变化

This commit is contained in:
Achuan-2 2025-11-26 11:19:49 +08:00 committed by GitHub
parent 6dcb29f218
commit 0e005d40eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -22,7 +22,12 @@ class NodeImgAdjust {
this.currentImgWidth = 0 // 当前拖拽实时图片的大小
this.currentImgHeight = 0
this.isAdjusted = false // 是否是拖拽结束后的渲染期间
this.isAdjusted = false // 是否是拖拽结束后的渲染期间
this.referenceWidths = [] // 参考宽度列表
this.startClientX = 0
this.startClientY = 0
this.startImgWidth = 0
this.startImgHeight = 0
this.bindEvent()
}
@ -238,11 +243,17 @@ class NodeImgAdjust {
this.isMousedown = true
this.mousedownDrawTransform = this.mindMap.draw.transform()
// 隐藏节点实际图片
this.hideNodeImage()
// this.hideNodeImage()
this.mousedownOffset.x = e.clientX - this.rect.x2
this.mousedownOffset.y = e.clientY - this.rect.y2
// 记录初始状态
this.startClientX = e.clientX
this.startClientY = e.clientY
const { width, height } = this.node.getData('imageSize')
this.startImgWidth = width
this.startImgHeight = height
// 将节点图片渲染到自定义元素上
this.handleEl.style.backgroundImage = `url(${this.node.getData('image')})`
// this.handleEl.style.backgroundImage = `url(${this.node.getData('image')})`
// 收集参考宽度
this.referenceWidths = this.collectImageWidths()
}
@ -302,23 +313,50 @@ class NodeImgAdjust {
imgMaxWidth = imgMaxWidth * scaleX
imgMaxHeight = imgMaxHeight * scaleY
// 计算当前拖拽位置对应的图片的实时大小
let newWidth = Math.abs(e.clientX - this.rect.x - this.mousedownOffset.x)
let newHeight = Math.abs(e.clientY - this.rect.y - this.mousedownOffset.y)
// 逻辑尺寸变化量
const deltaX = (e.clientX - this.startClientX) / scaleX
// 逻辑尺寸
let newWidth = this.startImgWidth + deltaX
// 转换为屏幕像素用于吸附判断
let screenWidth = newWidth * scaleX
// 吸附逻辑
const SNAP_THRESHOLD = 5
let snapped = false
for (const width of this.referenceWidths) {
const screenWidth = width * scaleX
if (Math.abs(newWidth - screenWidth) <= SNAP_THRESHOLD) {
newWidth = screenWidth
const refScreenWidth = width * scaleX
if (Math.abs(screenWidth - refScreenWidth) <= SNAP_THRESHOLD) {
newWidth = width
screenWidth = refScreenWidth
snapped = true
break
}
}
// 如果吸附了,根据宽高比调整高度
let newHeight = newWidth / oRatio
// 限制最小值
if (newWidth < minImgResizeWidth) newWidth = minImgResizeWidth
if (newHeight < minImgResizeHeight) newHeight = minImgResizeHeight
// 限制最大值
if (newWidth > imgMaxWidth) newWidth = imgMaxWidth
if (newHeight > imgMaxHeight) newHeight = imgMaxHeight
this.currentImgWidth = newWidth
this.currentImgHeight = newHeight
// 更新handleEl的位置和大小
this.node.getData().imageSize = {
width: this.currentImgWidth,
height: this.currentImgHeight,
custom: true
}
this.mindMap.render()
// 更新按钮状态
if (snapped) {
newHeight = newWidth / oRatio
if (this.resizeBtnEl) {
this.resizeBtnEl.style.backgroundColor = '#409eff'
}
@ -327,29 +365,13 @@ class NodeImgAdjust {
this.resizeBtnEl.style.backgroundColor = 'rgba(0, 0, 0, 0.3)'
}
}
// 限制最小值
if (newWidth < minImgResizeWidth) newWidth = minImgResizeWidth
if (newHeight < minImgResizeHeight) newHeight = minImgResizeHeight
// 限制最大值
if (newWidth > imgMaxWidth) newWidth = imgMaxWidth
if (newHeight > imgMaxHeight) newHeight = imgMaxHeight
const [actWidth, actHeight] = resizeImgSizeByOriginRatio(
imageOriginWidth,
imageOriginHeight,
newWidth,
newHeight
)
this.currentImgWidth = actWidth
this.currentImgHeight = actHeight
this.updateHandleElSize()
}
// 鼠标松开
onMouseup() {
if (!this.isMousedown) return
// 显示节点实际图片
this.showNodeImage()
// this.showNodeImage()
// 隐藏自定义元素
this.hideHandleEl()
// 重置按钮颜色
@ -382,6 +404,18 @@ class NodeImgAdjust {
// 渲染完成事件
onRenderEnd() {
if (this.isMousedown && this.node) {
// 拖拽过程中渲染完成,需要更新操作柄位置
// 必须重新获取 img 元素,因为 render 后 DOM 可能重建
const img = this.node.group.findOne('image')
if (img) {
this.img = img
this.rect = img.rbox()
// 强制更新位置,确保跟随
this.setHandleElRect()
}
return
}
if (!this.isAdjusted) {
this.hideHandleEl()
return