feat(canvas): 新节点自动往右找空位,一行10个才换行
This commit is contained in:
@@ -5,7 +5,7 @@ import { computed, nextTick, onBeforeUnmount, onMounted, reactive, ref, watch }
|
|||||||
import { onBeforeRouteLeave } from 'vue-router'
|
import { onBeforeRouteLeave } from 'vue-router'
|
||||||
import { api, generatedUrl, jsonBody, thumbUrl } from '../api'
|
import { api, generatedUrl, jsonBody, thumbUrl } from '../api'
|
||||||
import { auth } from '../auth'
|
import { auth } from '../auth'
|
||||||
import { normalizeDoc, newId, ratioToSize, serializeDoc, screenToWorld, DEFAULT_SCALE } from '../utils/canvas'
|
import { normalizeDoc, newId, ratioToSize, serializeDoc, screenToWorld, rectsIntersect, DEFAULT_SCALE } from '../utils/canvas'
|
||||||
import CanvasStage from '../components/canvas/CanvasStage.vue'
|
import CanvasStage from '../components/canvas/CanvasStage.vue'
|
||||||
import SelectMenu from '../components/SelectMenu.vue'
|
import SelectMenu from '../components/SelectMenu.vue'
|
||||||
|
|
||||||
@@ -318,8 +318,34 @@ function redo() {
|
|||||||
|
|
||||||
// ================= 节点操作 =================
|
// ================= 节点操作 =================
|
||||||
|
|
||||||
|
// 自动找空位:从锚点(默认视口中心)开始往右排,一行最多10个,超了才换下一行
|
||||||
|
const NODE_PAD = 48
|
||||||
|
const ROW_MAX = 10
|
||||||
|
function spotIsFree(x, y, w, h) {
|
||||||
|
const r = { x: x - NODE_PAD / 2, y: y - NODE_PAD / 2, w: w + NODE_PAD, h: h + NODE_PAD }
|
||||||
|
return !doc.nodes.some((n) => rectsIntersect(r, { x: n.x, y: n.y, w: n.w, h: n.h }))
|
||||||
|
}
|
||||||
|
function freeSpot(w, h, at = null) {
|
||||||
|
const c = at || viewportCenterWorld()
|
||||||
|
const x0 = Math.round(c.x - w / 2)
|
||||||
|
const y0 = Math.round(c.y - h / 2)
|
||||||
|
for (let i = 0; i < 200; i++) {
|
||||||
|
const x = x0 + (i % ROW_MAX) * (w + NODE_PAD)
|
||||||
|
const y = y0 + Math.floor(i / ROW_MAX) * (h + NODE_PAD)
|
||||||
|
if (spotIsFree(x, y, w, h)) return { x, y }
|
||||||
|
}
|
||||||
|
return { x: x0, y: y0 }
|
||||||
|
}
|
||||||
|
|
||||||
function addNote() {
|
function addNote() {
|
||||||
addNoteAt(viewportCenterWorld())
|
const s = freeSpot(260, 140)
|
||||||
|
const n = {
|
||||||
|
id: newId('t'), type: 'note', text: '',
|
||||||
|
x: s.x, y: s.y, w: 260, h: 140, z: 0,
|
||||||
|
}
|
||||||
|
doc.nodes.push(n)
|
||||||
|
selectionIds.value = [n.id]
|
||||||
|
pushHistory()
|
||||||
}
|
}
|
||||||
|
|
||||||
function addNoteAt(w) {
|
function addNoteAt(w) {
|
||||||
@@ -333,23 +359,17 @@ function addNoteAt(w) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addImageNode(src, prompt = '', at = null) {
|
function addImageNode(src, prompt = '', at = null) {
|
||||||
const c = at || viewportCenterWorld()
|
// at 作为锚点(拖放位置);被占用就自动往右找空位,连续上传自然排成一排
|
||||||
|
const s = freeSpot(512, 512, at)
|
||||||
const n = {
|
const n = {
|
||||||
id: newId('i'), type: 'image', src, prompt,
|
id: newId('i'), type: 'image', src, prompt,
|
||||||
x: Math.round(c.x - 256 + cascade()), y: Math.round(c.y - 256 + cascade()),
|
x: s.x, y: s.y, w: 512, h: 512, z: 0,
|
||||||
w: 512, h: 512, z: 0,
|
|
||||||
}
|
}
|
||||||
doc.nodes.push(n)
|
doc.nodes.push(n)
|
||||||
selectionIds.value = [n.id]
|
selectionIds.value = [n.id]
|
||||||
pushHistory()
|
pushHistory()
|
||||||
}
|
}
|
||||||
|
|
||||||
let cascadeN = 0
|
|
||||||
function cascade() {
|
|
||||||
cascadeN = (cascadeN + 1) % 8
|
|
||||||
return cascadeN * 24
|
|
||||||
}
|
|
||||||
|
|
||||||
function viewportCenterWorld() {
|
function viewportCenterWorld() {
|
||||||
const vp = stage.value?.vp
|
const vp = stage.value?.vp
|
||||||
const el = document.querySelector('.cv-stage')
|
const el = document.querySelector('.cv-stage')
|
||||||
@@ -589,10 +609,10 @@ async function generate() {
|
|||||||
x = maxX + 64
|
x = maxX + 64
|
||||||
y = minY
|
y = minY
|
||||||
} else {
|
} else {
|
||||||
const c = viewportCenterWorld()
|
|
||||||
const totalW = n * size.w + (n - 1) * 48
|
const totalW = n * size.w + (n - 1) * 48
|
||||||
x = c.x - totalW / 2
|
const s = freeSpot(totalW, size.h)
|
||||||
y = c.y - size.h / 2
|
x = s.x
|
||||||
|
y = s.y
|
||||||
}
|
}
|
||||||
|
|
||||||
const created = []
|
const created = []
|
||||||
|
|||||||
Reference in New Issue
Block a user