fix: update lod-controller disableLod

This commit is contained in:
Yanyan-Wang 2023-10-30 18:39:50 +08:00
parent 40976cf3ee
commit 56cb08602d
8 changed files with 115 additions and 93 deletions

View File

@ -174,6 +174,10 @@ export default class Node extends Item {
isNaN(position.z as number)
)
return;
const viewportPosition = graph.getViewportByCanvas(position);
labelGroup.style.x = viewportPosition.x;
labelGroup.style.y = viewportPosition.y;
labelGroup.style.z = viewportPosition.z || 0;
if (animate && !disableAnimate && animates?.update) {
const groupAnimates = animates.update.filter(
({ shapeId, fields = [] }) =>
@ -199,10 +203,6 @@ export default class Node extends Item {
group.style.x = position.x;
group.style.y = position.y;
group.style.z = position.z;
const viewportPosition = graph.getViewportByCanvas({ x, y, z });
labelGroup.style.x = viewportPosition.x;
labelGroup.style.y = viewportPosition.y;
labelGroup.style.z = viewportPosition.z || 0;
onfinish(displayModel.id, !animate);
}
/**
@ -214,7 +214,14 @@ export default class Node extends Item {
}
const { graph, group, labelGroup, displayModel, shapeMap, renderExt } =
this;
const [x, y, z] = group.getPosition();
let [x, y, z] = group.getPosition();
if (group.getAnimations().length) {
const { x: dataX, y: dataY, z: dataZ } = displayModel.data;
x = dataX as number;
y = dataY as number;
z = dataZ as number;
}
const zoom = graph.getZoom();
const { x: vx, y: vy, z: vz } = graph.getViewportByCanvas({ x, y, z });
if (labelGroup.style.x !== vx) {

View File

@ -1239,7 +1239,7 @@ export class ItemController {
return {
id,
data: {
...item.displayModel,
...item.displayModel.data,
...item.renderExt.mergedStyles,
lodLevels: item.lodLevels,
},

View File

@ -108,19 +108,19 @@ export class LayoutController {
animationEffectTiming = {
duration: 1000,
} as Partial<IAnimationEffectTiming>,
preset,
presetLayout,
execute,
...rest
} = options;
// preset layout
// presetLayout layout
const nodesWithPosition = await this.presetLayout(
layoutData,
nodeSize,
width,
height,
center,
preset,
presetLayout,
params,
layoutGraphCore,
);
@ -160,16 +160,16 @@ export class LayoutController {
);
}
} else {
const { preset } = options;
const { presetLayout } = options;
// preset layout
// presetLayout layout
const nodesWithPosition = await this.presetLayout(
layoutData,
nodeSize,
width,
height,
center,
preset,
presetLayout,
params,
layoutGraphCore,
);
@ -335,24 +335,24 @@ export class LayoutController {
width,
height,
center,
preset,
presetLayout,
params,
layoutGraphCore,
) => {
// preset has higher priority than the positions in data
if (preset?.type) {
// presetLayout has higher priority than the positions in data
if (presetLayout?.type) {
const presetPositions = await this.layoutOnce(
layoutData,
nodeSize,
width,
height,
center,
preset,
presetLayout,
params,
layoutGraphCore,
);
presetPositions.nodes.forEach((node) => {
layoutGraphCore.updateNodeData(node.id, {
layoutGraphCore.mergeNodeData(node.id, {
x: node.data.x,
y: node.data.y,
});

View File

@ -10,6 +10,7 @@ type Listener = (event: IG6GraphEvent) => void;
const REQUIRED_PLUGINS = [
{
key: 'lod-controller',
type: 'lod-controller',
pluginClass: LodController,
},
@ -90,6 +91,11 @@ export class PluginController {
)
) {
plugins.push(required.type);
if (!this.graph.specification.plugins) {
this.graph.specification.plugins = [];
}
this.graph.specification.plugins.push(required);
}
});
@ -170,7 +176,7 @@ export class PluginController {
}
if (action === 'update') {
pluginCfgs.forEach(this.updatePlugin);
pluginCfgs.forEach(this.updatePlugin.bind(this));
return;
}
}

View File

@ -2020,7 +2020,10 @@ export class Graph<B extends BehaviorRegistry, T extends ThemeRegistry>
/**
* Layout the graph (with current configurations if cfg is not assigned).
*/
public async layout(options?: LayoutOptions, disableAnimate = false) {
public async layout(
options?: Partial<LayoutOptions>,
disableAnimate = false,
) {
this.emit('beforelayout');
const { graphCore } = this.dataController;
const formattedOptions = {
@ -2285,12 +2288,15 @@ export class Graph<B extends BehaviorRegistry, T extends ThemeRegistry>
| PluginBase,
) {
const { plugins } = this.specification;
const { key } = plugin;
const { key, type } = plugin as {
key: string;
type: string;
[cfg: string]: unknown;
};
if (!key) {
console.warn(
'Update plugin failed, the key for the plugin to be updated should be assign.',
`The key for the plugin is not found. G6 will update the first plugin with type ${type}`,
);
return;
}
if (!plugins) {
console.warn(
@ -2299,12 +2305,21 @@ export class Graph<B extends BehaviorRegistry, T extends ThemeRegistry>
return;
}
const oldPlugin = plugins?.find((p) => {
if (typeof p === 'string') return p === key;
return p.key === key;
if (typeof p === 'string') return p === key || p === type;
return (
p.key === key ||
(
p as {
key: string;
type: string;
[cfg: string]: unknown;
}
).type === type
);
});
if (!oldPlugin) {
console.warn(
'Update plugin failed, the key for the plugin to be updated should be assign.',
`Update plugin failed, the plugin with key ${key} or type ${type} is not found.`,
);
return;
}

View File

@ -68,6 +68,7 @@ export class LodController extends Base {
}
public getEvents() {
if (this.graph.rendererType === 'webgl-3d') return;
return {
afterrender: this.onAfterRender,
afterlayout: this.onAfterLayout,
@ -81,47 +82,10 @@ export class LodController extends Base {
}
protected onAfterRender = () => {
this.clearCache();
// show the shapes with lod when diableLod is true
const { graph, options } = this;
const graphZoom = graph.getZoom();
if (options.disableLod) {
const models = graph.getAllNodesData().concat(graph.getAllEdgesData());
models.forEach((model) => {
const displayModel = this.getDisplayModel(model.id);
const { lodLevels, ...others } = displayModel.data;
const lodLevelsEmpty = isEmptyObj(lodLevels);
const currentZoomLevel = lodLevelsEmpty
? 0
: getZoomLevel(lodLevels as any, graphZoom);
const shapeIdsToShow = [];
Object.keys(others).forEach((shapeId) => {
if (shapeId === 'keyShape') return;
const val = others[shapeId] as any;
if (
typeof val !== 'object' ||
!Object.keys(val).length ||
isArray(val)
) {
return;
}
if (val.visible === false) return;
if (
lodLevelsEmpty ||
val.lod === 'auto' ||
val.lod > currentZoomLevel
) {
shapeIdsToShow.push(shapeId);
}
});
if (shapeIdsToShow.length) {
graph.showItem(model.id, {
shapeIds: shapeIdsToShow,
disableAnimate: options.disableAnimate,
});
}
});
}
this.clearCache();
this.debounce = 80;
if (options.debounce === undefined || options.debounce === 'auto') {
@ -156,7 +120,7 @@ export class LodController extends Base {
private updateVisible = (zoomRatio = 1) => {
const { graph, cacheViewModels, options } = this;
const { cellSize, numberPerCell, disableAnimate } = options;
const { cellSize, numberPerCell, disableAnimate, disableLod } = options;
const graphZoom = graph.getZoom();
const { inView } = cacheViewModels || this.groupItemsByView(1);
@ -173,7 +137,7 @@ export class LodController extends Base {
const lodInvisibleIds = new Map<ID, string[]>();
inView.forEach((model) => {
const displayModel = this.getDisplayModel(model.id);
const { lodLevels, ...others } = displayModel.data;
const { lodLevels, x, y, z, ...others } = displayModel.data;
const lodLevelsEmpty = isEmptyObj(lodLevels);
const currentZoomLevel = lodLevelsEmpty
? 0
@ -220,8 +184,8 @@ export class LodController extends Base {
const { center } = bounds;
const param = graphZoom / cellSize;
// rowIdx = (center[i] * graphZoom + offset[i]) - offset[i] / cellSize = center[i] * param
const rowIdx = Math.floor(center[0] * param);
const colIdx = Math.floor(center[1] * param);
const rowIdx = Math.floor((center[0] || x) * param);
const colIdx = Math.floor((center[1] || y) * param);
const cellIdx = `${rowIdx}-${colIdx}`;
const cellNodeIds = cells.get(cellIdx) || [];
cellNodeIds.push(model.id);
@ -253,13 +217,14 @@ export class LodController extends Base {
const { lodVisibleShapeIds, autoVisibleShapeIds, invisibleShapeIds } =
candidateShapeMap.get(id);
if (invisibleShapeIds.length) {
if (!disableLod && invisibleShapeIds.length) {
graph.hideItem(id, { shapeIds: invisibleShapeIds, disableAnimate });
}
const item = graph.itemController.itemMap.get(id);
if (
item.labelGroup.children.length &&
(rest > 0 || (zoomRatio >= 1 && this.shownIds.has(id)))
disableLod ||
(item.labelGroup.children.length &&
(rest > 0 || (zoomRatio >= 1 && this.shownIds.has(id))))
) {
const shapeIdsToShow = lodVisibleShapeIds.concat(autoVisibleShapeIds);
if (shapeIdsToShow.length) {
@ -269,7 +234,7 @@ export class LodController extends Base {
});
}
if (this.labelPositionDirty.has(id)) {
item.updateLabelPosition();
item.updateLabelPosition(disableLod);
this.labelPositionDirty.delete(id);
}
shownIds.set(id, 1);
@ -279,7 +244,7 @@ export class LodController extends Base {
lodVisibleShapeIds.includes('labelShape') &&
this.labelPositionDirty.has(id)
) {
item.updateLabelPosition();
item.updateLabelPosition(disableLod);
this.labelPositionDirty.delete(id);
}
lodVisibleShapeIds.length &&
@ -287,17 +252,20 @@ export class LodController extends Base {
shapeIds: lodVisibleShapeIds,
disableAnimate,
});
autoVisibleShapeIds.length &&
if (!disableLod && autoVisibleShapeIds.length) {
graph.hideItem(id, {
shapeIds: autoVisibleShapeIds,
disableAnimate,
});
}
}
});
});
lodInvisibleIds.forEach((shapeIds, id) => {
shapeIds.length && graph.hideItem(id, { shapeIds, disableAnimate });
});
if (!disableLod) {
lodInvisibleIds.forEach((shapeIds, id) => {
shapeIds.length && graph.hideItem(id, { shapeIds, disableAnimate });
});
}
this.shownIds = shownIds;
};
@ -322,9 +290,10 @@ export class LodController extends Base {
if (
!item ||
!item.labelGroup.children.length ||
item.labelGroup.style.visibility === 'hidden' ||
!item.shapeMap.labelShape ||
item.shapeMap.labelShape.style.visibility === 'hidden'
(!options.disableLod &&
(item.labelGroup.style.visibility === 'hidden' ||
item.shapeMap.labelShape.style.visibility === 'hidden'))
) {
return;
}
@ -333,7 +302,7 @@ export class LodController extends Base {
if (!labelShape) return;
const updatePosition = () => {
// adjust labels'positions for visible items
item.updateLabelPosition();
item.updateLabelPosition(options.disableLod);
this.labelPositionDirty.delete(model.id);
};
const { visible, lod } = labelShape;
@ -445,6 +414,11 @@ export class LodController extends Base {
inView = [];
outView = [];
models.forEach((model) => {
if (!this.modelCanvasIdxMap.get(model.id)) {
outView.push(model);
if (!previousOutView.has(model.id)) newlyOutView.push(model);
return;
}
const { rowIdx, colIdx } = this.modelCanvasIdxMap.get(model.id);
if (atBoundary(rowIdx, colIdx)) {
const renderBounds = this.getRenderBBox(model.id);
@ -468,6 +442,10 @@ export class LodController extends Base {
// zoom-out
const outViewNew = [];
outView.forEach((model) => {
if (!this.modelCanvasIdxMap.get(model.id)) {
outViewNew.push(model);
return;
}
const { rowIdx, colIdx } = this.modelCanvasIdxMap.get(model.id);
if (atBoundary(rowIdx, colIdx)) {
const renderBounds = this.getRenderBBox(model.id);
@ -490,6 +468,11 @@ export class LodController extends Base {
// zoom-in
const inViewNew = [];
inView.forEach((model) => {
if (!this.modelCanvasIdxMap.get(model.id)) {
outView.push(model);
newlyOutView.push(model);
return;
}
const { rowIdx, colIdx } = this.modelCanvasIdxMap.get(model.id);
if (atBoundary(rowIdx, colIdx)) {
const renderBounds = this.getRenderBBox(model.id);
@ -524,6 +507,7 @@ export class LodController extends Base {
const cellIdx = `${rowIdx}-${colIdx}`;
const cell = canvasCells.get(cellIdx) || [];
cell.push(model.id);
canvasCells.set(cellIdx, cell);
idxMap.set(model.id, { rowIdx, colIdx });
});
graph.getAllEdgesData().forEach((model) => {
@ -535,6 +519,7 @@ export class LodController extends Base {
const cellIdx = `${centerRowIdx}-${centerColIdx}`;
const cell = canvasCells.get(cellIdx) || [];
cell.push(model.id);
canvasCells.set(cellIdx, cell);
idxMap.set(model.id, { rowIdx: centerRowIdx, colIdx: centerColIdx });
});
this.modelCanvasIdxMap = idxMap;

View File

@ -59,7 +59,7 @@ export type ImmediatelyInvokedLayoutOptions = {
*/
execute: (graph: GraphCore, options?: any) => Promise<LayoutMapping>;
} & Animatable & {
preset?: PureLayoutOptions;
presetLayout?: Partial<PureLayoutOptions>;
};
type CustomLayout = {
@ -70,7 +70,7 @@ type CustomLayout = {
export type StandardLayoutOptions = PureLayoutOptions &
Animatable &
Workerized & {
preset?: PureLayoutOptions;
presetLayout?: Partial<PureLayoutOptions>;
};
export type LayoutOptions =

View File

@ -1731,7 +1731,7 @@ export default (
plugins: [
// {
// type: 'lod-controller',
// // disableLod: true,
// disableLod: true,
// // disableAnimate: false,
// },
],
@ -1821,8 +1821,10 @@ export default (
// },
},
labelBackgroundShape: {
opacity: 0.1,
fill: '#00f',
opacity: 1,
fill: '#fff',
// opacity: 0.1,
// fill: '#00f',
// lod: model.id === 'node1' ? 0 : 'auto',
},
iconShape: {
@ -1832,9 +1834,9 @@ export default (
};
},
layout: {
preset: {
type: 'concentric',
},
// presetLayout: {
// type: 'concentric',
// },
type: 'force',
linkDistance: 100,
edgeStrength: 1000,
@ -1845,6 +1847,8 @@ export default (
},
});
let disable = false;
graph.on('canvas:click', (e) => {
// const { x, y } = graph.getNodeData('Mlle.Gillenormand')?.data || {};
// graph.updateData('node', {
@ -1867,10 +1871,15 @@ export default (
// graph.hideItem('Marius');
// graph.showItem('Marius');
console.log(
'click',
graph.itemController.itemMap.get('Gervais')?.labelGroup,
);
disable = !disable;
graph.updatePlugin({
key: 'lod-controller',
type: 'lod-controller',
disableLod: disable,
});
// console.log(graph.itemController.itemMap.get('Gillenormand'));
// console.log(graph.itemController.itemMap.get('Child2'));
});
let allData = { ...data };
graph.on('node:click', (e) => {
@ -1897,7 +1906,7 @@ export default (
};
graph.changeData(allData, 'mergeReplace', false);
graph.layout({
preset: {},
presetLayout: {},
});
});
return graph;