Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): snap the text pos of cloneNode to grid(#1545) #1550

Merged
merged 1 commit into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions packages/core/__tests__/bugs/1545-spec.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { NodeConfig, TextConfig } from '../../src/index';
import { LogicFlow } from '../../src/index';

type NodeConfigTextObj = NodeConfig & { text: TextConfig };
describe('#1545', () => {
const dom = document.createElement('div');
dom.id = 'main-graph';
document.body.appendChild(dom);
const lf = new LogicFlow({
container: dom,
width: 1000,
height: 1000,
grid: true,
});

it('clone node text pos should snap to grid', () => {
lf.render({
nodes: [
{
id: 'node_id_1',
type: 'rect',
x: 300,
y: 300,
text: {
x: 32,
y: 19,
value: '文本1',
},
},
],
});
const originNode = lf.getDataById('node_id_1') as NodeConfigTextObj;
const newNode = lf.cloneNode('node_id_1') as NodeConfigTextObj;
expect(originNode.x - originNode.text.x).toEqual(newNode.x - newNode.text.x);
expect(originNode.y - originNode.text.y).toEqual(newNode.y - newNode.text.y);
expect(originNode.text.value).toEqual(newNode.text.value);
});
});
67 changes: 67 additions & 0 deletions packages/core/__tests__/model/graphmodel.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import type { NodeConfig, TextConfig } from '../../src/index';
import { LogicFlow } from '../../src/index';

type NodeConfigTextObj = NodeConfig & { text: TextConfig };
describe('graphmodel', () => {
const dom = document.createElement('div');
dom.id = 'main-graph';
document.body.appendChild(dom);
const lf = new LogicFlow({
container: dom,
width: 1000,
height: 1000,
keyboard: {
enabled: true,
},
allowRotation: true,
metaKeyMultipleSelected: true,
grid: true,
snapline: true,
});

// 将node节点位置进行grid修正,同时处理node内文字的偏移量,返回一个位置修正过的复制节点NodeModel
test('getModelAfterSnapToGrid', () => {
const rawData = {
nodes: [
{
id: 'node1',
type: 'rect',
x: 111,
y: 123,
text: {
x: 32,
y: 19,
value: '文本1',
},
},
],
};
lf.render(rawData);

const originNode = lf.getDataById('node1') as NodeConfigTextObj;

// grid=true 默认 gridSize=20
const newNode = lf.graphModel.getModelAfterSnapToGrid(originNode) as NodeConfigTextObj;
expect(originNode.x - originNode.text.x).toEqual(newNode.x - newNode.text.x);
expect(originNode.y - originNode.text.y).toEqual(newNode.y - newNode.text.y);
expect(originNode.text.value).toEqual(newNode.text.value);

lf.graphModel.gridSize = 40;
const newNode1 = lf.graphModel.getModelAfterSnapToGrid(originNode) as NodeConfigTextObj;
expect(originNode.x - originNode.text.x).toEqual(newNode1.x - newNode1.text.x);
expect(originNode.y - originNode.text.y).toEqual(newNode1.y - newNode1.text.y);
expect(originNode.text.value).toEqual(newNode1.text.value);

lf.graphModel.gridSize = 1;
const newNode2 = lf.graphModel.getModelAfterSnapToGrid(originNode) as NodeConfigTextObj;
expect(originNode.x - originNode.text.x).toEqual(newNode2.x - newNode2.text.x);
expect(originNode.y - originNode.text.y).toEqual(newNode2.y - newNode2.text.y);
expect(originNode.text.value).toEqual(newNode2.text.value);

lf.graphModel.gridSize = 17;
const newNode3 = lf.graphModel.getModelAfterSnapToGrid(originNode) as NodeConfigTextObj;
expect(originNode.x - originNode.text.x).toEqual(newNode3.x - newNode3.text.x);
expect(originNode.y - originNode.text.y).toEqual(newNode3.y - newNode3.text.y);
expect(originNode.text.value).toEqual(newNode3.text.value);
});
});
56 changes: 31 additions & 25 deletions packages/core/src/model/GraphModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,23 +380,7 @@ class GraphModel {
return;
}
if (graphData.nodes) {
this.nodes = map(graphData.nodes, node => {
const Model = this.getModel(node.type);
if (!Model) {
throw new Error(`找不到${node.type}对应的节点。`);
}
const { x: nodeX, y: nodeY } = node;
// 根据 grid 修正节点的 x, y
if (nodeX && nodeY) {
node.x = snapToGrid(nodeX, this.gridSize);
node.y = snapToGrid(nodeY, this.gridSize);
if (typeof node.text === 'object') {
node.text.x -= getGridOffset(nodeX, this.gridSize);
node.text.y -= getGridOffset(nodeY, this.gridSize);
}
}
return new Model(node, this);
});
this.nodes = map(graphData.nodes, (node: NodeConfig) => this.getModelAfterSnapToGrid(node));
} else {
this.nodes = [];
}
Expand Down Expand Up @@ -681,13 +665,7 @@ class GraphModel {
if (nodeOriginData.id && this.nodesMap[nodeConfig.id]) {
delete nodeOriginData.id;
}
const Model = this.getModel(nodeOriginData.type);
if (!Model) {
throw new Error(`找不到${nodeOriginData.type}对应的节点,请确认是否已注册此类型节点。`);
}
nodeOriginData.x = snapToGrid(nodeOriginData.x, this.gridSize);
nodeOriginData.y = snapToGrid(nodeOriginData.y, this.gridSize);
const nodeModel = new Model(nodeOriginData, this);
const nodeModel = this.getModelAfterSnapToGrid(nodeOriginData);
this.nodes.push(nodeModel);
const nodeData = nodeModel.getData();
const eventData: Record<string, any> = { data: nodeData };
Expand All @@ -697,7 +675,35 @@ class GraphModel {
this.eventCenter.emit(eventType, eventData);
return nodeModel;
}

/**
* 将node节点位置进行grid修正
* 同时处理node内文字的偏移量
* 返回一个位置修正过的复制节点NodeModel
* @param node
*/
getModelAfterSnapToGrid(node: NodeConfig) {
const Model = this.getModel(node.type);
if (!Model) {
throw new Error(`找不到${node.type}对应的节点,请确认是否已注册此类型节点。`);
}
const { x: nodeX, y: nodeY } = node;
// 根据 grid 修正节点的 x, y
if (nodeX && nodeY) {
node.x = snapToGrid(nodeX, this.gridSize);
node.y = snapToGrid(nodeY, this.gridSize);
if (typeof node.text === 'object') {
// 原来的处理是:node.text.x -= getGridOffset(nodeX, this.gridSize);
// 由于snapToGrid()使用了Math.round()四舍五入的做法,因此无法判断需要执行
// node.text.x = node.text.x + getGridOffset()
// 还是
// node.text.x = node.text.x - getGridOffset()
// 直接改为node.x - nodeX就可以满足上面的要求
node.text.x += (node.x - nodeX);
node.text.y += (node.y - nodeY);
}
}
return new Model(node, this);
}
/**
* 克隆节点
* @param nodeId 节点Id
Expand Down