fix:修复少量bug
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import { Engine } from "../engine";
|
||||
import { Util } from "./../Common/util";
|
||||
|
||||
export class Behavior {
|
||||
private engine: Engine;
|
||||
private graphInstance;
|
||||
|
||||
constructor(engine: Engine, graphInstance) {
|
||||
this.engine = engine;
|
||||
this.graphInstance = graphInstance;
|
||||
|
||||
const interactionOptions = this.engine.interactionOptions;
|
||||
|
||||
if(interactionOptions.dragNode) {
|
||||
this.initDragNode();
|
||||
}
|
||||
|
||||
if(interactionOptions.selectNode) {
|
||||
this.initSelectNode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化节点拖拽事件
|
||||
*/
|
||||
private initDragNode() {
|
||||
let pointer = null,
|
||||
pointerX = null,
|
||||
pointerY = null,
|
||||
dragStartX = null,
|
||||
dragStartY = null;
|
||||
|
||||
this.graphInstance.on('node:dragstart', ev => {
|
||||
pointer = this.graphInstance.findById(ev.item.getModel().externalPointerId);
|
||||
|
||||
if(pointer) {
|
||||
pointerX = pointer.getModel().x,
|
||||
pointerY = pointer.getModel().y;
|
||||
dragStartX = ev.canvasX;
|
||||
dragStartY = ev.canvasY;
|
||||
}
|
||||
});
|
||||
|
||||
this.graphInstance.on('node:dragend', ev => {
|
||||
pointer = null;
|
||||
pointerX = null,
|
||||
pointerY = null,
|
||||
dragStartX = null,
|
||||
dragStartY = null;
|
||||
});
|
||||
|
||||
this.graphInstance.on('node:drag', ev => {
|
||||
if(!pointer) {
|
||||
return;
|
||||
}
|
||||
|
||||
let dx = ev.canvasX - dragStartX,
|
||||
dy = ev.canvasY - dragStartY,
|
||||
zoom = this.graphInstance.getZoom();
|
||||
|
||||
pointer.updatePosition({
|
||||
x: pointerX + dx / zoom,
|
||||
y: pointerY + dy / zoom
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化节/边选中
|
||||
*/
|
||||
private initSelectNode() {
|
||||
let defaultHighlightColor = '#f08a5d',
|
||||
curSelectItem = null,
|
||||
curSelectItemStyle = null;
|
||||
|
||||
const selectCallback = ev => {
|
||||
const item = ev.item,
|
||||
type = item.getType(),
|
||||
highlightColor = item.getModel().style.selectedColor;
|
||||
|
||||
if(curSelectItem && curSelectItem !== item) {
|
||||
curSelectItem.update({
|
||||
style: curSelectItemStyle
|
||||
});
|
||||
}
|
||||
|
||||
curSelectItem = item;
|
||||
curSelectItemStyle = Util.objectClone(curSelectItem.getModel().style);
|
||||
curSelectItem.update({
|
||||
style: {
|
||||
...curSelectItemStyle,
|
||||
[type === 'node'? 'fill': 'stroke']: highlightColor || defaultHighlightColor
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.graphInstance.on('node:click', selectCallback);
|
||||
this.graphInstance.on('edge:click', selectCallback);
|
||||
this.graphInstance.on('click', ev => {
|
||||
if(curSelectItem === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
curSelectItem.update({
|
||||
style: curSelectItemStyle
|
||||
});
|
||||
|
||||
curSelectItem = null;
|
||||
curSelectItemStyle = null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定 G6 事件
|
||||
* @param eventName
|
||||
* @param callback
|
||||
*/
|
||||
public on(eventName: string, callback: Function) {
|
||||
if(this.graphInstance) {
|
||||
this.graphInstance.on(eventName, callback)
|
||||
}
|
||||
}
|
||||
};
|
||||
+34
-18
@@ -1,7 +1,7 @@
|
||||
import { Util } from "../Common/util";
|
||||
import { Engine } from "../engine";
|
||||
import { ConstructedData } from "../Model/modelConstructor";
|
||||
import { Element, Pointer } from "../Model/modelData";
|
||||
import { Element, Model, Pointer } from "../Model/modelData";
|
||||
import { LayoutOptions, PointerOption } from "../options";
|
||||
import { Bound, BoundingRect } from "./boundingRect";
|
||||
|
||||
@@ -10,31 +10,31 @@ import { Bound, BoundingRect } from "./boundingRect";
|
||||
|
||||
export class Layouter {
|
||||
private engine: Engine;
|
||||
private containerWidth: number;
|
||||
private containerHeight: number;
|
||||
|
||||
constructor(engine: Engine, containerWidth: number, containerHeight: number) {
|
||||
constructor(engine: Engine) {
|
||||
this.engine = engine;
|
||||
this.containerWidth = containerWidth;
|
||||
this.containerHeight = containerHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将视图调整至画布中心
|
||||
* @param nodes
|
||||
*/
|
||||
private fiTCenter(nodes: (Element | Pointer)[]) {
|
||||
const viewBound: BoundingRect = nodes.map(item => item.getBound()).reduce((prev, cur) => Bound.union(prev, cur));
|
||||
private fitCenter(models: Model[]) {
|
||||
const viewBound: BoundingRect = models.map(item => item.getBound()).reduce((prev, cur) => Bound.union(prev, cur));
|
||||
|
||||
let centerX = this.containerWidth / 2, centerY = this.containerHeight / 2,
|
||||
let width = this.engine.getGraphInstance().getWidth(),
|
||||
height = this.engine.getGraphInstance().getHeight(),
|
||||
centerX = width / 2, centerY = height / 2,
|
||||
boundCenterX = viewBound.x + viewBound.width / 2,
|
||||
boundCenterY = viewBound.y + viewBound.height / 2,
|
||||
dx = centerX - boundCenterX,
|
||||
dy = centerY - boundCenterY;
|
||||
|
||||
nodes.forEach(item => {
|
||||
item.set('x', item.get('x') + dx);
|
||||
item.set('y', item.get('y') + dy)
|
||||
models.forEach(item => {
|
||||
item.set({
|
||||
x: item.get('x') + dx,
|
||||
y: item.get('y') + dy
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -50,8 +50,10 @@ export class Layouter {
|
||||
|
||||
pointerList.forEach(item => {
|
||||
let targetBound: BoundingRect = item.target.getBound();
|
||||
item.set('x', targetBound.x + targetBound.width / 2);
|
||||
item.set('y', targetBound.y - offset);
|
||||
item.set({
|
||||
x: targetBound.x + targetBound.width / 2,
|
||||
y: targetBound.y - offset
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -59,11 +61,21 @@ export class Layouter {
|
||||
/**
|
||||
* 主布局函数
|
||||
* @param constructedData
|
||||
* @param modelList
|
||||
* @param layoutFn
|
||||
*/
|
||||
public layout(constructedData: ConstructedData, layoutFn: (element: { [ket: string]: Element[] }, layoutOptions: LayoutOptions) => void) {
|
||||
const options: LayoutOptions = this.engine.layoutOptions,
|
||||
nodes: (Element | Pointer)[] = [...Util.converterList(constructedData.element), ...Util.converterList(constructedData.pointer)]
|
||||
public layout(constructedData: ConstructedData, modelList: Model[], layoutFn: (element: { [ket: string]: Element[] }, layoutOptions: LayoutOptions) => void) {
|
||||
const options: LayoutOptions = this.engine.layoutOptions;
|
||||
|
||||
// 首先初始化所有节点的坐标为0,且设定旋转
|
||||
modelList.forEach(item => {
|
||||
item.G6Item = item.shadowG6Item;
|
||||
|
||||
if(item.type === 'element' || item.type === 'pointer') {
|
||||
item.set('rotation', item.get('rotation'));
|
||||
item.set({ x: 0, y: 0 });
|
||||
}
|
||||
});
|
||||
|
||||
// 布局节点
|
||||
layoutFn.call(this.engine, constructedData.element, options);
|
||||
@@ -72,6 +84,10 @@ export class Layouter {
|
||||
this.layoutPointer(constructedData.pointer);
|
||||
|
||||
// 将视图调整到画布中心
|
||||
options.fitCenter && this.fiTCenter(nodes);
|
||||
options.fitCenter && this.fitCenter(modelList);
|
||||
|
||||
modelList.forEach(item => {
|
||||
item.G6Item = item.renderG6Item;
|
||||
});
|
||||
}
|
||||
}
|
||||
+55
-48
@@ -4,6 +4,7 @@ import { ConstructedData } from '../Model/modelConstructor';
|
||||
import { Util } from '../Common/util';
|
||||
import { Animations } from './animation';
|
||||
import { SV } from '../StructV';
|
||||
import { Model } from './../Model/modelData';
|
||||
|
||||
|
||||
|
||||
@@ -21,12 +22,14 @@ export class Renderer {
|
||||
private isFirstRender: boolean;
|
||||
private prevRenderData: G6Data;
|
||||
private graphInstance;
|
||||
private helpGraphInstance;
|
||||
private shadowGraphInstance;
|
||||
private modelList: Model[];
|
||||
|
||||
constructor(engine: Engine, DOMContainer: HTMLElement, containerWidth: number, containerHeight: number) {
|
||||
constructor(engine: Engine, DOMContainer: HTMLElement) {
|
||||
this.engine = engine;
|
||||
this.DOMContainer = DOMContainer;
|
||||
this.isFirstRender = true;
|
||||
this.modelList = [];
|
||||
this.prevRenderData = {
|
||||
nodes: [],
|
||||
edges: []
|
||||
@@ -34,12 +37,33 @@ export class Renderer {
|
||||
|
||||
const enable: boolean = this.engine.animationOptions.enable === undefined? true: this.engine.animationOptions.enable,
|
||||
duration: number = this.engine.animationOptions.duration,
|
||||
timingFunction: string = this.engine.animationOptions.timingFunction;
|
||||
timingFunction: string = this.engine.animationOptions.timingFunction,
|
||||
interactionOptions = this.engine.interactionOptions;
|
||||
|
||||
const modeMap = {
|
||||
drag: 'drag-canvas',
|
||||
zoom: 'zoom-canvas',
|
||||
dragNode: {
|
||||
type: 'drag-node',
|
||||
shouldBegin: n => {
|
||||
// 不允许拖拽外部指针
|
||||
if (n.item && n.item.getModel().modelType === 'pointer') return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
defaultModes = [];
|
||||
|
||||
Object.keys(interactionOptions).forEach(item => {
|
||||
if(interactionOptions[item] === true && modeMap[item] !== undefined) {
|
||||
defaultModes.push(modeMap[item]);
|
||||
}
|
||||
});
|
||||
|
||||
this.graphInstance = new SV.G6.Graph({
|
||||
container: DOMContainer,
|
||||
width: containerWidth,
|
||||
height: containerHeight,
|
||||
width: DOMContainer.offsetWidth,
|
||||
height: DOMContainer.offsetHeight,
|
||||
animate: enable,
|
||||
animateCfg: {
|
||||
duration: duration,
|
||||
@@ -47,40 +71,15 @@ export class Renderer {
|
||||
},
|
||||
fitView: this.engine.layoutOptions.fitView,
|
||||
modes: {
|
||||
default: ['drag-canvas', 'zoom-canvas', 'drag-node']
|
||||
default: defaultModes
|
||||
}
|
||||
});
|
||||
|
||||
this.helpGraphInstance = new SV.G6.Graph({
|
||||
this.shadowGraphInstance = new SV.G6.Graph({
|
||||
container: DOMContainer.cloneNode()
|
||||
});
|
||||
|
||||
this.animations = new Animations(duration, timingFunction);
|
||||
this.initBehavior();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化交互
|
||||
*/
|
||||
private initBehavior() {
|
||||
this.graphInstance.on('node:drag', (() => {
|
||||
let pointer = null;
|
||||
|
||||
return ev => {
|
||||
if(pointer === null) {
|
||||
pointer = this.graphInstance.findById(ev.item.getModel().externalPointerId);
|
||||
}
|
||||
|
||||
if(pointer) {
|
||||
pointer.updatePosition({
|
||||
x: ev.canvasX,
|
||||
y: ev.canvasY
|
||||
});
|
||||
}
|
||||
|
||||
console.log(ev);
|
||||
}
|
||||
})());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,21 +146,21 @@ export class Renderer {
|
||||
let elementList: Element[] = Util.converterList(constructedData.element),
|
||||
linkList: Link[] = Util.converterList(constructedData.link),
|
||||
pointerList: Pointer[] = Util.converterList(constructedData.pointer),
|
||||
nodeList = [...elementList.map(item => item.props), ...pointerList.map(item => item.props)],
|
||||
edgeList = linkList.map(item => item.props),
|
||||
list = [...elementList, ...linkList, ...pointerList];
|
||||
nodeList = [...elementList.map(item => item.cloneProps()), ...pointerList.map(item => item.cloneProps())],
|
||||
edgeList = linkList.map(item => item.cloneProps());
|
||||
|
||||
this.modelList = [...elementList, ...linkList, ...pointerList];
|
||||
|
||||
const data: G6Data = {
|
||||
nodes: <G6NodeModel[]>nodeList,
|
||||
edges: <G6EdgeModel[]>edgeList
|
||||
};
|
||||
|
||||
this.helpGraphInstance.clear();
|
||||
this.helpGraphInstance.read(data);
|
||||
this.shadowGraphInstance.clear();
|
||||
this.shadowGraphInstance.read(data);
|
||||
|
||||
list.forEach(item => {
|
||||
item.G6Item = this.helpGraphInstance.findById(item.id);
|
||||
item.afterInitG6Item();
|
||||
this.modelList.forEach(item => {
|
||||
item.shadowG6Item = this.shadowGraphInstance.findById(item.id);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -194,20 +193,28 @@ export class Renderer {
|
||||
|
||||
this.handleAppendItems(appendData);
|
||||
this.handleRemoveItems(removeData);
|
||||
|
||||
|
||||
if(this.engine.layoutOptions.fitView) {
|
||||
this.graphInstance.fitView();
|
||||
}
|
||||
|
||||
this.modelList.forEach(item => {
|
||||
item.renderG6Item = this.graphInstance.findById(item.id);
|
||||
item.G6Item = item.renderG6Item;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定 G6 事件
|
||||
* @param eventName
|
||||
* @param callback
|
||||
* 获取 model 队列
|
||||
*/
|
||||
public on(eventName: string, callback: Function) {
|
||||
if(this.graphInstance) {
|
||||
this.graphInstance.on(eventName, callback)
|
||||
}
|
||||
getModelList(): Model[] {
|
||||
return this.modelList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 G6 实例
|
||||
*/
|
||||
public getGraphInstance() {
|
||||
return this.graphInstance;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user