feat: 将pointer重新定义为marker
This commit is contained in:
parent
a0ebd04892
commit
da2d43581e
2
dist/sv.js
vendored
2
dist/sv.js
vendored
File diff suppressed because one or more lines are too long
@ -97,7 +97,7 @@ export const Util = {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
convertG6Data(layoutGroup: LayoutGroup): G6Data {
|
convertG6Data(layoutGroup: LayoutGroup): G6Data {
|
||||||
let nodes = [...layoutGroup.element, ...layoutGroup.pointer],
|
let nodes = [...layoutGroup.element, ...layoutGroup.marker],
|
||||||
edges = layoutGroup.link;
|
edges = layoutGroup.link;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { Util } from "../Common/util";
|
import { Util } from "../Common/util";
|
||||||
import { Engine } from "../engine";
|
import { Engine } from "../engine";
|
||||||
import { ElementOption, Layouter, LayoutGroupOptions, LinkOption, PointerOption } from "../options";
|
import { ElementOption, Layouter, LayoutGroupOptions, LinkOption, MarkerOption } from "../options";
|
||||||
import { sourceLinkData, SourceElement, LinkTarget, Sources } from "../sources";
|
import { sourceLinkData, SourceElement, LinkTarget, Sources } from "../sources";
|
||||||
import { SV } from "../StructV";
|
import { SV } from "../StructV";
|
||||||
import { Element, Link, Model, Pointer } from "./modelData";
|
import { Element, Link, Marker, Model } from "./modelData";
|
||||||
|
|
||||||
|
|
||||||
export type LayoutGroup = {
|
export type LayoutGroup = {
|
||||||
element: Element[];
|
element: Element[];
|
||||||
link: Link[];
|
link: Link[];
|
||||||
pointer: Pointer[];
|
marker: Marker[];
|
||||||
layouter: Layouter;
|
layouter: Layouter;
|
||||||
layouterName: string;
|
layouterName: string;
|
||||||
options: LayoutGroupOptions;
|
options: LayoutGroupOptions;
|
||||||
@ -32,7 +32,7 @@ export class ModelConstructor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建element,link和pointer
|
* 构建element,link和marker
|
||||||
* @param sourceList
|
* @param sourceList
|
||||||
*/
|
*/
|
||||||
public construct(sources: Sources): LayoutGroupTable {
|
public construct(sources: Sources): LayoutGroupTable {
|
||||||
@ -52,7 +52,7 @@ export class ModelConstructor {
|
|||||||
let sourceDataString: string = JSON.stringify(sourceGroup.data),
|
let sourceDataString: string = JSON.stringify(sourceGroup.data),
|
||||||
prevString: string = this.prevSourcesStringMap[name],
|
prevString: string = this.prevSourcesStringMap[name],
|
||||||
elementList: Element[] = [],
|
elementList: Element[] = [],
|
||||||
pointerList: Pointer[] = [];
|
markerList: Marker[] = [];
|
||||||
|
|
||||||
if(prevString === sourceDataString) {
|
if(prevString === sourceDataString) {
|
||||||
return;
|
return;
|
||||||
@ -61,18 +61,18 @@ export class ModelConstructor {
|
|||||||
const options: LayoutGroupOptions = optionsTable[layouterName],
|
const options: LayoutGroupOptions = optionsTable[layouterName],
|
||||||
sourceData = layouter.sourcesPreprocess(sourceGroup.data, options),
|
sourceData = layouter.sourcesPreprocess(sourceGroup.data, options),
|
||||||
elementOptions = options.element || { },
|
elementOptions = options.element || { },
|
||||||
pointerOptions = options.pointer || { };
|
markerOptions = options.marker || { };
|
||||||
|
|
||||||
elementList = this.constructElements(elementOptions, name, sourceData, layouterName);
|
elementList = this.constructElements(elementOptions, name, sourceData, layouterName);
|
||||||
pointerList = this.constructPointers(pointerOptions, elementList);
|
markerList = this.constructMarkers(markerOptions, elementList);
|
||||||
|
|
||||||
layoutGroupTable.set(name, {
|
layoutGroupTable.set(name, {
|
||||||
element: elementList,
|
element: elementList,
|
||||||
link: [],
|
link: [],
|
||||||
pointer: pointerList,
|
marker: markerList,
|
||||||
options: options,
|
options: options,
|
||||||
layouter: layouter,
|
layouter: layouter,
|
||||||
modelList: [...elementList, ...pointerList],
|
modelList: [...elementList, ...markerList],
|
||||||
layouterName,
|
layouterName,
|
||||||
isHide: false
|
isHide: false
|
||||||
});
|
});
|
||||||
@ -179,31 +179,31 @@ export class ModelConstructor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从配置和 element 集构建 pointer 集
|
* 从配置和 element 集构建 marker 集
|
||||||
* @param pointerOptions
|
* @param markerOptions
|
||||||
* @param elements
|
* @param elements
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
private constructPointers(pointerOptions: { [key: string]: PointerOption }, elements: Element[]): Pointer[] {
|
private constructMarkers(markerOptions: { [key: string]: MarkerOption }, elements: Element[]): Marker[] {
|
||||||
let pointerList: Pointer[] = [],
|
let markerList: Marker[] = [],
|
||||||
pointerNames = Object.keys(pointerOptions);
|
markerNames = Object.keys(markerOptions);
|
||||||
|
|
||||||
pointerNames.forEach(name => {
|
markerNames.forEach(name => {
|
||||||
for(let i = 0; i < elements.length; i++) {
|
for(let i = 0; i < elements.length; i++) {
|
||||||
let element = elements[i],
|
let element = elements[i],
|
||||||
pointerData = element[name];
|
markerData = element[name];
|
||||||
|
|
||||||
// 若没有指针字段的结点则跳过
|
// 若没有指针字段的结点则跳过
|
||||||
if(!pointerData) continue;
|
if(!markerData) continue;
|
||||||
|
|
||||||
let id = name + '.' + (Array.isArray(pointerData)? pointerData.join('-'): pointerData),
|
let id = name + '.' + (Array.isArray(markerData)? markerData.join('-'): markerData),
|
||||||
pointer = this.createPointer(id, name, pointerData, element, pointerOptions[name]);
|
marker = this.createMarker(id, name, markerData, element, markerOptions[name]);
|
||||||
|
|
||||||
pointerList.push(pointer);
|
markerList.push(marker);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return pointerList;
|
return markerList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -249,20 +249,20 @@ export class ModelConstructor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 外部指针工厂,创建Pointer
|
* 外部指针工厂,创建marker
|
||||||
* @param id
|
* @param id
|
||||||
* @param pointerName
|
* @param markerName
|
||||||
* @param label
|
* @param label
|
||||||
* @param target
|
* @param target
|
||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
private createPointer(id: string, pointerName: string, pointerData: string | string[], target: Element, options: PointerOption): Pointer {
|
private createMarker(id: string, markerName: string, markerData: string | string[], target: Element, options: MarkerOption): Marker {
|
||||||
let pointer = undefined;
|
let marker = undefined;
|
||||||
|
|
||||||
pointer = new Pointer(id, pointerName, pointerData, target);
|
marker = new Marker(id, markerName, markerData, target);
|
||||||
pointer.initProps(options);
|
marker.initProps(options);
|
||||||
|
|
||||||
return pointer;
|
return marker;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Util } from "../Common/util";
|
import { Util } from "../Common/util";
|
||||||
import { ElementLabelOption, ElementOption, LinkLabelOption, LinkOption, PointerOption, Style } from "../options";
|
import { ElementLabelOption, ElementOption, LinkLabelOption, LinkOption, MarkerOption, Style } from "../options";
|
||||||
import { SourceElement } from "../sources";
|
import { SourceElement } from "../sources";
|
||||||
import { BoundingRect } from "../Common/boundingRect";
|
import { BoundingRect } from "../Common/boundingRect";
|
||||||
import { SV } from './../StructV';
|
import { SV } from './../StructV';
|
||||||
@ -16,7 +16,7 @@ export interface G6NodeModel {
|
|||||||
label: string | string[];
|
label: string | string[];
|
||||||
style: Style;
|
style: Style;
|
||||||
labelCfg: ElementLabelOption;
|
labelCfg: ElementLabelOption;
|
||||||
externalPointerId: string;
|
markerId: string;
|
||||||
SVLayouter: string;
|
SVLayouter: string;
|
||||||
SVModelType: string;
|
SVModelType: string;
|
||||||
SVModelName: string;
|
SVModelName: string;
|
||||||
@ -64,7 +64,7 @@ export class Model {
|
|||||||
* 定义 G6 model 的属性
|
* 定义 G6 model 的属性
|
||||||
* @param option
|
* @param option
|
||||||
*/
|
*/
|
||||||
protected defineProps(option: ElementOption | LinkOption | PointerOption) {
|
protected defineProps(option: ElementOption | LinkOption | MarkerOption) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ export class Model {
|
|||||||
* 初始化 G6 model 的属性
|
* 初始化 G6 model 的属性
|
||||||
* @param option
|
* @param option
|
||||||
*/
|
*/
|
||||||
initProps(option: ElementOption | LinkOption | PointerOption) {
|
initProps(option: ElementOption | LinkOption | MarkerOption) {
|
||||||
this.props = this.defineProps(option);
|
this.props = this.defineProps(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ export class Element extends Model {
|
|||||||
groupName: string;
|
groupName: string;
|
||||||
layouterName: string;
|
layouterName: string;
|
||||||
freed: boolean;
|
freed: boolean;
|
||||||
pointers: { [key: string]: Pointer };
|
markers: { [key: string]: Marker };
|
||||||
|
|
||||||
constructor(id: string, type: string, group: string, layouter: string, sourceElement: SourceElement) {
|
constructor(id: string, type: string, group: string, layouter: string, sourceElement: SourceElement) {
|
||||||
super(id, type);
|
super(id, type);
|
||||||
@ -190,7 +190,7 @@ export class Element extends Model {
|
|||||||
|
|
||||||
this.sourceId = this.id.split('.')[1];
|
this.sourceId = this.id.split('.')[1];
|
||||||
this.sourceElement = sourceElement;
|
this.sourceElement = sourceElement;
|
||||||
this.pointers = { };
|
this.markers = { };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected defineProps(option: ElementOption): G6NodeModel {
|
protected defineProps(option: ElementOption): G6NodeModel {
|
||||||
@ -206,7 +206,7 @@ export class Element extends Model {
|
|||||||
label: option.label,
|
label: option.label,
|
||||||
style: Util.objectClone<Style>(option.style),
|
style: Util.objectClone<Style>(option.style),
|
||||||
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
||||||
externalPointerId: null,
|
markerId: null,
|
||||||
SVLayouter: this.layouterName,
|
SVLayouter: this.layouterName,
|
||||||
SVModelType: 'element',
|
SVModelType: 'element',
|
||||||
SVModelName: this.type
|
SVModelName: this.type
|
||||||
@ -260,7 +260,7 @@ export class Link extends Model {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
export class Pointer extends Model {
|
export class Marker extends Model {
|
||||||
target: Element;
|
target: Element;
|
||||||
label: string | string[];
|
label: string | string[];
|
||||||
anchor: number;
|
anchor: number;
|
||||||
@ -270,28 +270,38 @@ export class Pointer extends Model {
|
|||||||
this.target = target;
|
this.target = target;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
|
||||||
this.target.set('externalPointerId', id);
|
this.target.set('markerId', id);
|
||||||
this.target.pointers[type] = this;
|
this.target.markers[type] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected defineProps(option: PointerOption): G6NodeModel {
|
getLabelSizeRadius(): number {
|
||||||
|
const { width, height } = this.G6Item.getContainer().getChildren()[2].getBBox();
|
||||||
|
return width > height? width: height;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected defineProps(option: MarkerOption): G6NodeModel {
|
||||||
this.anchor = option.anchor;
|
this.anchor = option.anchor;
|
||||||
|
|
||||||
|
const type = option.type,
|
||||||
|
defaultSize: [number, number] = type === 'pointer'? [8, 30]: [12, 12];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
rotation: 0,
|
rotation: 0,
|
||||||
type: option.type || 'external-pointer',
|
type: option.type || 'marker',
|
||||||
size: option.size || [8, 50],
|
size: option.size || defaultSize,
|
||||||
anchorPoints: null,
|
anchorPoints: null,
|
||||||
label: typeof this.label === 'string'? this.label: this.label.join(', '),
|
label: typeof this.label === 'string'? this.label: this.label.join(', '),
|
||||||
style: Util.objectClone<Style>(option.style),
|
style: Util.objectClone<Style>(option.style),
|
||||||
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
labelCfg: Util.objectClone<ElementLabelOption>(option.labelOptions),
|
||||||
externalPointerId: null,
|
markerId: null,
|
||||||
SVLayouter: null,
|
SVLayouter: null,
|
||||||
SVModelType: 'pointer',
|
SVModelType: 'marker',
|
||||||
SVModelName: this.type
|
SVModelName: this.type
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
86
src/RegisteredShape/cursor.ts
Normal file
86
src/RegisteredShape/cursor.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
|
||||||
|
|
||||||
|
import * as G6 from "./../Lib/g6.js";
|
||||||
|
|
||||||
|
|
||||||
|
export default G6.registerNode('cursor', {
|
||||||
|
draw(cfg, group) {
|
||||||
|
const keyShape = group.addShape('path', {
|
||||||
|
attrs: {
|
||||||
|
path: this.getPath(cfg),
|
||||||
|
fill: cfg.style.fill,
|
||||||
|
matrix: cfg.style.matrix
|
||||||
|
},
|
||||||
|
name: 'cursor-path'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cfg.label) {
|
||||||
|
const style = (cfg.labelCfg && cfg.labelCfg.style) || {};
|
||||||
|
|
||||||
|
const bgRect = group.addShape('rect', {
|
||||||
|
attrs: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
text: cfg.label,
|
||||||
|
fill: '#fafafa',
|
||||||
|
radius: 2,
|
||||||
|
},
|
||||||
|
name: 'bgRect'
|
||||||
|
});
|
||||||
|
|
||||||
|
const text = group.addShape('text', {
|
||||||
|
attrs: {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
textAlign: 'center',
|
||||||
|
textBaseline: 'middle',
|
||||||
|
text: cfg.label,
|
||||||
|
fill: style.fill || '#999',
|
||||||
|
fontSize: style.fontSize || 16
|
||||||
|
},
|
||||||
|
name: 'cursor-text-shape'
|
||||||
|
});
|
||||||
|
|
||||||
|
const { width: textWidth, height: textHeight } = text.getBBox();
|
||||||
|
bgRect.attr({
|
||||||
|
width: textWidth + 6,
|
||||||
|
height: textHeight + 6
|
||||||
|
});
|
||||||
|
|
||||||
|
// 旋转文字
|
||||||
|
const markerEndPosition = cfg.markerEndPosition;
|
||||||
|
if(markerEndPosition) {
|
||||||
|
let textX = markerEndPosition[0],
|
||||||
|
textY = markerEndPosition[1];
|
||||||
|
|
||||||
|
text.attr({
|
||||||
|
x: textX,
|
||||||
|
y: textY
|
||||||
|
});
|
||||||
|
|
||||||
|
bgRect.attr({
|
||||||
|
x: textX - textWidth / 2 - 3,
|
||||||
|
y: textY - textHeight / 2 - 3
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keyShape;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
getPath(cfg) {
|
||||||
|
let width = cfg.size[0],
|
||||||
|
height = cfg.size[1];
|
||||||
|
|
||||||
|
const path = [
|
||||||
|
['M', 0, 0],
|
||||||
|
['L', -width / 2, -height],
|
||||||
|
['L', width / 2, -height],
|
||||||
|
['L', 0, 0],
|
||||||
|
['Z'],
|
||||||
|
];
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
});
|
@ -1,7 +1,7 @@
|
|||||||
import * as G6 from "./../Lib/g6.js";
|
import * as G6 from "../Lib/g6.js";
|
||||||
|
|
||||||
|
|
||||||
export default G6.registerNode('external-pointer', {
|
export default G6.registerNode('pointer', {
|
||||||
draw(cfg, group) {
|
draw(cfg, group) {
|
||||||
const keyShape = group.addShape('path', {
|
const keyShape = group.addShape('path', {
|
||||||
attrs: {
|
attrs: {
|
||||||
@ -30,7 +30,7 @@ export default G6.registerNode('external-pointer', {
|
|||||||
attrs: {
|
attrs: {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
textAlign: 'left',
|
textAlign: 'center',
|
||||||
textBaseline: 'middle',
|
textBaseline: 'middle',
|
||||||
text: cfg.label,
|
text: cfg.label,
|
||||||
fill: style.fill || '#999',
|
fill: style.fill || '#999',
|
||||||
@ -46,12 +46,10 @@ export default G6.registerNode('external-pointer', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 旋转文字
|
// 旋转文字
|
||||||
const pointerEndPosition = cfg.pointerEndPosition;
|
const markerEndPosition = cfg.markerEndPosition;
|
||||||
if(pointerEndPosition) {
|
if(markerEndPosition) {
|
||||||
let textX = pointerEndPosition[0] - textWidth / 2,
|
let textX = markerEndPosition[0],
|
||||||
textY = pointerEndPosition[1],
|
textY = markerEndPosition[1];
|
||||||
rectWidth = bgRect.attr('width'),
|
|
||||||
rectHeight = bgRect.attr('height');
|
|
||||||
|
|
||||||
text.attr({
|
text.attr({
|
||||||
x: textX,
|
x: textX,
|
||||||
@ -59,8 +57,8 @@ export default G6.registerNode('external-pointer', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
bgRect.attr({
|
bgRect.attr({
|
||||||
x: pointerEndPosition[0] - rectWidth / 2,
|
x: textX - textWidth / 2 - 3,
|
||||||
y: pointerEndPosition[1] - rectHeight / 2
|
y: textY - textHeight / 2 - 3
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,15 +1,15 @@
|
|||||||
import { Engine } from "./engine";
|
import { Engine } from "./engine";
|
||||||
import { Bound } from "./Common/boundingRect";
|
import { Bound } from "./Common/boundingRect";
|
||||||
import { Group } from "./Common/group";
|
import { Group } from "./Common/group";
|
||||||
import externalPointer from "./RegisteredShape/externalPointer";
|
import pointer from "./RegisteredShape/pointer";
|
||||||
import * as G6 from "./Lib/g6.js";
|
import * as G6 from "./Lib/g6.js";
|
||||||
import linkListNode from "./RegisteredShape/linkListNode";
|
import linkListNode from "./RegisteredShape/linkListNode";
|
||||||
import binaryTreeNode from "./RegisteredShape/binaryTreeNode";
|
import binaryTreeNode from "./RegisteredShape/binaryTreeNode";
|
||||||
import twoCellNode from "./RegisteredShape/twoCellNode";
|
import twoCellNode from "./RegisteredShape/twoCellNode";
|
||||||
|
import Cursor from "./RegisteredShape/cursor";
|
||||||
import { Vector } from "./Common/vector";
|
import { Vector } from "./Common/vector";
|
||||||
import indexedNode from "./RegisteredShape/indexedNode";
|
import indexedNode from "./RegisteredShape/indexedNode";
|
||||||
import { EngineOptions, Layouter } from "./options";
|
import { EngineOptions, Layouter } from "./options";
|
||||||
import { LayoutGroup } from "./Model/modelConstructor";
|
|
||||||
import { SourceElement } from "./sources";
|
import { SourceElement } from "./sources";
|
||||||
import { Element } from "./Model/modelData";
|
import { Element } from "./Model/modelData";
|
||||||
|
|
||||||
@ -49,11 +49,13 @@ SV.G6 = G6;
|
|||||||
|
|
||||||
SV.registeredLayouter = {};
|
SV.registeredLayouter = {};
|
||||||
SV.registeredShape = [
|
SV.registeredShape = [
|
||||||
externalPointer,
|
pointer,
|
||||||
linkListNode,
|
linkListNode,
|
||||||
binaryTreeNode,
|
binaryTreeNode,
|
||||||
twoCellNode,
|
twoCellNode,
|
||||||
indexedNode
|
indexedNode,
|
||||||
|
Cursor
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
SV.registerShape = G6.registerNode;
|
SV.registerShape = G6.registerNode;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Engine } from "../../engine";
|
import { Engine } from "../../engine";
|
||||||
import { Model, Pointer } from "../../Model/modelData";
|
import { Model, Marker } from "../../Model/modelData";
|
||||||
import { AnimationOptions, InteractionOptions, LayoutGroupOptions } from "../../options";
|
import { AnimationOptions, InteractionOptions, LayoutGroupOptions } from "../../options";
|
||||||
import { SV } from "../../StructV";
|
import { SV } from "../../StructV";
|
||||||
import { Animations } from "../animation";
|
import { Animations } from "../animation";
|
||||||
@ -95,15 +95,40 @@ export class Container {
|
|||||||
* @param list
|
* @param list
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
protected findReTargetPointer(list: Model[]): Pointer[] {
|
protected findReTargetMarkers(list: Model[]): Marker[] {
|
||||||
let prevPointers = this.prevModelList.filter(item => item instanceof Pointer),
|
let prevMarkers = this.prevModelList.filter(item => item instanceof Marker),
|
||||||
pointers = list.filter(item => item instanceof Pointer);
|
markers = list.filter(item => item instanceof Marker);
|
||||||
|
|
||||||
return <Pointer[]>pointers.filter(item => prevPointers.find(prevItem => {
|
return <Marker[]>markers.filter(item => prevMarkers.find(prevItem => {
|
||||||
return prevItem.id === item.id && (<Pointer>prevItem).target.id !== (<Pointer>item).target.id
|
return prevItem.id === item.id && (<Marker>prevItem).target.id !== (<Marker>item).target.id
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 找出前后 label 发生变化的 model
|
||||||
|
* @param list
|
||||||
|
*/
|
||||||
|
protected findLabelChangeModels(list: Model[]): Model[] {
|
||||||
|
let labelChangeModels: Model[] = [];
|
||||||
|
|
||||||
|
list.forEach(item => {
|
||||||
|
const prevItem = this.prevModelList.find(prevItem => prevItem.id === item.id);
|
||||||
|
|
||||||
|
if(prevItem === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prevLabel = prevItem.get('label'),
|
||||||
|
label = item.get('label');
|
||||||
|
|
||||||
|
if(prevLabel !== label) {
|
||||||
|
labelChangeModels.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return labelChangeModels;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理新增的 G6Item(主要是动画)
|
* 处理新增的 G6Item(主要是动画)
|
||||||
* @param appendData
|
* @param appendData
|
||||||
@ -184,7 +209,11 @@ export class Container {
|
|||||||
public render(modelList: Model[]) {
|
public render(modelList: Model[]) {
|
||||||
const appendModels: Model[] = this.getAppendModels(this.prevModelList, modelList),
|
const appendModels: Model[] = this.getAppendModels(this.prevModelList, modelList),
|
||||||
removeModels: Model[] = this.getRemoveModels(this.prevModelList, modelList),
|
removeModels: Model[] = this.getRemoveModels(this.prevModelList, modelList),
|
||||||
changeModels: Model[] = [...appendModels, ...this.findReTargetPointer(modelList)];
|
changeModels: Model[] = [
|
||||||
|
...appendModels,
|
||||||
|
...this.findLabelChangeModels(modelList),
|
||||||
|
...this.findReTargetMarkers(modelList)
|
||||||
|
];
|
||||||
|
|
||||||
// 渲染视图
|
// 渲染视图
|
||||||
this.renderer.render(modelList, removeModels);
|
this.renderer.render(modelList, removeModels);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { Engine } from "../../engine";
|
import { Engine } from "../../engine";
|
||||||
import { Link, Model } from "../../Model/modelData";
|
import { Link, Model } from "../../Model/modelData";
|
||||||
import { InteractionOptions, LayoutGroupOptions } from "../../options";
|
import { InteractionOptions, LayoutGroupOptions } from "../../options";
|
||||||
import { Animations } from "../animation";
|
|
||||||
import { Container } from "./container";
|
import { Container } from "./container";
|
||||||
|
|
||||||
|
|
||||||
@ -10,32 +9,9 @@ import { Container } from "./container";
|
|||||||
* 主可视化视图
|
* 主可视化视图
|
||||||
*/
|
*/
|
||||||
export class MainContainer extends Container {
|
export class MainContainer extends Container {
|
||||||
private leakContainerPosition: { x: number, y: number } = null;
|
|
||||||
private freedContainerPosition: { x: number, y: number } = null;
|
|
||||||
|
|
||||||
constructor(engine: Engine, DOMContainer: HTMLElement, g6Options: { [key: string]: any } = { }) {
|
constructor(engine: Engine, DOMContainer: HTMLElement, g6Options: { [key: string]: any } = { }) {
|
||||||
super(engine, DOMContainer, g6Options);
|
super(engine, DOMContainer, g6Options);
|
||||||
|
|
||||||
this.leakContainerPosition = this.getDOMPosition(this.engine.engineOptions.leakContainer);
|
|
||||||
this.freedContainerPosition = this.getDOMPosition(this.engine.engineOptions.freedContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param dom
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
private getDOMPosition(dom: HTMLElement): { x: number, y: number } {
|
|
||||||
if(dom === null) {
|
|
||||||
return { x: 0, y: 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
const bound = dom.getBoundingClientRect();
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: bound.x + bound.width / 2,
|
|
||||||
y: bound.y + bound.height / 2
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,8 +3,8 @@ import { Group } from '../Common/group';
|
|||||||
import { Vector } from '../Common/vector';
|
import { Vector } from '../Common/vector';
|
||||||
import { Engine } from '../engine';
|
import { Engine } from '../engine';
|
||||||
import { LayoutGroupTable } from '../Model/modelConstructor';
|
import { LayoutGroupTable } from '../Model/modelConstructor';
|
||||||
import { Element, Model, Pointer } from '../Model/modelData';
|
import { Element, Model, Marker } from '../Model/modelData';
|
||||||
import { LayoutOptions, PointerOption, ViewOptions } from '../options';
|
import { LayoutOptions, MarkerOption, ViewOptions } from '../options';
|
||||||
import { Container } from './container/container';
|
import { Container } from './container/container';
|
||||||
|
|
||||||
|
|
||||||
@ -21,10 +21,10 @@ export class Layouter {
|
|||||||
/**
|
/**
|
||||||
* 初始化布局参数
|
* 初始化布局参数
|
||||||
* @param elements
|
* @param elements
|
||||||
* @param pointers
|
* @param markers
|
||||||
*/
|
*/
|
||||||
private initLayoutValue(elements: Element[], pointers: Pointer[]) {
|
private initLayoutValue(elements: Element[], markers: Marker[]) {
|
||||||
[...elements, ...pointers].forEach(item => {
|
[...elements, ...markers].forEach(item => {
|
||||||
item.set('rotation', item.get('rotation'));
|
item.set('rotation', item.get('rotation'));
|
||||||
item.set({ x: 0, y: 0 });
|
item.set({ x: 0, y: 0 });
|
||||||
});
|
});
|
||||||
@ -32,21 +32,22 @@ export class Layouter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 布局外部指针
|
* 布局外部指针
|
||||||
* @param pointer
|
* @param marker
|
||||||
* @param pointerOptions
|
* @param markerOptions
|
||||||
*/
|
*/
|
||||||
private layoutPointer(pointers: Pointer[], pointerOptions: { [key: string]: PointerOption }) {
|
private layoutMarker(markers: Marker[], markerOptions: { [key: string]: MarkerOption }) {
|
||||||
pointers.forEach(item => {
|
markers.forEach(item => {
|
||||||
const options: PointerOption = pointerOptions[item.getType()],
|
const options: MarkerOption = markerOptions[item.getType()],
|
||||||
offset = options.offset || 8,
|
offset = options.offset ?? 8,
|
||||||
anchor = item.anchor || 0;
|
anchor = item.anchor ?? 0,
|
||||||
|
labelOffset = options.labelOffset ?? 2;
|
||||||
|
|
||||||
let target = item.target,
|
let target = item.target,
|
||||||
targetBound: BoundingRect = target.getBound(),
|
targetBound: BoundingRect = target.getBound(),
|
||||||
anchorPosition = item.target.G6Item.getAnchorPoints()[anchor],
|
anchorPosition = item.target.G6Item.getAnchorPoints()[anchor],
|
||||||
center: [number, number] = [targetBound.x + targetBound.width / 2, targetBound.y + targetBound.height / 2],
|
center: [number, number] = [targetBound.x + targetBound.width / 2, targetBound.y + targetBound.height / 2],
|
||||||
pointerPosition: [number, number],
|
markerPosition: [number, number],
|
||||||
pointerEndPosition: [number, number];
|
markerEndPosition: [number, number];
|
||||||
|
|
||||||
anchorPosition = [anchorPosition.x, anchorPosition.y];
|
anchorPosition = [anchorPosition.x, anchorPosition.y];
|
||||||
|
|
||||||
@ -60,18 +61,19 @@ export class Layouter {
|
|||||||
angle = Math.sign(anchorVector[0]) * (Math.PI / 2 - Math.atan(anchorVector[1] / anchorVector[0]));
|
angle = Math.sign(anchorVector[0]) * (Math.PI / 2 - Math.atan(anchorVector[1] / anchorVector[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
const pointerHeight = item.get('size')[1];
|
const markerHeight = item.get('size')[1],
|
||||||
|
labelRadius = item.getLabelSizeRadius() / 2;
|
||||||
|
|
||||||
anchorVector = Vector.normalize(anchorVector);
|
anchorVector = Vector.normalize(anchorVector);
|
||||||
pointerPosition = Vector.location(center, anchorVector, len);
|
markerPosition = Vector.location(center, anchorVector, len);
|
||||||
pointerEndPosition = Vector.location(center, anchorVector, pointerHeight + len);
|
markerEndPosition = Vector.location(center, anchorVector, markerHeight + len + labelRadius + labelOffset);
|
||||||
pointerEndPosition = Vector.subtract(pointerEndPosition, pointerPosition);
|
markerEndPosition = Vector.subtract(markerEndPosition, markerPosition);
|
||||||
|
|
||||||
item.set({
|
item.set({
|
||||||
x: pointerPosition[0],
|
x: markerPosition[0],
|
||||||
y: pointerPosition[1],
|
y: markerPosition[1],
|
||||||
rotation: angle,
|
rotation: angle,
|
||||||
pointerEndPosition
|
markerEndPosition
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -110,13 +112,13 @@ export class Layouter {
|
|||||||
modelGroup.add(item);
|
modelGroup.add(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.initLayoutValue(group.element, group.pointer); // 初始化布局参数
|
this.initLayoutValue(group.element, group.marker); // 初始化布局参数
|
||||||
group.layouter.layout(group.element, options); // 布局节点
|
group.layouter.layout(group.element, options); // 布局节点
|
||||||
modelGroupList.push(modelGroup);
|
modelGroupList.push(modelGroup);
|
||||||
});
|
});
|
||||||
|
|
||||||
layoutGroupTable.forEach(group => {
|
layoutGroupTable.forEach(group => {
|
||||||
this.layoutPointer(group.pointer, group.options.pointer); // 布局外部指针
|
this.layoutMarker(group.marker, group.options.marker); // 布局外部指针
|
||||||
});
|
});
|
||||||
|
|
||||||
return modelGroupList;
|
return modelGroupList;
|
||||||
|
@ -81,7 +81,7 @@ export class ViewManager {
|
|||||||
freedList.forEach(fItem => {
|
freedList.forEach(fItem => {
|
||||||
removeModels.push(...freedGroup.element.splice(freedGroup.element.findIndex(item => item.id === fItem.id), 1));
|
removeModels.push(...freedGroup.element.splice(freedGroup.element.findIndex(item => item.id === fItem.id), 1));
|
||||||
removeModels.push(...freedGroup.link.splice(freedGroup.link.findIndex(item => item.element.id === fItem.id || item.target.id === fItem.id)));
|
removeModels.push(...freedGroup.link.splice(freedGroup.link.findIndex(item => item.element.id === fItem.id || item.target.id === fItem.id)));
|
||||||
removeModels.push(...freedGroup.pointer.splice(freedGroup.pointer.findIndex(item => item.target.id === fItem.id)));
|
removeModels.push(...freedGroup.marker.splice(freedGroup.marker.findIndex(item => item.target.id === fItem.id)));
|
||||||
});
|
});
|
||||||
|
|
||||||
removeModels.map(model => {
|
removeModels.map(model => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Element, Link, Pointer } from "./Model/modelData";
|
import { Element, Link, Marker } from "./Model/modelData";
|
||||||
import { Sources } from "./sources";
|
import { Sources } from "./sources";
|
||||||
import { LayoutGroupTable, ModelConstructor } from "./Model/modelConstructor";
|
import { LayoutGroupTable, ModelConstructor } from "./Model/modelConstructor";
|
||||||
import { AnimationOptions, EngineOptions, InteractionOptions, LayoutGroupOptions, ViewOptions } from "./options";
|
import { AnimationOptions, EngineOptions, InteractionOptions, LayoutGroupOptions, ViewOptions } from "./options";
|
||||||
@ -139,22 +139,22 @@ export class Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有 pointer
|
* 获取所有 marker
|
||||||
* @param group
|
* @param group
|
||||||
*/
|
*/
|
||||||
public getPointers(group?: string): Pointer[] {
|
public getMarkers(group?: string): Marker[] {
|
||||||
const layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
|
const layoutGroupTable = this.modelConstructor.getLayoutGroupTable();
|
||||||
|
|
||||||
if(group && layoutGroupTable.has('group')) {
|
if(group && layoutGroupTable.has('group')) {
|
||||||
return layoutGroupTable.get('group').pointer;
|
return layoutGroupTable.get('group').marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pointers: Pointer[] = [];
|
const markers: Marker[] = [];
|
||||||
layoutGroupTable.forEach(item => {
|
layoutGroupTable.forEach(item => {
|
||||||
pointers.push(...item.pointer);
|
markers.push(...item.marker);
|
||||||
})
|
})
|
||||||
|
|
||||||
return pointers;
|
return markers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,12 +54,14 @@ export interface LinkOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface PointerOption extends ElementOption {
|
export interface MarkerOption extends ElementOption {
|
||||||
anchor: number;
|
anchor: number;
|
||||||
offset: number;
|
offset: number;
|
||||||
|
labelOffset: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export interface LayoutOptions {
|
export interface LayoutOptions {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
};
|
};
|
||||||
@ -74,7 +76,7 @@ export interface BehaviorOptions {
|
|||||||
export interface LayoutGroupOptions {
|
export interface LayoutGroupOptions {
|
||||||
element: { [key: string]: ElementOption };
|
element: { [key: string]: ElementOption };
|
||||||
link?: { [key: string]: LinkOption }
|
link?: { [key: string]: LinkOption }
|
||||||
pointer?: { [key: string]: PointerOption };
|
marker?: { [key: string]: MarkerOption }
|
||||||
layout?: LayoutOptions;
|
layout?: LayoutOptions;
|
||||||
behavior?: BehaviorOptions;
|
behavior?: BehaviorOptions;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user