完成 d3 数据项目 + 渲染的架构调整
This commit is contained in:
parent
2a1dc56148
commit
425c513635
@ -34,4 +34,13 @@ onMounted(async () => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
transition: var(--animation-5s);
|
transition: var(--animation-5s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grab {
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grabbing {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
@ -5,11 +5,30 @@ export class CellRender {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {d3.Selection} selection
|
* @param {d3.Selection} selection
|
||||||
* @param {BasicD3DataItem} cells
|
|
||||||
*/
|
*/
|
||||||
constructor(selection, cells) {
|
constructor(selection, cells) {
|
||||||
this.parentSelection = selection;
|
this.parentSelection = selection;
|
||||||
this.data = cells;
|
|
||||||
|
/**
|
||||||
|
* @type {BasicD3DataItem[]}
|
||||||
|
*/
|
||||||
|
this.data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 将 elknode 关于 器件 的数据添加为 d3 数据项目
|
||||||
|
* @param {ElkNode} node
|
||||||
|
* @param {HTMLElement} element
|
||||||
|
*/
|
||||||
|
addAsD3DataItem(node, element) {
|
||||||
|
this.data.push({
|
||||||
|
element,
|
||||||
|
x: node.x,
|
||||||
|
y: node.y,
|
||||||
|
width: node.width,
|
||||||
|
height: node.height,
|
||||||
|
fill: 'var(--main-dark-color)'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -32,12 +51,23 @@ export class CellRender {
|
|||||||
cellSelections = cellSelections
|
cellSelections = cellSelections
|
||||||
.transition()
|
.transition()
|
||||||
.duration(1000)
|
.duration(1000)
|
||||||
.attr('stroke-opacity', 1);
|
.attr('stroke-opacity', 1)
|
||||||
}
|
.attr('class', 'grab')
|
||||||
cellSelections.on('end', function (data) {
|
.on('end', function (data) {
|
||||||
|
console.log('enter end');
|
||||||
|
|
||||||
const cellSelection = d3.select(this);
|
const cellSelection = d3.select(this);
|
||||||
registerDragEvent(cellSelection, data);
|
registerDragEvent(cellSelection, data);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
cellSelections = cellSelections
|
||||||
|
.attr('class', 'grab')
|
||||||
|
.each(function (data) {
|
||||||
|
console.log('enter end'); // 在这里执行你需要的逻辑
|
||||||
|
const cellSelection = d3.select(this);
|
||||||
|
registerDragEvent(cellSelection, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.selections = cellSelections;
|
this.selections = cellSelections;
|
||||||
return cellSelections;
|
return cellSelections;
|
||||||
@ -54,10 +84,22 @@ export class CellRender {
|
|||||||
export function registerDragEvent(selection, data) {
|
export function registerDragEvent(selection, data) {
|
||||||
// 创建拖拽行为
|
// 创建拖拽行为
|
||||||
const drag = d3.drag();
|
const drag = d3.drag();
|
||||||
drag.on("drag", event => dragged(event, selection, data));
|
|
||||||
|
drag.on('start', event => dragStart(event, selection, data));
|
||||||
|
drag.on('drag', event => dragged(event, selection, data));
|
||||||
|
drag.on('end', event => dragEnd(event, selection, data))
|
||||||
|
|
||||||
selection.call(drag);
|
selection.call(drag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {d3.D3DragEvent} event
|
||||||
|
* @param {d3.Selection} selection
|
||||||
|
*/
|
||||||
|
function dragStart(event, selection, data) {
|
||||||
|
selection.attr('class', 'grabbing');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -67,5 +109,17 @@ export function registerDragEvent(selection, data) {
|
|||||||
function dragged(event, selection, data) {
|
function dragged(event, selection, data) {
|
||||||
data.x = event.x;
|
data.x = event.x;
|
||||||
data.y = event.y;
|
data.y = event.y;
|
||||||
selection.attr('x', event.x).attr('y', event.y);
|
|
||||||
|
selection
|
||||||
|
.attr('x', event.x)
|
||||||
|
.attr('y', event.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {d3.D3DragEvent} event
|
||||||
|
* @param {d3.Selection} selection
|
||||||
|
*/
|
||||||
|
function dragEnd(event, selection, data) {
|
||||||
|
selection.attr('class', 'grab');
|
||||||
}
|
}
|
@ -3,13 +3,32 @@ import { globalSetting } from '../global';
|
|||||||
|
|
||||||
export class ConnectionRender {
|
export class ConnectionRender {
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @param {d3.Selection} selection
|
* @param {d3.Selection} selection
|
||||||
* @param {BasicD3DataItem} connections
|
|
||||||
*/
|
*/
|
||||||
constructor(selection, connections) {
|
constructor(selection) {
|
||||||
this.parentSelection = selection;
|
this.parentSelection = selection;
|
||||||
this.data = connections;
|
|
||||||
|
/**
|
||||||
|
* @type {BasicD3DataItem[]}
|
||||||
|
*/
|
||||||
|
this.data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 将 elknode 关于 module connection 的数据添加为 d3 数据项目
|
||||||
|
* @param {ElkPort} cellPort 连接点对象
|
||||||
|
* @param {ElkNode} node 当前的实体(port/例化模块/器件)
|
||||||
|
*/
|
||||||
|
addAsD3DataItem(cellPort, node) {
|
||||||
|
this.data.push({
|
||||||
|
x: cellPort.x + node.x,
|
||||||
|
y: cellPort.y + node.y + 0.5, // 0.5 是为了线宽
|
||||||
|
width: cellPort.width,
|
||||||
|
height: cellPort.height,
|
||||||
|
fill: 'var(--main-color)',
|
||||||
|
text: '',
|
||||||
|
r: 3.5
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -32,39 +51,9 @@ export class ConnectionRender {
|
|||||||
|
|
||||||
connectionSelections
|
connectionSelections
|
||||||
.attr('fill', d => d.fill)
|
.attr('fill', d => d.fill)
|
||||||
.attr('r', d => d.r)
|
.attr('r', d => d.r);
|
||||||
.on('end', function (data) {
|
|
||||||
const connectionSelection = d3.select(this);
|
|
||||||
registerDragEvent(connectionSelection, data);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.selections = connectionSelections;
|
this.selections = connectionSelections;
|
||||||
return connectionSelections;
|
return connectionSelections;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 注册关于 器件 的拖动事件
|
|
||||||
*
|
|
||||||
* 需要提取最小拓扑子图,然后重新调整各个区域的尺寸
|
|
||||||
* @param {d3.Selection} selection
|
|
||||||
* @param {any} data
|
|
||||||
*/
|
|
||||||
export function registerDragEvent(selection, data) {
|
|
||||||
// 创建拖拽行为
|
|
||||||
const drag = d3.drag();
|
|
||||||
drag.on("drag", event => dragged(event, selection, data));
|
|
||||||
selection.call(drag);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {d3.D3DragEvent} event
|
|
||||||
* @param {d3.Selection} selection
|
|
||||||
*/
|
|
||||||
function dragged(event, selection, data) {
|
|
||||||
data.x = event.x;
|
|
||||||
data.y = event.y;
|
|
||||||
selection.attr('x', event.x).attr('y', event.y);
|
|
||||||
}
|
|
@ -4,11 +4,11 @@ import ELK from 'elkjs';
|
|||||||
|
|
||||||
import { Module } from './layout';
|
import { Module } from './layout';
|
||||||
import { globalLookup, globalSetting } from '../global';
|
import { globalLookup, globalSetting } from '../global';
|
||||||
import { registerCellDragEvent } from './drag';
|
|
||||||
import { PortRender } from './port';
|
import { PortRender } from './port';
|
||||||
import { InstantiationRender } from './instantiation';
|
import { InstantiationRender } from './instantiation';
|
||||||
import { CellRender } from './cell';
|
import { CellRender } from './cell';
|
||||||
import { ConnectionRender } from './connection';
|
import { ConnectionRender } from './connection';
|
||||||
|
import { WireRender } from './wire';
|
||||||
|
|
||||||
export class NetlistRender {
|
export class NetlistRender {
|
||||||
/**
|
/**
|
||||||
@ -129,112 +129,77 @@ export class NetlistRender {
|
|||||||
.attr('width', this.renderWidth)
|
.attr('width', this.renderWidth)
|
||||||
.attr('height', this.renderHeight);
|
.attr('height', this.renderHeight);
|
||||||
|
|
||||||
await this.renderLine(svg, computedLayout, ratio);
|
// 将分组作为一个后续操作的 parent selection
|
||||||
await this.renderEntity(svg, computedLayout, ratio);
|
const g = svg.append('g');
|
||||||
|
|
||||||
|
await this.renderLine(g, computedLayout, ratio);
|
||||||
|
await this.renderEntity(g, computedLayout, ratio);
|
||||||
|
|
||||||
|
// svg 挂载为全局注册的 selection
|
||||||
this.selection = svg;
|
this.selection = svg;
|
||||||
|
|
||||||
|
// 注册平移和缩放
|
||||||
|
// this.registerRenderTransform(g);
|
||||||
|
|
||||||
return svg;
|
return svg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 绘制实体
|
* @description 绘制实体
|
||||||
* @param {d3.Selection} svg
|
* @param {d3.Selection} parentSelection
|
||||||
* @param {ElkNode} computedLayout
|
* @param {ElkNode} computedLayout
|
||||||
* @param {number} ratio
|
* @param {number} ratio
|
||||||
*/
|
*/
|
||||||
async renderEntity(svg, computedLayout, ratio) {
|
async renderEntity(parentSelection, computedLayout, ratio) {
|
||||||
// node 可能是如下的几类
|
// node 可能是如下的几类
|
||||||
// - module 的 port
|
// - module 的 port
|
||||||
// - 器件(基础器件 & 例化模块)
|
// - 器件(基础器件 & 例化模块)
|
||||||
// - 器件的 port
|
// - 器件的 port
|
||||||
|
|
||||||
// 生成用于绘制的 d3 数据结构
|
|
||||||
// 默认需要渲染成矩形的(缺失样式的器件、例化模块等等)
|
|
||||||
const ports = [];
|
|
||||||
const instantiations = [];
|
|
||||||
|
|
||||||
const cells = [];
|
|
||||||
const connections = [];
|
|
||||||
|
|
||||||
const skinManager = globalLookup.skinManager;
|
const skinManager = globalLookup.skinManager;
|
||||||
|
|
||||||
// TODO: 把下面的逻辑融合进入 render 中
|
// 创建各个主要实体的 render
|
||||||
|
this.cellRender = new CellRender(parentSelection);
|
||||||
|
this.portRender = new PortRender(parentSelection);
|
||||||
|
this.instantiationRender = new InstantiationRender(parentSelection);
|
||||||
|
this.connectionRender = new ConnectionRender(parentSelection);
|
||||||
|
|
||||||
for (const node of computedLayout.children) {
|
for (const node of computedLayout.children) {
|
||||||
const skin = skinManager.querySkin(node.renderName);
|
const skin = skinManager.querySkin(node.renderName);
|
||||||
if (skin) {
|
if (skin) {
|
||||||
// 具有 skin 的器件
|
// 具有 skin 的器件
|
||||||
cells.push({
|
this.cellRender.addAsD3DataItem(node, skin.meta.svgDoc.documentElement);
|
||||||
element: skin.meta.svgDoc.documentElement,
|
|
||||||
x: node.x,
|
|
||||||
y: node.y,
|
|
||||||
width: node.width,
|
|
||||||
height: node.height,
|
|
||||||
fill: 'var(--main-dark-color)',
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
if (node.renderType === 'port') {
|
if (node.renderType === 'port') {
|
||||||
ports.push({
|
this.portRender.addAsD3DataItem(node);
|
||||||
x: node.x,
|
|
||||||
y: node.y,
|
|
||||||
width: node.width,
|
|
||||||
height: node.height,
|
|
||||||
fill: 'var(--main-dark-color)',
|
|
||||||
text: node.renderName,
|
|
||||||
rx: 3,
|
|
||||||
ry: 3
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
// 没有 skin 的器件或者端口
|
// 没有 skin 的器件或者端口
|
||||||
instantiations.push({
|
this.instantiationRender.addAsD3DataItem(node);
|
||||||
x: node.x,
|
|
||||||
y: node.y,
|
|
||||||
width: node.width,
|
|
||||||
height: node.height,
|
|
||||||
fill: 'var(--main-dark-color)',
|
|
||||||
text: node.renderName,
|
|
||||||
rx: 3,
|
|
||||||
ry: 3
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果存在 port,绘制 port
|
// 如果存在 port,绘制 port
|
||||||
for (const cellPort of node.ports || []) {
|
for (const cellPort of node.ports || []) {
|
||||||
connections.push({
|
this.connectionRender.addAsD3DataItem(cellPort, node);
|
||||||
x: cellPort.x + node.x,
|
|
||||||
y: cellPort.y + node.y + 0.5, // 0.5 是为了线宽
|
|
||||||
width: cellPort.width,
|
|
||||||
height: cellPort.height,
|
|
||||||
fill: 'var(--main-color)',
|
|
||||||
text: '',
|
|
||||||
r: 3.5
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.portRender = new PortRender(svg, ports);
|
|
||||||
this.portRender.render();
|
this.portRender.render();
|
||||||
|
// TODO: 实现它
|
||||||
// this.instantiationRender = new InstantiationRender(svg, instantiations);
|
|
||||||
// this.instantiationRender.render();
|
// this.instantiationRender.render();
|
||||||
|
|
||||||
this.cellRender = new CellRender(svg, cells);
|
|
||||||
this.cellRender.render();
|
this.cellRender.render();
|
||||||
|
|
||||||
this.connectionRender = new ConnectionRender(svg, connections);
|
|
||||||
this.connectionRender.render();
|
this.connectionRender.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 绘制连线
|
* @description 绘制连线
|
||||||
* @param {d3.Selection} svg
|
* @param {d3.Selection} parentSelection
|
||||||
* @param {ElkNode} computedLayout
|
* @param {ElkNode} computedLayout
|
||||||
* @param {number} ratio
|
* @param {number} ratio
|
||||||
*/
|
*/
|
||||||
async renderLine(svg, computedLayout, ratio) {
|
async renderLine(parentSelection, computedLayout, ratio) {
|
||||||
const lines = [];
|
|
||||||
|
this.wireRender = new WireRender(parentSelection);
|
||||||
|
|
||||||
for (const edge of computedLayout.edges) {
|
for (const edge of computedLayout.edges) {
|
||||||
for (const section of edge.sections || []) {
|
for (const section of edge.sections || []) {
|
||||||
const points = [];
|
const points = [];
|
||||||
@ -243,47 +208,60 @@ export class NetlistRender {
|
|||||||
points.push(point);
|
points.push(point);
|
||||||
}
|
}
|
||||||
points.push(section.endPoint);
|
points.push(section.endPoint);
|
||||||
|
this.wireRender.addAsD3DataItems(points);
|
||||||
for (let i = 0; i < points.length - 1; ++ i) {
|
|
||||||
lines.push({
|
|
||||||
x1: points[i].x,
|
|
||||||
y1: points[i].y,
|
|
||||||
x2: points[i + 1].x,
|
|
||||||
y2: points[i + 1].y,
|
|
||||||
strokeWidth: 2,
|
|
||||||
color: 'var(--foreground)'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let lineSelection = svg.selectAll('line')
|
this.wireRender.render();
|
||||||
.data(lines)
|
}
|
||||||
.enter()
|
|
||||||
.append('line')
|
|
||||||
.attr('x1', data => data.x1)
|
|
||||||
.attr('y1', data => data.y1)
|
|
||||||
.attr('x2', data => data.x2)
|
|
||||||
.attr('y2', data => data.y2)
|
|
||||||
.attr('stroke', data => data.color);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 注册平移和缩放
|
||||||
|
* @param {d3.Selection} parentSelection
|
||||||
|
*/
|
||||||
|
registerRenderTransform(parentSelection) {
|
||||||
|
// 创建缩放行为
|
||||||
|
const zoom = d3.zoom()
|
||||||
|
// 设置缩放范围(最小缩放比例 0.5,最大缩放比例 5)
|
||||||
|
.scaleExtent([0.5, 5])
|
||||||
|
.on("zoom", zoomed);
|
||||||
|
|
||||||
|
// 将缩放行为应用到 SVG
|
||||||
|
this.selection.call(zoom);
|
||||||
|
|
||||||
|
// 缩放事件处理函数
|
||||||
|
function zoomed(event) {
|
||||||
|
const { transform, sourceEvent } = event;
|
||||||
|
|
||||||
|
if (sourceEvent && sourceEvent.type === "wheel") {
|
||||||
if (globalSetting.renderAnimation) {
|
if (globalSetting.renderAnimation) {
|
||||||
lineSelection = lineSelection.transition().duration(1000);
|
parentSelection
|
||||||
|
.transition()
|
||||||
|
.duration(350)
|
||||||
|
.attr('transform', transform);
|
||||||
|
} else {
|
||||||
|
parentSelection.attr('transform', transform);
|
||||||
|
}
|
||||||
|
} else if (sourceEvent && sourceEvent.type === "mousemove") {
|
||||||
|
if (globalSetting.renderAnimation) {
|
||||||
|
parentSelection.attr('transform', transform);
|
||||||
|
} else {
|
||||||
|
parentSelection.attr('transform', transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lineSelection.attr('stroke-width', data => data.strokeWidth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 从 globalLookup 中更新 svg 的方位
|
* @description 从 globalLookup 中更新 svg 的方位
|
||||||
*/
|
*/
|
||||||
updateLocationFromGlobal() {
|
updateLocationFromGlobal() {
|
||||||
const svg = globalLookup.netlistRender.selection;
|
// const svg = globalLookup.netlistRender.selection;
|
||||||
if (!svg) {
|
// if (!svg) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
svg.attr('transform', `translate(${globalLookup.svgTranslateX}, ${globalLookup.svgTranslateY}) scale(${globalLookup.svgScale})`);
|
// svg.attr('transform', `translate(${globalLookup.svgTranslateX}, ${globalLookup.svgTranslateY}) scale(${globalLookup.svgScale})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,5 +7,27 @@ export class InstantiationRender {
|
|||||||
*/
|
*/
|
||||||
constructor(selection) {
|
constructor(selection) {
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {BasicD3DataItem[]}
|
||||||
|
*/
|
||||||
|
this.data = []
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 将 elknode 关于 例化模块 的数据添加为 d3 数据项目
|
||||||
|
* @param {ElkNode} node
|
||||||
|
*/
|
||||||
|
addAsD3DataItem(node) {
|
||||||
|
this.data.push({
|
||||||
|
x: node.x,
|
||||||
|
y: node.y,
|
||||||
|
width: node.width,
|
||||||
|
height: node.height,
|
||||||
|
fill: 'var(--main-dark-color)',
|
||||||
|
text: node.renderName,
|
||||||
|
rx: 3,
|
||||||
|
ry: 3
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,11 +6,30 @@ export class PortRender {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {d3.Selection} selection
|
* @param {d3.Selection} selection
|
||||||
* @param {BasicD3DataItem} ports
|
|
||||||
*/
|
*/
|
||||||
constructor(selection, ports) {
|
constructor(selection) {
|
||||||
this.parentSelection = selection;
|
this.parentSelection = selection;
|
||||||
this.data = ports;
|
/**
|
||||||
|
* @type {BasicD3DataItem[]}
|
||||||
|
*/
|
||||||
|
this.data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 将 elknode 关于 port 的数据添加为 d3 数据项目
|
||||||
|
* @param {ElkNode} node
|
||||||
|
*/
|
||||||
|
addAsD3DataItem(node) {
|
||||||
|
this.data.push({
|
||||||
|
x: node.x,
|
||||||
|
y: node.y,
|
||||||
|
width: node.width,
|
||||||
|
height: node.height,
|
||||||
|
fill: 'var(--main-dark-color)',
|
||||||
|
text: node.renderName,
|
||||||
|
rx: 3,
|
||||||
|
ry: 3
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -26,6 +45,7 @@ export class PortRender {
|
|||||||
.attr('height', data => data.height)
|
.attr('height', data => data.height)
|
||||||
.attr('fill', d => d.fill);
|
.attr('fill', d => d.fill);
|
||||||
|
|
||||||
|
|
||||||
portSelections.append("text")
|
portSelections.append("text")
|
||||||
.attr("x", d => d.width / 2) // 文本的 x 坐标(居中)
|
.attr("x", d => d.width / 2) // 文本的 x 坐标(居中)
|
||||||
.attr("y", d => d.height / 2) // 文本的 y 坐标(居中)
|
.attr("y", d => d.height / 2) // 文本的 y 坐标(居中)
|
||||||
@ -38,16 +58,28 @@ export class PortRender {
|
|||||||
portSelections = portSelections
|
portSelections = portSelections
|
||||||
.transition()
|
.transition()
|
||||||
.duration(1000)
|
.duration(1000)
|
||||||
}
|
.attr('stroke', 'var(--main-color)')
|
||||||
|
.attr('stroke-width', 2)
|
||||||
|
.attr('rx', d => d.rx)
|
||||||
|
.attr('ry', d => d.ry)
|
||||||
|
.attr('class', 'grab')
|
||||||
|
.on('end', function (data) {
|
||||||
|
const portSelection = d3.select(this);
|
||||||
|
registerDragEvent(portSelection, data);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
portSelections
|
portSelections
|
||||||
.attr('stroke', 'var(--main-color)')
|
.attr('stroke', 'var(--main-color)')
|
||||||
.attr('stroke-width', 2)
|
.attr('stroke-width', 2)
|
||||||
.attr('rx', d => d.rx)
|
.attr('rx', d => d.rx)
|
||||||
.attr('ry', d => d.ry)
|
.attr('ry', d => d.ry)
|
||||||
.on('end', function (data) {
|
.attr('class', 'grab')
|
||||||
|
.each(function (data) {
|
||||||
const portSelection = d3.select(this);
|
const portSelection = d3.select(this);
|
||||||
registerDragEvent(portSelection, data);
|
registerDragEvent(portSelection, data);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
this.selections = portSelections;
|
this.selections = portSelections;
|
||||||
return portSelections;
|
return portSelections;
|
||||||
@ -64,10 +96,22 @@ export class PortRender {
|
|||||||
export function registerDragEvent(selection, data) {
|
export function registerDragEvent(selection, data) {
|
||||||
// 创建拖拽行为
|
// 创建拖拽行为
|
||||||
const drag = d3.drag();
|
const drag = d3.drag();
|
||||||
|
|
||||||
|
drag.on("start", event => dragStart(event, selection, data));
|
||||||
drag.on("drag", event => dragged(event, selection, data));
|
drag.on("drag", event => dragged(event, selection, data));
|
||||||
|
drag.on("end", event => dragEnd(event, selection, data));
|
||||||
|
|
||||||
selection.call(drag);
|
selection.call(drag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {d3.D3DragEvent} event
|
||||||
|
* @param {d3.Selection} selection
|
||||||
|
*/
|
||||||
|
function dragStart(event, selection, data) {
|
||||||
|
selection.attr('class', 'grabbing');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -79,3 +123,12 @@ function dragged(event, selection, data) {
|
|||||||
data.y = event.y;
|
data.y = event.y;
|
||||||
selection.attr('x', event.x).attr('y', event.y);
|
selection.attr('x', event.x).attr('y', event.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {d3.D3DragEvent} event
|
||||||
|
* @param {d3.Selection} selection
|
||||||
|
*/
|
||||||
|
function dragEnd(event, selection, data) {
|
||||||
|
selection.attr('class', 'grab');
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
|
import { globalSetting } from '../global';
|
||||||
|
|
||||||
export class WireRender {
|
export class WireRender {
|
||||||
/**
|
/**
|
||||||
@ -7,5 +8,50 @@ export class WireRender {
|
|||||||
*/
|
*/
|
||||||
constructor(selection) {
|
constructor(selection) {
|
||||||
this.selection = selection;
|
this.selection = selection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {BasicD3DataItem[]}
|
||||||
|
*/
|
||||||
|
this.data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 将 elknode 关于 wire 的数据添加为 d3 数据项目
|
||||||
|
* @param {ElkPoint[]} points
|
||||||
|
*/
|
||||||
|
addAsD3DataItems(points) {
|
||||||
|
for (let i = 0; i < points.length - 1; ++ i) {
|
||||||
|
this.data.push({
|
||||||
|
x1: points[i].x,
|
||||||
|
y1: points[i].y,
|
||||||
|
x2: points[i + 1].x,
|
||||||
|
y2: points[i + 1].y,
|
||||||
|
strokeWidth: 2,
|
||||||
|
color: 'var(--foreground)'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const data = this.data;
|
||||||
|
|
||||||
|
let lineSelections = this.selection.selectAll('line')
|
||||||
|
.data(data)
|
||||||
|
.enter()
|
||||||
|
.append('line')
|
||||||
|
.attr('x1', data => data.x1)
|
||||||
|
.attr('y1', data => data.y1)
|
||||||
|
.attr('x2', data => data.x2)
|
||||||
|
.attr('y2', data => data.y2)
|
||||||
|
.attr('stroke', data => data.color);
|
||||||
|
|
||||||
|
if (globalSetting.renderAnimation) {
|
||||||
|
lineSelections = lineSelections
|
||||||
|
.transition()
|
||||||
|
.duration(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
lineSelections.attr('stroke-width', data => data.strokeWidth);
|
||||||
|
// line 就不注册拖拽事件了
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user