aldehyde 0.2.472 → 0.2.474
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/controls/entity-select/entity-select.js +1 -1
- package/lib/controls/entity-select/entity-select.js.map +1 -1
- package/lib/controls/entry-control.js +2 -2
- package/lib/controls/entry-control.js.map +1 -1
- package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.css +47 -3
- package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.js +12 -12
- package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.js.map +1 -1
- package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.json +77 -0
- package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.ttf +0 -0
- package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff +0 -0
- package/lib/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff2 +0 -0
- package/lib/draw-canvas/edit/components/asset-bar/index.d.ts +5 -0
- package/lib/draw-canvas/edit/components/asset-bar/index.d.ts.map +1 -0
- package/lib/draw-canvas/edit/components/asset-bar/index.js +78 -0
- package/lib/draw-canvas/edit/components/asset-bar/index.js.map +1 -0
- package/lib/draw-canvas/edit/components/asset-bar/index.less +36 -0
- package/lib/draw-canvas/edit/components/main-header/index.d.ts +14 -0
- package/lib/draw-canvas/edit/components/main-header/index.d.ts.map +1 -0
- package/lib/draw-canvas/edit/components/main-header/index.js +163 -0
- package/lib/draw-canvas/edit/components/main-header/index.js.map +1 -0
- package/lib/draw-canvas/edit/components/main-header/index.less +21 -0
- package/lib/draw-canvas/edit/components/render/index.d.ts +86 -0
- package/lib/draw-canvas/edit/components/render/index.d.ts.map +1 -0
- package/lib/draw-canvas/edit/components/render/index.js +686 -0
- package/lib/draw-canvas/edit/components/render/index.js.map +1 -0
- package/lib/draw-canvas/edit/components/render/types.d.ts +243 -0
- package/lib/draw-canvas/edit/components/render/types.d.ts.map +1 -0
- package/lib/draw-canvas/edit/components/render/types.js +66 -0
- package/lib/draw-canvas/edit/components/render/types.js.map +1 -0
- package/lib/draw-canvas/edit/components/setting-form/index.d.ts +19 -0
- package/lib/draw-canvas/edit/components/setting-form/index.d.ts.map +1 -0
- package/lib/draw-canvas/edit/components/setting-form/index.js +164 -0
- package/lib/draw-canvas/edit/components/setting-form/index.js.map +1 -0
- package/lib/draw-canvas/edit/index.d.ts +5 -0
- package/lib/draw-canvas/edit/index.d.ts.map +1 -0
- package/lib/draw-canvas/edit/index.js +112 -0
- package/lib/draw-canvas/edit/index.js.map +1 -0
- package/lib/draw-canvas/edit/index.less +34 -0
- package/lib/form/form-Item-group.d.ts.map +1 -1
- package/lib/form/form-Item-group.js +1 -1
- package/lib/form/form-Item-group.js.map +1 -1
- package/lib/icon/local-aliIcon/iconfont.js +5 -5
- package/lib/icon/local-aliIcon/iconfont.js.map +1 -1
- package/lib/table/relation-table.d.ts +4 -0
- package/lib/table/relation-table.d.ts.map +1 -1
- package/lib/tmpl/hcservice-v3.d.ts +1 -0
- package/lib/tmpl/hcservice-v3.d.ts.map +1 -1
- package/lib/tmpl/hcservice-v3.js +27 -0
- package/lib/tmpl/hcservice-v3.js.map +1 -1
- package/lib/tmpl/interface.d.ts +4 -0
- package/lib/tmpl/interface.d.ts.map +1 -1
- package/lib/tmpl/interface.js.map +1 -1
- package/lib/units/index.d.ts +1 -0
- package/lib/units/index.d.ts.map +1 -1
- package/lib/units/index.js +16 -0
- package/lib/units/index.js.map +1 -1
- package/package.json +1 -1
- package/src/aldehyde/controls/entity-select/entity-select.tsx +1 -1
- package/src/aldehyde/controls/entry-control.tsx +2 -2
- package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.css +47 -3
- package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.js +1 -1
- package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.json +77 -0
- package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.ttf +0 -0
- package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff +0 -0
- package/src/aldehyde/controls/icon-selector/icon/phonenode-menu-icon/iconfont.woff2 +0 -0
- package/src/aldehyde/draw-canvas/edit/components/asset-bar/index.less +36 -0
- package/src/aldehyde/draw-canvas/edit/components/asset-bar/index.tsx +93 -0
- package/src/aldehyde/draw-canvas/edit/components/main-header/index.less +21 -0
- package/src/aldehyde/draw-canvas/edit/components/main-header/index.tsx +187 -0
- package/src/aldehyde/draw-canvas/edit/components/render/draws/bg-draw.ts +98 -0
- package/src/aldehyde/draw-canvas/edit/components/render/draws/contextmenu-draw.ts +307 -0
- package/src/aldehyde/draw-canvas/edit/components/render/draws/graph-draw.ts +251 -0
- package/src/aldehyde/draw-canvas/edit/components/render/draws/index.ts +7 -0
- package/src/aldehyde/draw-canvas/edit/components/render/draws/link-draw.ts +1416 -0
- package/src/aldehyde/draw-canvas/edit/components/render/draws/preview-draw.ts +257 -0
- package/src/aldehyde/draw-canvas/edit/components/render/draws/ref-line-draw.ts +72 -0
- package/src/aldehyde/draw-canvas/edit/components/render/draws/ruler-draw.ts +167 -0
- package/src/aldehyde/draw-canvas/edit/components/render/graphs/base-graph.ts +241 -0
- package/src/aldehyde/draw-canvas/edit/components/render/graphs/bezier.ts +542 -0
- package/src/aldehyde/draw-canvas/edit/components/render/graphs/circle.ts +700 -0
- package/src/aldehyde/draw-canvas/edit/components/render/graphs/curve.ts +501 -0
- package/src/aldehyde/draw-canvas/edit/components/render/graphs/index.ts +6 -0
- package/src/aldehyde/draw-canvas/edit/components/render/graphs/line.ts +494 -0
- package/src/aldehyde/draw-canvas/edit/components/render/graphs/rect.ts +681 -0
- package/src/aldehyde/draw-canvas/edit/components/render/handlers/drag-handlers.ts +69 -0
- package/src/aldehyde/draw-canvas/edit/components/render/handlers/drag-outside-handlers.ts +162 -0
- package/src/aldehyde/draw-canvas/edit/components/render/handlers/graph-handlers.ts +108 -0
- package/src/aldehyde/draw-canvas/edit/components/render/handlers/index.ts +9 -0
- package/src/aldehyde/draw-canvas/edit/components/render/handlers/key-move-handlers.ts +50 -0
- package/src/aldehyde/draw-canvas/edit/components/render/handlers/link-handlers.ts +46 -0
- package/src/aldehyde/draw-canvas/edit/components/render/handlers/selection-handlers.ts +385 -0
- package/src/aldehyde/draw-canvas/edit/components/render/handlers/shutcut-handlers.ts +46 -0
- package/src/aldehyde/draw-canvas/edit/components/render/handlers/text-handlers.ts +82 -0
- package/src/aldehyde/draw-canvas/edit/components/render/handlers/zoom-handlers.ts +60 -0
- package/src/aldehyde/draw-canvas/edit/components/render/index.ts +768 -0
- package/src/aldehyde/draw-canvas/edit/components/render/tools/align-tool.ts +91 -0
- package/src/aldehyde/draw-canvas/edit/components/render/tools/asset-tool.ts +142 -0
- package/src/aldehyde/draw-canvas/edit/components/render/tools/attract-tool.ts +440 -0
- package/src/aldehyde/draw-canvas/edit/components/render/tools/copy-tool.ts +269 -0
- package/src/aldehyde/draw-canvas/edit/components/render/tools/import-export-tool.ts +603 -0
- package/src/aldehyde/draw-canvas/edit/components/render/tools/index.ts +9 -0
- package/src/aldehyde/draw-canvas/edit/components/render/tools/link-tool.ts +225 -0
- package/src/aldehyde/draw-canvas/edit/components/render/tools/position-tool.ts +212 -0
- package/src/aldehyde/draw-canvas/edit/components/render/tools/selection-tool.ts +132 -0
- package/src/aldehyde/draw-canvas/edit/components/render/tools/z-index-tool.ts +227 -0
- package/src/aldehyde/draw-canvas/edit/components/render/types.ts +287 -0
- package/src/aldehyde/draw-canvas/edit/components/render/utils/a-star.ts +116 -0
- package/src/aldehyde/draw-canvas/edit/components/render/utils/bezier-scene-func.ts +73 -0
- package/src/aldehyde/draw-canvas/edit/components/setting-form/index.tsx +200 -0
- package/src/aldehyde/draw-canvas/edit/index.less +34 -0
- package/src/aldehyde/draw-canvas/edit/index.tsx +138 -0
- package/src/aldehyde/form/form-Item-group.tsx +1 -0
- package/src/aldehyde/icon/local-aliIcon/iconfont.js +1 -1
- package/src/aldehyde/tmpl/hcservice-v3.tsx +14 -0
- package/src/aldehyde/tmpl/interface.tsx +2 -0
- package/src/aldehyde/units/index.tsx +15 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import Konva from 'konva';
|
|
2
|
+
import { Render } from '../index';
|
|
3
|
+
import { AlignType } from '../types';
|
|
4
|
+
import { GraphDraw, LinkDraw, RulerDraw, PreviewDraw } from '../draws';
|
|
5
|
+
|
|
6
|
+
// 工具栏对齐
|
|
7
|
+
|
|
8
|
+
export class AlignTool {
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
static readonly name = 'AlignTool';
|
|
11
|
+
private render: Render;
|
|
12
|
+
constructor(render: Render) {
|
|
13
|
+
this.render = render;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getAlignRect(node: Konva.Node | Konva.Transformer) {
|
|
17
|
+
const stageState = this.render.getStageState();
|
|
18
|
+
let width = 0, height = 0, x = 0, y = 0;
|
|
19
|
+
const result = node.getClientRect();
|
|
20
|
+
// 转为 逻辑觉尺寸
|
|
21
|
+
[width, height, x, y] = [
|
|
22
|
+
this.render.toStageValue(result.width),
|
|
23
|
+
this.render.toStageValue(result.height),
|
|
24
|
+
this.render.toStageValue(result.x - stageState.x),
|
|
25
|
+
this.render.toStageValue(result.y - stageState.y)
|
|
26
|
+
];
|
|
27
|
+
return { width, height, x, y };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 对齐参考点
|
|
31
|
+
getAlignPoints(node?: Konva.Node | Konva.Transformer): { [index: string]: number } {
|
|
32
|
+
let width = 0, height = 0, x = 0, y = 0;
|
|
33
|
+
if (node !== void 0) {
|
|
34
|
+
// 选择器 / 基于节点 逻辑觉尺寸
|
|
35
|
+
const rect = this.getAlignRect(node);
|
|
36
|
+
[width, height, x, y] = [rect.width, rect.height, rect.x, rect.y];
|
|
37
|
+
} else { // 默认为选择器
|
|
38
|
+
return this.getAlignPoints(this.render.transformer);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
Middle: x + width / 2,
|
|
42
|
+
Left: x,
|
|
43
|
+
Right: x + width,
|
|
44
|
+
Center: y + height / 2,
|
|
45
|
+
Top: y,
|
|
46
|
+
Bottom: y + height
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
align(type: AlignType, target?: Konva.Node) {
|
|
51
|
+
// 对齐参考点(所有)
|
|
52
|
+
const points = this.getAlignPoints(target);
|
|
53
|
+
// 对齐参考点
|
|
54
|
+
const point = points[type];
|
|
55
|
+
// 需要移动的节点
|
|
56
|
+
const nodes = this.render.transformer.nodes().filter((node) => node !== target);
|
|
57
|
+
// 移动逻辑
|
|
58
|
+
for (const node of nodes) {
|
|
59
|
+
// 逻辑觉尺寸
|
|
60
|
+
const rect = this.getAlignRect(node);
|
|
61
|
+
const [width, height, x, y] = [rect.width, rect.height, rect.x, rect.y];
|
|
62
|
+
switch (type) {
|
|
63
|
+
case "Middle":
|
|
64
|
+
case "Left":
|
|
65
|
+
case "Right":
|
|
66
|
+
{
|
|
67
|
+
const cx = type === "Middle" ? x + width / 2 : type === "Left" ? x : x + width;
|
|
68
|
+
node.x(node.x() + (point - cx));
|
|
69
|
+
}
|
|
70
|
+
break;
|
|
71
|
+
case "Center":
|
|
72
|
+
case "Top":
|
|
73
|
+
case "Bottom":
|
|
74
|
+
{
|
|
75
|
+
const cy = type === "Center" ? y + height / 2 : type === "Top" ? y : y + height;
|
|
76
|
+
node.y(node.y() + (point - cy));
|
|
77
|
+
}
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// 更新历史
|
|
82
|
+
this.render.updateHistory();
|
|
83
|
+
// 重绘
|
|
84
|
+
this.render.redraw([
|
|
85
|
+
GraphDraw.name,
|
|
86
|
+
LinkDraw.name,
|
|
87
|
+
RulerDraw.name,
|
|
88
|
+
PreviewDraw.name
|
|
89
|
+
]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import Konva from 'konva';
|
|
2
|
+
import { Render } from '../index';
|
|
3
|
+
import { PreviewDraw } from '../draws';
|
|
4
|
+
|
|
5
|
+
const gifler = (window as any).gifler;
|
|
6
|
+
|
|
7
|
+
export class AssetTool {
|
|
8
|
+
// @ts-ignore
|
|
9
|
+
static readonly name = 'AssetTool';
|
|
10
|
+
private render: Render;
|
|
11
|
+
constructor(render: Render) {
|
|
12
|
+
this.render = render;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// 加载 svg xml
|
|
16
|
+
async loadSvgXML(svgXML: string) {
|
|
17
|
+
const blob = new Blob([svgXML], { type: 'image/svg+xml' });
|
|
18
|
+
const url = URL.createObjectURL(blob);
|
|
19
|
+
return new Promise<Konva.Image>((resolve) => {
|
|
20
|
+
Konva.Image.fromURL(url, (imageNode) => {
|
|
21
|
+
imageNode.setAttrs({ svgXML } as any);
|
|
22
|
+
resolve(imageNode);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 加载 svg
|
|
28
|
+
async loadSvg(src: string) {
|
|
29
|
+
const svgXML = await (await fetch(src)).text();
|
|
30
|
+
return this.loadSvgXML(this.render.setSvgXMLSettings(svgXML, this.render.getAssetSettings()));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 加载 gif
|
|
34
|
+
async loadGif(src: string) {
|
|
35
|
+
return new Promise<Konva.Image>((resolve) => {
|
|
36
|
+
const img = document.createElement('img');
|
|
37
|
+
img.onload = () => {
|
|
38
|
+
const canvas = document.createElement('canvas');
|
|
39
|
+
canvas.width = img.naturalWidth;
|
|
40
|
+
canvas.height = img.naturalHeight;
|
|
41
|
+
const gif = gifler(src);
|
|
42
|
+
gif.frames(canvas, (ctx: CanvasRenderingContext2D, frame: any) => {
|
|
43
|
+
ctx.drawImage(frame.buffer, frame.x, frame.y);
|
|
44
|
+
this.render.layer.draw();
|
|
45
|
+
// 更新预览(layer)
|
|
46
|
+
this.render.draws[PreviewDraw.name]?.layer.draw();
|
|
47
|
+
});
|
|
48
|
+
img.remove();
|
|
49
|
+
// TODO: 拖动 gif 素材产生大量 JS event listeners
|
|
50
|
+
resolve(new Konva.Image({ image: canvas, gif: src }));
|
|
51
|
+
}
|
|
52
|
+
img.src = src;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 加载图片
|
|
57
|
+
async loadImg(src: string) {
|
|
58
|
+
return new Promise<Konva.Image>((resolve) => {
|
|
59
|
+
Konva.Image.fromURL(src, (imageNode) => {
|
|
60
|
+
imageNode.setAttrs({ src } as any);
|
|
61
|
+
resolve(imageNode);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 加载节点 json
|
|
67
|
+
async loadJson(src: string) {
|
|
68
|
+
try {
|
|
69
|
+
// 读取 json内容
|
|
70
|
+
const json = JSON.parse(await (await fetch(src)).text());
|
|
71
|
+
// 子素材
|
|
72
|
+
const assets = json.children;
|
|
73
|
+
// 刷新id
|
|
74
|
+
this.render.linkTool.jsonIdCover(assets);
|
|
75
|
+
// 生成空白 stage+layer
|
|
76
|
+
const stageEmpty = new Konva.Stage({ container: document.createElement('div') });
|
|
77
|
+
const layerEmpty = new Konva.Layer();
|
|
78
|
+
stageEmpty.add(layerEmpty);
|
|
79
|
+
// 空白 json 根
|
|
80
|
+
const jsonRoot = JSON.parse(stageEmpty.toJSON());
|
|
81
|
+
jsonRoot.children[0].children = [json];
|
|
82
|
+
// 重新加载 stage
|
|
83
|
+
const stageReload = Konva.Node.create(JSON.stringify(jsonRoot), document.createElement('div'));
|
|
84
|
+
// 目标 group(即 json 转化后的节点)
|
|
85
|
+
const groupTarget = stageReload.children[0].children[0] as Konva.Group;
|
|
86
|
+
// 释放内存
|
|
87
|
+
stageEmpty.destroy();
|
|
88
|
+
groupTarget.remove();
|
|
89
|
+
stageReload.destroy();
|
|
90
|
+
// 深度遍历加载子素材
|
|
91
|
+
const nodes: {
|
|
92
|
+
target: Konva.Stage | Konva.Layer | Konva.Group | Konva.Node
|
|
93
|
+
parent?: Konva.Stage | Konva.Layer | Konva.Group | Konva.Node
|
|
94
|
+
}[] = [{ target: groupTarget }];
|
|
95
|
+
while (nodes.length > 0) {
|
|
96
|
+
const item = nodes.shift();
|
|
97
|
+
if (item) {
|
|
98
|
+
const node = item.target;
|
|
99
|
+
if (node instanceof Konva.Image) {
|
|
100
|
+
if (node.attrs.svgXML) {
|
|
101
|
+
const n = await this.loadSvgXML(node.attrs.svgXML);
|
|
102
|
+
n.listening(false);
|
|
103
|
+
node.parent?.add(n);
|
|
104
|
+
node.remove();
|
|
105
|
+
} else if (node.attrs.gif) {
|
|
106
|
+
const n = await this.loadGif(node.attrs.gif);
|
|
107
|
+
n.listening(false);
|
|
108
|
+
node.parent?.add(n);
|
|
109
|
+
node.remove();
|
|
110
|
+
} else if (node.attrs.src) {
|
|
111
|
+
const n = await this.loadImg(node.attrs.src);
|
|
112
|
+
n.listening(false);
|
|
113
|
+
node.parent?.add(n);
|
|
114
|
+
node.remove();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (node instanceof Konva.Stage || node instanceof Konva.Layer || node instanceof Konva.Group) {
|
|
118
|
+
nodes.push(
|
|
119
|
+
...node.getChildren().map((o) => ({
|
|
120
|
+
target: o,
|
|
121
|
+
parent: node
|
|
122
|
+
}))
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 作用:点击空白区域可选择
|
|
129
|
+
const clickMask = new Konva.Rect({
|
|
130
|
+
id: 'click-mask',
|
|
131
|
+
width: groupTarget.width(),
|
|
132
|
+
height: groupTarget.height()
|
|
133
|
+
});
|
|
134
|
+
groupTarget.add(clickMask);
|
|
135
|
+
clickMask.zIndex(1)
|
|
136
|
+
return groupTarget;
|
|
137
|
+
} catch (e) {
|
|
138
|
+
console.error(e);
|
|
139
|
+
return new Konva.Group();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import Konva from 'konva';
|
|
2
|
+
import { Render } from '../index';
|
|
3
|
+
import { SortItem } from '../types';
|
|
4
|
+
|
|
5
|
+
interface AlignRect {
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
type SortItemPair = [SortItem, SortItem];
|
|
13
|
+
|
|
14
|
+
export class AttractTool {
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
static readonly name = 'AttractTool';
|
|
17
|
+
|
|
18
|
+
private render: Render;
|
|
19
|
+
constructor(render: Render) {
|
|
20
|
+
this.render = render;
|
|
21
|
+
}
|
|
22
|
+
// 对齐线
|
|
23
|
+
alignLines: Konva.Line[] = [];
|
|
24
|
+
|
|
25
|
+
// 对齐线清除
|
|
26
|
+
alignLinesClear() {
|
|
27
|
+
for (const line of this.alignLines) {
|
|
28
|
+
line.destroy();
|
|
29
|
+
}
|
|
30
|
+
this.alignLines = [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
getSortItems(rect: AlignRect) {
|
|
34
|
+
const stageState = this.render.getStageState();
|
|
35
|
+
// 横向所有需要判断对齐的 x 坐标
|
|
36
|
+
const sortX: Array<SortItem> = [];
|
|
37
|
+
// 纵向向所有需要判断对齐的 y 坐标
|
|
38
|
+
const sortY: Array<SortItem> = [];
|
|
39
|
+
// 选择目标所有的对齐 x
|
|
40
|
+
sortX.push(
|
|
41
|
+
{ value: this.render.toStageValue(rect.x - stageState.x) },
|
|
42
|
+
{ value: this.render.toStageValue(rect.x - stageState.x + rect.width / 2) },
|
|
43
|
+
{ value: this.render.toStageValue(rect.x - stageState.x + rect.width) }
|
|
44
|
+
);
|
|
45
|
+
// 选择目标所有的对齐 y
|
|
46
|
+
sortY.push(
|
|
47
|
+
{ value: this.render.toStageValue(rect.y - stageState.y) },
|
|
48
|
+
{ value: this.render.toStageValue(rect.y - stageState.y + rect.height / 2) },
|
|
49
|
+
{ value: this.render.toStageValue(rect.y - stageState.y + rect.height) }
|
|
50
|
+
);
|
|
51
|
+
// 拖动目标
|
|
52
|
+
const targetIds = this.render.selectionTool.selectingNodes.map((o) => o._id);
|
|
53
|
+
// 除拖动目标的其他
|
|
54
|
+
const otherNodes = this.render.layer.find('.asset').filter((node) => !targetIds.includes(node._id));
|
|
55
|
+
// 其他节点所有的 x / y 坐标
|
|
56
|
+
for (const node of otherNodes) {
|
|
57
|
+
const nodeRect = node.getClientRect();
|
|
58
|
+
sortX.push(
|
|
59
|
+
{ id: node._id, value: this.render.toStageValue(nodeRect.x - stageState.x) },
|
|
60
|
+
{ id: node._id, value: this.render.toStageValue(nodeRect.x - stageState.x + nodeRect.width / 2) },
|
|
61
|
+
{ id: node._id, value: this.render.toStageValue(nodeRect.x - stageState.x + nodeRect.width) }
|
|
62
|
+
);
|
|
63
|
+
sortY.push(
|
|
64
|
+
{ id: node._id, value: this.render.toStageValue(nodeRect.y - stageState.y) },
|
|
65
|
+
{ id: node._id, value: this.render.toStageValue(nodeRect.y - stageState.y + nodeRect.height / 2) },
|
|
66
|
+
{ id: node._id, value: this.render.toStageValue(nodeRect.y - stageState.y + nodeRect.height) }
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
sortX.sort((a, b) => a.value - b.value);
|
|
70
|
+
sortY.sort((a, b) => a.value - b.value);
|
|
71
|
+
return { sortX, sortY };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
attractPoint = (pos: Konva.Vector2d) => {
|
|
75
|
+
this.alignLinesClear(); // 对齐线清除
|
|
76
|
+
const stageState = this.render.getStageState();
|
|
77
|
+
let newPosX = pos.x;
|
|
78
|
+
let newPosY = pos.y;
|
|
79
|
+
let isAttract = false;
|
|
80
|
+
let pairX: SortItemPair | null = null;
|
|
81
|
+
let pairY: SortItemPair | null = null;
|
|
82
|
+
// 对齐线 磁吸逻辑
|
|
83
|
+
if (!this.render.config.readonly && this.render.config.attractNode) {
|
|
84
|
+
const sortX = [{ value: this.render.toStageValue(newPosX - stageState.x) }] as SortItem[],
|
|
85
|
+
sortY = [{ value: this.render.toStageValue(newPosY - stageState.y) }] as SortItem[];
|
|
86
|
+
// x 最短距离
|
|
87
|
+
let XMin = Infinity;
|
|
88
|
+
// x 最短距离的【对】(多个)
|
|
89
|
+
let pairXMin: Array<SortItemPair> = [];
|
|
90
|
+
// y 最短距离
|
|
91
|
+
let YMin = Infinity;
|
|
92
|
+
// y 最短距离的【对】(多个)
|
|
93
|
+
let pairYMin: Array<SortItemPair> = [];
|
|
94
|
+
// 一对对比较距离,记录最短距离的【对】
|
|
95
|
+
// 必须是 选择目标 与 其他节点 成【对】
|
|
96
|
+
// 可能有多个这样的【对】
|
|
97
|
+
for (let i = 0; i < sortX.length - 1; i++) {
|
|
98
|
+
// 相邻两个点,必须为 目标节点 + 非目标节点
|
|
99
|
+
if ((sortX[i].id === void 0 && sortX[i + 1].id !== void 0) || (sortX[i].id !== void 0 && sortX[i + 1].id === void 0)) {
|
|
100
|
+
// 相邻两个点的 x 距离
|
|
101
|
+
const offset = Math.abs(sortX[i].value - sortX[i + 1].value);
|
|
102
|
+
if (offset < XMin) {
|
|
103
|
+
// 更新 x 最短距离 记录
|
|
104
|
+
XMin = offset;
|
|
105
|
+
// 更新 x 最短距离的【对】 记录
|
|
106
|
+
pairXMin = [[sortX[i], sortX[i + 1]]];
|
|
107
|
+
} else if (offset === XMin) {
|
|
108
|
+
// 存在多个 x 最短距离
|
|
109
|
+
pairXMin.push([sortX[i], sortX[i + 1]]);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
for (let i = 0; i < sortY.length - 1; i++) {
|
|
114
|
+
// 相邻两个点,必须为 目标节点 + 非目标节点
|
|
115
|
+
if ((sortY[i].id === void 0 && sortY[i + 1].id !== void 0) || (sortY[i].id !== void 0 && sortY[i + 1].id === void 0)) {
|
|
116
|
+
// 相邻两个点的 y 距离
|
|
117
|
+
const offset = Math.abs(sortY[i].value - sortY[i + 1].value);
|
|
118
|
+
if (offset < YMin) {
|
|
119
|
+
// 更新 y 最短距离 记录
|
|
120
|
+
YMin = offset;
|
|
121
|
+
// 更新 y 最短距离的【对】 记录
|
|
122
|
+
pairYMin = [[sortY[i], sortY[i + 1]]];
|
|
123
|
+
} else if (offset === YMin) {
|
|
124
|
+
// 存在多个 y 最短距离
|
|
125
|
+
pairYMin.push([sortY[i], sortY[i + 1]]);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// 取第一【对】,用于判断距离是否在阈值内
|
|
130
|
+
if (pairXMin[0]) {
|
|
131
|
+
if (Math.abs(pairXMin[0][0].value - pairXMin[0][1].value) < this.render.bgSize / 2) {
|
|
132
|
+
pairX = pairXMin[0];
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (pairYMin[0]) {
|
|
136
|
+
if (Math.abs(pairYMin[0][0].value - pairYMin[0][1].value) < this.render.bgSize / 2) {
|
|
137
|
+
pairY = pairYMin[0];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// 优先对齐节点
|
|
141
|
+
// 存在 1或多个 x 最短距离 满足阈值
|
|
142
|
+
if (pairX?.length === 2) {
|
|
143
|
+
for (const pair of pairXMin) {
|
|
144
|
+
// 【对】里的那个非目标节点
|
|
145
|
+
const other = pair.find((o) => o.id !== void 0);
|
|
146
|
+
if (other) { // x 对齐线
|
|
147
|
+
const line = new Konva.Line({
|
|
148
|
+
points: [[other.value, this.render.toStageValue(-stageState.y)], [other.value, this.render.toStageValue(this.render.stage.height() - stageState.y)]].flat(),
|
|
149
|
+
stroke: 'blue',
|
|
150
|
+
strokeWidth: this.render.toStageValue(1),
|
|
151
|
+
dash: [4, 4],
|
|
152
|
+
listening: false
|
|
153
|
+
});
|
|
154
|
+
this.alignLines.push(line);
|
|
155
|
+
this.render.layerCover.add(line);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// 磁贴第一个【对】
|
|
159
|
+
const target = pairX.find((o) => o.id === void 0);
|
|
160
|
+
const other = pairX.find((o) => o.id !== void 0);
|
|
161
|
+
if (target && other) {
|
|
162
|
+
// 磁铁坐标值
|
|
163
|
+
newPosX = newPosX - this.render.toBoardValue(target.value - other.value);
|
|
164
|
+
isAttract = true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// 存在 1或多个 y 最短距离 满足阈值
|
|
168
|
+
if (pairY?.length === 2) {
|
|
169
|
+
for (const pair of pairYMin) {
|
|
170
|
+
// 【对】里的那个非目标节点
|
|
171
|
+
const other = pair.find((o) => o.id !== void 0);
|
|
172
|
+
if (other) {
|
|
173
|
+
// y 对齐线
|
|
174
|
+
const line = new Konva.Line({
|
|
175
|
+
points: [[this.render.toStageValue(-stageState.x), other.value], [this.render.toStageValue(this.render.stage.width() - stageState.x), other.value]].flat(),
|
|
176
|
+
stroke: 'blue',
|
|
177
|
+
strokeWidth: this.render.toStageValue(1),
|
|
178
|
+
dash: [4, 4],
|
|
179
|
+
listening: false
|
|
180
|
+
});
|
|
181
|
+
this.alignLines.push(line);
|
|
182
|
+
this.render.layerCover.add(line);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// 磁贴第一个【对】
|
|
186
|
+
const target = pairY.find((o) => o.id === void 0);
|
|
187
|
+
const other = pairY.find((o) => o.id !== void 0);
|
|
188
|
+
if (target && other) {
|
|
189
|
+
// 磁铁坐标值
|
|
190
|
+
newPosY = newPosY - this.render.toBoardValue(target.value - other.value);
|
|
191
|
+
isAttract = true;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (!this.render.config.readonly && this.render.config.attractBg) {
|
|
196
|
+
// 没有 x 对齐节点
|
|
197
|
+
if (pairX === null) {
|
|
198
|
+
const logicLeftX = this.render.toStageValue(newPosX - stageState.x); // x坐标
|
|
199
|
+
const logicNumLeftX = Math.round(logicLeftX / this.render.bgSize); // x单元格个数
|
|
200
|
+
const logicClosestLeftX = logicNumLeftX * this.render.bgSize; // x磁贴目标坐标
|
|
201
|
+
const logicDiffLeftX = Math.abs(logicLeftX - logicClosestLeftX); // x磁贴偏移量
|
|
202
|
+
const logicRightX = this.render.toStageValue(newPosX - stageState.x); // x坐标
|
|
203
|
+
const logicNumRightX = Math.round(logicRightX / this.render.bgSize); // x单元格个数
|
|
204
|
+
const logicClosestRightX = logicNumRightX * this.render.bgSize; // x磁贴目标坐标
|
|
205
|
+
const logicDiffRightX = Math.abs(logicRightX - logicClosestRightX); // x磁贴偏移量
|
|
206
|
+
// stage 逻辑边界磁贴
|
|
207
|
+
const logicStageRightX = stageState.width;
|
|
208
|
+
const logicDiffStageRightX = Math.abs(logicRightX - logicStageRightX);
|
|
209
|
+
// 距离近优先
|
|
210
|
+
for (const diff of [{ type: 'leftX', value: logicDiffLeftX }, { type: 'rightX', value: logicDiffRightX }, { type: 'stageRightX', value: logicDiffStageRightX }].sort((a, b) => a.value - b.value)) {
|
|
211
|
+
if (diff.value < 5) {
|
|
212
|
+
if (diff.type === 'stageRightX') {
|
|
213
|
+
newPosX = this.render.toBoardValue(logicStageRightX) + stageState.x;
|
|
214
|
+
} else if (diff.type === 'leftX') {
|
|
215
|
+
newPosX = this.render.toBoardValue(logicClosestLeftX) + stageState.x;
|
|
216
|
+
} else if (diff.type === 'rightX') {
|
|
217
|
+
newPosX = this.render.toBoardValue(logicClosestRightX) + stageState.x;
|
|
218
|
+
}
|
|
219
|
+
isAttract = true;
|
|
220
|
+
break;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// 没有 y 对齐节点
|
|
225
|
+
if (pairY === null) {
|
|
226
|
+
const logicTopY = this.render.toStageValue(newPosY - stageState.y); // y坐标
|
|
227
|
+
const logicNumTopY = Math.round(logicTopY / this.render.bgSize); // y单元格个数
|
|
228
|
+
const logicClosestTopY = logicNumTopY * this.render.bgSize; // y磁贴目标坐标
|
|
229
|
+
const logicDiffTopY = Math.abs(logicTopY - logicClosestTopY); // y磁贴偏移量
|
|
230
|
+
const logicBottomY = this.render.toStageValue(newPosY - stageState.y); // y坐标
|
|
231
|
+
const logicNumBottomY = Math.round(logicBottomY / this.render.bgSize); // y单元格个数
|
|
232
|
+
const logicClosestBottomY = logicNumBottomY * this.render.bgSize; // y磁贴目标坐标
|
|
233
|
+
const logicDiffBottomY = Math.abs(logicBottomY - logicClosestBottomY); // y磁贴偏移量
|
|
234
|
+
// stage 逻辑边界磁贴
|
|
235
|
+
const logicStageBottomY = stageState.height;
|
|
236
|
+
const logicDiffStageBottomY = Math.abs(logicBottomY - logicStageBottomY);
|
|
237
|
+
// 距离近优先
|
|
238
|
+
for (const diff of [{ type: 'topY', value: logicDiffTopY }, { type: 'bottomY', value: logicDiffBottomY }, { type: 'stageBottomY', value: logicDiffStageBottomY }].sort((a, b) => a.value - b.value)) {
|
|
239
|
+
if (diff.value < 5) {
|
|
240
|
+
if (diff.type === 'stageBottomY') {
|
|
241
|
+
newPosY = this.render.toBoardValue(logicStageBottomY) + stageState.y;
|
|
242
|
+
} else if (diff.type === 'topY') {
|
|
243
|
+
newPosY = this.render.toBoardValue(logicClosestTopY) + stageState.y;
|
|
244
|
+
} else if (diff.type === 'bottomY') {
|
|
245
|
+
newPosY = this.render.toBoardValue(logicClosestBottomY) + stageState.y;
|
|
246
|
+
}
|
|
247
|
+
isAttract = true;
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return { pos: { x: newPosX, y: newPosY }, isAttract };
|
|
254
|
+
}
|
|
255
|
+
// 磁吸逻辑
|
|
256
|
+
attractTransformer = (rect: AlignRect) => {
|
|
257
|
+
// 对齐线清除
|
|
258
|
+
this.alignLinesClear();
|
|
259
|
+
const stageState = this.render.getStageState();
|
|
260
|
+
const width = this.render.transformer.width();
|
|
261
|
+
const height = this.render.transformer.height();
|
|
262
|
+
let newPosX = rect.x;
|
|
263
|
+
let newPosY = rect.y;
|
|
264
|
+
let isAttract = false;
|
|
265
|
+
let pairX: SortItemPair | null = null;
|
|
266
|
+
let pairY: SortItemPair | null = null;
|
|
267
|
+
// 对齐线 磁吸逻辑
|
|
268
|
+
if (!this.render.config.readonly && this.render.config.attractNode) {
|
|
269
|
+
const { sortX, sortY } = this.getSortItems(rect);
|
|
270
|
+
// x 最短距离
|
|
271
|
+
let XMin = Infinity;
|
|
272
|
+
// x 最短距离的【对】(多个)
|
|
273
|
+
let pairXMin: Array<SortItemPair> = [];
|
|
274
|
+
// y 最短距离
|
|
275
|
+
let YMin = Infinity;
|
|
276
|
+
// y 最短距离的【对】(多个)
|
|
277
|
+
let pairYMin: Array<SortItemPair> = [];
|
|
278
|
+
// 一对对比较距离,记录最短距离的【对】
|
|
279
|
+
// 必须是 选择目标 与 其他节点 成【对】
|
|
280
|
+
// 可能有多个这样的【对】
|
|
281
|
+
for (let i = 0; i < sortX.length - 1; i++) {
|
|
282
|
+
// 相邻两个点,必须为 目标节点 + 非目标节点
|
|
283
|
+
if ((sortX[i].id === void 0 && sortX[i + 1].id !== void 0) || (sortX[i].id !== void 0 && sortX[i + 1].id === void 0)) {
|
|
284
|
+
// 相邻两个点的 x 距离
|
|
285
|
+
const offset = Math.abs(sortX[i].value - sortX[i + 1].value)
|
|
286
|
+
if (offset < XMin) {
|
|
287
|
+
// 更新 x 最短距离 记录
|
|
288
|
+
XMin = offset;
|
|
289
|
+
// 更新 x 最短距离的【对】 记录
|
|
290
|
+
pairXMin = [[sortX[i], sortX[i + 1]]];
|
|
291
|
+
} else if (offset === XMin) {
|
|
292
|
+
// 存在多个 x 最短距离
|
|
293
|
+
pairXMin.push([sortX[i], sortX[i + 1]]);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
for (let i = 0; i < sortY.length - 1; i++) {
|
|
298
|
+
// 相邻两个点,必须为 目标节点 + 非目标节点
|
|
299
|
+
if ((sortY[i].id === void 0 && sortY[i + 1].id !== void 0) || (sortY[i].id !== void 0 && sortY[i + 1].id === void 0)) {
|
|
300
|
+
// 相邻两个点的 y 距离
|
|
301
|
+
const offset = Math.abs(sortY[i].value - sortY[i + 1].value);
|
|
302
|
+
if (offset < YMin) {
|
|
303
|
+
// 更新 y 最短距离 记录
|
|
304
|
+
YMin = offset;
|
|
305
|
+
// 更新 y 最短距离的【对】 记录
|
|
306
|
+
pairYMin = [[sortY[i], sortY[i + 1]]];
|
|
307
|
+
} else if (offset === YMin) {
|
|
308
|
+
// 存在多个 y 最短距离
|
|
309
|
+
pairYMin.push([sortY[i], sortY[i + 1]]);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// 取第一【对】,用于判断距离是否在阈值内
|
|
314
|
+
if (pairXMin[0]) {
|
|
315
|
+
if (Math.abs(pairXMin[0][0].value - pairXMin[0][1].value) < this.render.bgSize / 2) {
|
|
316
|
+
pairX = pairXMin[0];
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
if (pairYMin[0]) {
|
|
320
|
+
if (Math.abs(pairYMin[0][0].value - pairYMin[0][1].value) < this.render.bgSize / 2) {
|
|
321
|
+
pairY = pairYMin[0];
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
// 优先对齐节点
|
|
325
|
+
// 存在 1或多个 x 最短距离 满足阈值
|
|
326
|
+
if (pairX?.length === 2) {
|
|
327
|
+
for (const pair of pairXMin) {
|
|
328
|
+
// 【对】里的那个非目标节点
|
|
329
|
+
const other = pair.find((o) => o.id !== void 0);
|
|
330
|
+
if (other) {
|
|
331
|
+
// x 对齐线
|
|
332
|
+
const line = new Konva.Line({
|
|
333
|
+
points: [[other.value, this.render.toStageValue(-stageState.y)], [other.value, this.render.toStageValue(this.render.stage.height() - stageState.y)]].flat(),
|
|
334
|
+
stroke: 'blue',
|
|
335
|
+
strokeWidth: this.render.toStageValue(1),
|
|
336
|
+
dash: [4, 4],
|
|
337
|
+
listening: false
|
|
338
|
+
});
|
|
339
|
+
this.alignLines.push(line);
|
|
340
|
+
this.render.layerCover.add(line);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
// 磁贴第一个【对】
|
|
344
|
+
const target = pairX.find((o) => o.id === void 0);
|
|
345
|
+
const other = pairX.find((o) => o.id !== void 0);
|
|
346
|
+
if (target && other) {
|
|
347
|
+
// 磁贴坐标值
|
|
348
|
+
newPosX = newPosX - this.render.toBoardValue(target.value - other.value);
|
|
349
|
+
isAttract = true;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
// 存在 1或多个 y 最短距离 满足阈值
|
|
353
|
+
if (pairY?.length === 2) {
|
|
354
|
+
for (const pair of pairYMin) {
|
|
355
|
+
// 【对】里的那个非目标节点
|
|
356
|
+
const other = pair.find((o) => o.id !== void 0);
|
|
357
|
+
if (other) {
|
|
358
|
+
// y 对齐线
|
|
359
|
+
const line = new Konva.Line({
|
|
360
|
+
points: [[this.render.toStageValue(-stageState.x), other.value], [this.render.toStageValue(this.render.stage.width() - stageState.x), other.value]].flat(),
|
|
361
|
+
stroke: 'blue',
|
|
362
|
+
strokeWidth: this.render.toStageValue(1),
|
|
363
|
+
dash: [4, 4],
|
|
364
|
+
listening: false
|
|
365
|
+
});
|
|
366
|
+
this.alignLines.push(line);
|
|
367
|
+
this.render.layerCover.add(line);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
// 磁贴第一个【对】
|
|
371
|
+
const target = pairY.find((o) => o.id === void 0);
|
|
372
|
+
const other = pairY.find((o) => o.id !== void 0);
|
|
373
|
+
if (target && other) {
|
|
374
|
+
// 磁贴坐标值
|
|
375
|
+
newPosY = newPosY - this.render.toBoardValue(target.value - other.value);
|
|
376
|
+
isAttract = true;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (!this.render.config.readonly && this.render.config.attractBg) {
|
|
381
|
+
// 没有 x 对齐节点
|
|
382
|
+
if (pairX === null) {
|
|
383
|
+
const logicLeftX = this.render.toStageValue(newPosX - stageState.x); // x坐标
|
|
384
|
+
const logicNumLeftX = Math.round(logicLeftX / this.render.bgSize); // x单元格个数
|
|
385
|
+
const logicClosestLeftX = logicNumLeftX * this.render.bgSize; // x磁贴目标坐标
|
|
386
|
+
const logicDiffLeftX = Math.abs(logicLeftX - logicClosestLeftX); // x磁贴偏移量
|
|
387
|
+
const logicRightX = this.render.toStageValue(newPosX + width - stageState.x); // x坐标
|
|
388
|
+
const logicNumRightX = Math.round(logicRightX / this.render.bgSize); // x单元格个数
|
|
389
|
+
const logicClosestRightX = logicNumRightX * this.render.bgSize; // x磁贴目标坐标
|
|
390
|
+
const logicDiffRightX = Math.abs(logicRightX - logicClosestRightX); // x磁贴偏移量
|
|
391
|
+
// stage 逻辑边界磁贴
|
|
392
|
+
const logicStageRightX = stageState.width;
|
|
393
|
+
const logicDiffStageRightX = Math.abs(logicRightX - logicStageRightX);
|
|
394
|
+
// 距离近优先
|
|
395
|
+
for (const diff of [{ type: 'leftX', value: logicDiffLeftX }, { type: 'rightX', value: logicDiffRightX }, { type: 'stageRightX', value: logicDiffStageRightX }].sort((a, b) => a.value - b.value)) {
|
|
396
|
+
if (diff.value < 5) {
|
|
397
|
+
if (diff.type === 'stageRightX') {
|
|
398
|
+
newPosX = this.render.toBoardValue(logicStageRightX) + stageState.x - width;
|
|
399
|
+
} else if (diff.type === 'leftX') {
|
|
400
|
+
newPosX = this.render.toBoardValue(logicClosestLeftX) + stageState.x;
|
|
401
|
+
} else if (diff.type === 'rightX') {
|
|
402
|
+
newPosX = this.render.toBoardValue(logicClosestRightX) + stageState.x - width;
|
|
403
|
+
}
|
|
404
|
+
isAttract = true;
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
// 没有 y 对齐节点
|
|
410
|
+
if (pairY === null) {
|
|
411
|
+
const logicTopY = this.render.toStageValue(newPosY - stageState.y); // y坐标
|
|
412
|
+
const logicNumTopY = Math.round(logicTopY / this.render.bgSize); // y单元格个数
|
|
413
|
+
const logicClosestTopY = logicNumTopY * this.render.bgSize; // y磁贴目标坐标
|
|
414
|
+
const logicDiffTopY = Math.abs(logicTopY - logicClosestTopY); // y磁贴偏移量
|
|
415
|
+
const logicBottomY = this.render.toStageValue(newPosY + height - stageState.y); // y坐标
|
|
416
|
+
const logicNumBottomY = Math.round(logicBottomY / this.render.bgSize); // y单元格个数
|
|
417
|
+
const logicClosestBottomY = logicNumBottomY * this.render.bgSize; // y磁贴目标坐标
|
|
418
|
+
const logicDiffBottomY = Math.abs(logicBottomY - logicClosestBottomY); // y磁贴偏移量
|
|
419
|
+
// stage 逻辑边界磁贴
|
|
420
|
+
const logicStageBottomY = stageState.height;
|
|
421
|
+
const logicDiffStageBottomY = Math.abs(logicBottomY - logicStageBottomY);
|
|
422
|
+
// 距离近优先
|
|
423
|
+
for (const diff of [{ type: 'topY', value: logicDiffTopY }, { type: 'bottomY', value: logicDiffBottomY }, { type: 'stageBottomY', value: logicDiffStageBottomY }].sort((a, b) => a.value - b.value)) {
|
|
424
|
+
if (diff.value < 5) {
|
|
425
|
+
if (diff.type === 'stageBottomY') {
|
|
426
|
+
newPosY = this.render.toBoardValue(logicStageBottomY) + stageState.y - height;
|
|
427
|
+
} else if (diff.type === 'topY') {
|
|
428
|
+
newPosY = this.render.toBoardValue(logicClosestTopY) + stageState.y;
|
|
429
|
+
} else if (diff.type === 'bottomY') {
|
|
430
|
+
newPosY = this.render.toBoardValue(logicClosestBottomY) + stageState.y - height;
|
|
431
|
+
}
|
|
432
|
+
isAttract = true;
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return { pos: { x: newPosX, y: newPosY }, isAttract };
|
|
439
|
+
}
|
|
440
|
+
}
|