fix: v2.3 组合排列 3D 重叠修复
- CombineCanvas 新增 autoArrange: 单元按 X 序紧贴排布+底边对齐 - 拖动松手重叠检测: 与其他单元相交时自动重新排列 (消除 3D 玻璃面穿插与 z-fighting) - 工具栏新增自动排列按钮 - 移除 CombineCanvas 孤儿 @drop(归父容器统一处理)
This commit is contained in:
@@ -305,9 +305,15 @@ function onMove(e: MouseEvent) {
|
||||
|
||||
function onUp() {
|
||||
if (dragUnit) {
|
||||
if (dragUnit.moved) emit('change')
|
||||
const uid = dragUnit.uid
|
||||
const moved = dragUnit.moved
|
||||
guides = { v: [], h: [] }
|
||||
dragUnit = null
|
||||
if (moved && uid !== null && unitOverlaps(uid)) {
|
||||
// 拖动后与其他单元重叠 → 自动重新排列消除重叠
|
||||
autoArrange()
|
||||
return
|
||||
}
|
||||
render()
|
||||
return
|
||||
}
|
||||
@@ -362,6 +368,40 @@ function nudgeSelected(dx: number, dy: number) {
|
||||
emit('change')
|
||||
}
|
||||
|
||||
function rectsIntersect(a: BBox, b: BBox): boolean {
|
||||
return a.x0 < b.x1 - 1 && b.x0 < a.x1 - 1 && a.y0 < b.y1 - 1 && b.y0 < a.y1 - 1
|
||||
}
|
||||
|
||||
/** 单元是否与其它单元重叠 */
|
||||
function unitOverlaps(uid: number): boolean {
|
||||
const bb = unitBBox(uid)
|
||||
if (!bb) return false
|
||||
return uids().filter(u => u !== uid).some(u => {
|
||||
const o = unitBBox(u)
|
||||
return o ? rectsIntersect(bb, o) : false
|
||||
})
|
||||
}
|
||||
|
||||
/** 自动排列: 全部单元按 X 序紧贴排布、底边对齐(消除重叠) */
|
||||
function autoArrange() {
|
||||
const ids = uids().filter(u => unitBBox(u)).sort((a, b) =>
|
||||
(unitBBox(a)!.x0) - (unitBBox(b)!.x0))
|
||||
if (!ids.length) return
|
||||
let bottom = Infinity
|
||||
for (const id of ids) {
|
||||
const bb = unitBBox(id)!
|
||||
bottom = Math.min(bottom, bb.y0)
|
||||
}
|
||||
let x = ids.length ? unitBBox(ids[0])!.x0 : 0
|
||||
for (const id of ids) {
|
||||
const bb = unitBBox(id)!
|
||||
translateUid(id, x - bb.x0, bottom - bb.y0)
|
||||
x += bb.x1 - bb.x0
|
||||
}
|
||||
refresh()
|
||||
emit('change')
|
||||
}
|
||||
|
||||
function exportDrawing(): string | null {
|
||||
if (!props.shapes.length) return null
|
||||
return JSON.stringify({
|
||||
@@ -369,7 +409,7 @@ function exportDrawing(): string | null {
|
||||
epi: [], sbf: [], wlc: '', wall: [], scale: 0, note: [],
|
||||
})
|
||||
}
|
||||
defineExpose({ refresh, modelAt, exportDrawing, rotateUnit, mirrorUnit, resizeSelected, nudgeSelected })
|
||||
defineExpose({ refresh, modelAt, exportDrawing, rotateUnit, mirrorUnit, resizeSelected, nudgeSelected, autoArrange })
|
||||
|
||||
onMounted(() => {
|
||||
watch(() => props.shapes, () => { selectedUid.value = null; rebuild() }, { immediate: true })
|
||||
|
||||
Reference in New Issue
Block a user