UNPKG

@meta2d/core

Version:

@meta2d/core: Powerful, Beautiful, Simple, Open - Web-Based 2D At Its Best .

627 lines 18.4 kB
import { Direction } from '../../data'; import { deleteTempAnchor, facePen, getFromAnchor, getToAnchor, } from '../../pen'; import { s8 } from '../../utils'; let faceSpace = 10; export function polyline(store, pen, mousedwon) { if (!pen.calculative.worldAnchors) { pen.calculative.worldAnchors = []; } faceSpace = store.options.polylineSpace || 10; if (pen.calculative.worldAnchors.length < 2) { return; } let from = getFromAnchor(pen); let to = getToAnchor(pen); if (!from || !to) { return; } // 拖拽起点 let dragFrom; if (pen.anchors?.length && from === pen.calculative.activeAnchor) { dragFrom = true; from = to; to = getFromAnchor(pen); } else if ((!pen.anchors || !pen.anchors.length) && from !== pen.calculative.activeAnchor) { from = pen.calculative.activeAnchor; } if (!from || !to) { return; } from.next = undefined; to.prev = undefined; const connected = to.connectTo; deleteTempAnchor(pen); const pts = []; const fromPen = store.pens[from.connectTo]; const toPen = store.pens[to.connectTo]; const fromFace = facePen(from, fromPen); const toFace = facePen(to, toPen); let a = getFacePoint(from, fromFace, faceSpace); if (a) { from = a; pts.push(a); } a = getFacePoint(to, toFace, faceSpace); const end = to; let corner = undefined; if (a) { to = a; if (end.connectTo) { if ((a.y > end.y && from.y < end.y) || (a.y < end.y && from.y > end.y)) { //拐角 防止连线覆盖 corner = a; let _faceSpace = faceSpace; if (from.x < a.x) { _faceSpace = -_faceSpace; } if (Math.abs(from.x - a.x) < _faceSpace) { _faceSpace = -_faceSpace; } const point = { x: a.x + _faceSpace, y: a.y, id: s8() }; to = point; } } } switch (fromFace) { case Direction.Up: pts.push(...getNextPointsOfUp(from, to, toFace)); break; case Direction.Right: pts.push(...getNextPointsOfRight(from, to, toFace)); break; case Direction.Bottom: pts.push(...getNextPointsOfBottom(from, to, toFace)); break; case Direction.Left: pts.push(...getNextPointsOfLeft(from, to, toFace)); break; default: pts.push(...getNextPoints(pen, from, to)); break; } pts.forEach((anchor) => { anchor.id = s8(); anchor.penId = pen.id; pen.calculative.worldAnchors.push(anchor); }); pen.calculative.worldAnchors.push(to); if (corner) { pen.calculative.worldAnchors.push(corner); } if (a) { pen.calculative.worldAnchors.push(end); } if (dragFrom) { pen.calculative.worldAnchors.reverse(); } if (connected) { const i = pen.calculative.worldAnchors.length - 2; pen.calculative.worldAnchors[i].isTemp = false; pen.calculative.worldAnchors[1].isTemp = false; } } function getFacePoint(pt, d, dis) { const point = { x: pt.x, y: pt.y, id: s8() }; switch (d) { case Direction.Up: point.y -= dis; break; case Direction.Right: point.x += dis; break; case Direction.Bottom: point.y += dis; break; case Direction.Left: point.x -= dis; break; default: { return; } } return point; } function getNextPointsOfUp(from, to, toFace) { if (from.x === to.x || from.y === to.y) { return []; } const pts = []; let x; let y; switch (toFace) { case Direction.Up: if (from.y < to.y) { x = to.x; y = from.y; } else { x = from.x; y = to.y; } pts.push({ x, y }); break; case Direction.Bottom: x = to.x; y = from.y; if (to.y > from.y) { x = from.x + (to.x - from.x) / 2; pts.push({ x, y: from.y }, { x, y: to.y }); } else { const centerY = (from.y + to.y) / 2; pts.push({ x: from.x, y: centerY }, { x: to.x, y: centerY }); } break; case Direction.Right: x = to.x; y = from.y; if (to.x < from.x && to.y < from.y) { x = from.x; y = to.y; } pts.push({ x, y }); break; case Direction.Left: x = to.x; y = from.y; if (to.x > from.x && to.y < from.y) { x = from.x; y = to.y; } pts.push({ x, y }); break; default: if (to.y > from.y - faceSpace) { x = from.x + (to.x - from.x) / 2; pts.push({ x, y: from.y }, { x, y: to.y }); } else { const centerY = (from.y + to.y + faceSpace) / 2; pts.push({ x: from.x, y: centerY }, { x: to.x, y: centerY }); } break; } return pts; } function getNextPointsOfRight(from, to, toFace) { if (from.x === to.x || from.y === to.y) { return []; } const pts = []; let x; let y; switch (toFace) { case Direction.Up: x = from.x; y = to.y; if (to.x > from.x && to.y > from.y) { x = to.x; y = from.y; } pts.push({ x, y }); break; case Direction.Bottom: x = from.x; y = to.y; if (to.x > from.x && to.y < from.y) { x = to.x; y = from.y; } pts.push({ x, y }); break; case Direction.Left: x = to.x; y = from.y; if (to.x < from.x) { y = from.y + (to.y - from.y) / 2; pts.push({ x: from.x, y }, { x: to.x, y }); } else { const centerX = (from.x + to.x) / 2; pts.push({ x: centerX, y }, { x: centerX, y: to.y }); } break; case Direction.Right: if (to.x < from.x) { pts.push({ x: from.x, y: to.y }); } else { pts.push({ x: to.x, y: from.y }); } break; default: x = to.x; y = to.y; if (to.x < from.x + faceSpace) { pts.push({ x: from.x, y }); } else { const centerX = (from.x + to.x - faceSpace) / 2; pts.push({ x: centerX, y: from.y }, { x: centerX, y }); } break; } return pts; } function getNextPointsOfBottom(from, to, toFace) { if (from.x === to.x || from.y === to.y) { return []; } const pts = []; let x; let y; switch (toFace) { case Direction.Up: x = from.x; y = to.y; if (to.y < from.y) { x = from.x + (to.x - from.x) / 2; pts.push({ x, y: from.y }, { x, y: to.y }); } else { const centerY = (from.y + to.y) / 2; pts.push({ x, y: centerY }, { x: to.x, y: centerY }); } break; case Direction.Right: x = to.x; y = from.y; if (to.x < from.x && to.y > from.y) { x = from.x; y = to.y; } pts.push({ x, y }); break; case Direction.Bottom: if (from.y > to.y) { x = to.x; y = from.y; } else { x = from.x; y = to.y; } pts.push({ x, y }); break; case Direction.Left: x = to.x; y = from.y; if (to.x > from.x && to.y > from.y) { x = from.x; y = to.y; } pts.push({ x, y }); break; default: x = from.x; if (to.y < from.y + faceSpace) { x = from.x + (to.x - from.x) / 2; pts.push({ x, y: from.y }, { x, y: to.y }); } else { const centerY = (from.y + to.y - faceSpace) / 2; pts.push({ x, y: centerY }, { x: to.x, y: centerY }); } break; } return pts; } function getNextPointsOfLeft(from, to, toFace) { if (from.x === to.x || from.y === to.y) { return []; } const pts = []; let x; let y; switch (toFace) { case Direction.Up: x = from.x; y = to.y; if (to.x < from.x && to.y > from.y) { x = to.x; y = from.y; } pts.push({ x, y }); break; case Direction.Bottom: x = from.x; y = to.y; if (to.x < from.x && to.y < from.y) { x = to.x; y = from.y; } pts.push({ x, y }); break; case Direction.Right: x = from.x; y = to.y; if (to.x > from.x) { x = to.x; y = from.y + (to.y - from.y) / 2; pts.push({ x: from.x, y }, { x: to.x, y }); } else { const centerX = (from.x + to.x) / 2; pts.push({ x: centerX, y: from.y }, { x: centerX, y: to.y }); } break; case Direction.Left: if (to.x > from.x) { pts.push({ x: from.x, y: to.y }); } else { pts.push({ x: to.x, y: from.y }); } break; default: x = from.x; y = to.y; if (to.x < from.x - faceSpace) { const centerX = (from.x + to.x + faceSpace) / 2; pts.push({ x: centerX, y: from.y }, { x: centerX, y }); } else { pts.push({ x: from.x, y }); } break; } return pts; } function getNextPoints(pen, from, to) { const pts = []; if (pen.calculative.drawlineH == undefined) { pen.calculative.drawlineH = Math.abs(to.x - from.x) > Math.abs(to.y - from.y); } let index = pen.calculative.worldAnchors.findIndex((anchor) => anchor.id == from.id); if (index > 1) { let prev = pen.calculative.worldAnchors[index - 1]; if (prev.x === from.x && prev.y !== from.y) { //水平 pts.push({ x: to.x, y: from.y }); return pts; } else if (prev.y === from.y && prev.x !== from.x) { //垂直 pts.push({ x: from.x, y: to.y }); return pts; } } if (pen.calculative.worldAnchors.length) { to.isTemp = undefined; if (pen.calculative.drawlineH) { pts.push({ x: to.x, y: from.y }); if (Math.abs(to.y - from.y) < faceSpace) { to.isTemp = true; } } else { pts.push({ x: from.x, y: to.y }); if (Math.abs(to.x - from.x) < faceSpace) { to.isTemp = true; } } } return pts; } export function anchorInHorizontal(pen, anchor, from = true) { let anchors = pen.calculative.worldAnchors; if (!from) { anchors = []; pen.calculative.worldAnchors.forEach((item) => { anchors.unshift(item); }); } for (let i = 0; i < anchors.length; i++) { if (anchors[i].id === anchor.id) { break; } if (anchors[i].y !== anchor.y) { return false; } if (anchors[i].x === anchors[i + 1]?.x && anchors[i].y !== anchors[i + 1]?.y) { return false; } } return true; } export function anchorInVertical(pen, anchor, from = true) { let anchors = pen.calculative.worldAnchors; if (!from) { anchors = []; pen.calculative.worldAnchors.forEach((item) => { anchors.unshift(item); }); } for (let i = 0; i < anchors.length; i++) { if (anchors[i].id === anchor.id) { break; } if (anchors[i].x !== anchor.x) { return false; } if (anchors[i].y === anchors[i + 1]?.y && anchors[i].x !== anchors[i + 1]?.x) { return false; } } return true; } export function translatePolylineAnchor(pen, anchor, pt) { if (!pen.calculative.worldAnchors) { return; } const i = pen.calculative.worldAnchors.findIndex((item) => item.id === anchor.id); const from = getFromAnchor(pen); const to = getToAnchor(pen); let prev = pen.calculative.worldAnchors[i - 1]; let next = pen.calculative.worldAnchors[i + 1]; if (pen.calculative.h == undefined) { if (from.connectTo) { if (anchorInHorizontal(pen, anchor, true)) { pen.calculative.h = true; } else if (anchorInVertical(pen, anchor, true)) { pen.calculative.h = false; } } if (pen.calculative.h == undefined && to.connectTo) { if (anchorInHorizontal(pen, anchor, false)) { pen.calculative.h = true; } else if (anchorInVertical(pen, anchor, false)) { pen.calculative.h = false; } } if (pen.calculative.h == undefined) { if (prev) { pen.calculative.h = prev.y === anchor.y; } else if (next) { pen.calculative.h = next.y === anchor.y; } } } // 水平 if (pen.calculative.h) { anchor.x = pt.x; if (from.connectTo && anchorInHorizontal(pen, anchor, true)) { if (next && next.y !== anchor.y) { next.x = anchor.x; } return; } if (to.connectTo && anchorInHorizontal(pen, anchor, false)) { if (prev && prev.y !== anchor.y) { prev.x = anchor.x; } return; } const a = pen.anchors[i]; let d; for (let pos = i - 1; pos > -1; pos--) { prev = pen.anchors[pos]; if (d == undefined) { d = prev.y === a.y; } if (d === true) { if (prev.y === a.y) { pen.calculative.worldAnchors[pos].y = pt.y; } else { break; } } else { if (prev.x === a.x) { pen.calculative.worldAnchors[pos].x = pt.x; } else { break; } } } d = undefined; for (let pos = i + 1; pos < pen.calculative.worldAnchors.length; pos++) { next = pen.anchors[pos]; if (next) { if (d == undefined) { d = next.y === a.y; } if (d === true) { if (next.y === a.y) { pen.calculative.worldAnchors[pos].y = pt.y; } else { break; } } else { if (next.x === a.x) { pen.calculative.worldAnchors[pos].x = pt.x; } else { break; } } } else { break; } } anchor.y = pt.y; } // 垂直 else { anchor.y = pt.y; if (from.connectTo && anchorInVertical(pen, anchor, true)) { if (next && next.x !== anchor.x) { next.y = anchor.y; } return; } if (to.connectTo && anchorInVertical(pen, anchor, false)) { if (prev && prev.x !== anchor.x) { prev.y = anchor.y; } return; } const a = pen.anchors[i]; let d; for (let pos = i - 1; pos > -1; pos--) { prev = pen.anchors[pos]; if (d == undefined) { d = prev.x === a.x; } if (d === true) { if (prev.x === a.x) { pen.calculative.worldAnchors[pos].x = pt.x; } else { break; } } else { if (prev.y === a.y) { pen.calculative.worldAnchors[pos].y = pt.y; } else { break; } } } d = undefined; for (let pos = i + 1; pos < pen.calculative.worldAnchors.length; pos++) { next = pen.anchors[pos]; if (next) { if (d == undefined) { d = next.x === a.x; } if (d === true) { if (next.x === a.x) { pen.calculative.worldAnchors[pos].x = pt.x; } else { break; } } else { if (next.y === a.y) { pen.calculative.worldAnchors[pos].y = pt.y; } else { break; } } } else { break; } } anchor.x = pt.x; } } //# sourceMappingURL=polyline.js.map