UNPKG

@gravity-ui/graph

Version:

Modern graph editor component

106 lines (105 loc) 3.17 kB
import { cache } from "../../../../lib/utils"; class Path2DGroup { constructor() { this.items = new Set(); this.path = cache(() => { const path = new Path2D(); path.moveTo(0, 0); return Array.from(this.items).reduce((path, item) => { const subPath = item.getPath(); if (subPath) { path.addPath(subPath); } return path; }, path); }); } applyStyles(ctx) { const val = Array.from(this.items)[0]; return val.style(ctx); } add(item) { this.items.add(item); this.path.reset(); } delete(item) { this.items.delete(item); this.path.reset(); } render(ctx) { if (this.items.size) { ctx.save(); const result = this.applyStyles(ctx); if (result) { switch (result.type) { case "fill": { ctx.fill(this.path.get(), result.fillRule); break; } case "stroke": { ctx.stroke(this.path.get()); break; } case "both": { ctx.fill(this.path.get(), result.fillRule); ctx.stroke(this.path.get()); } } } ctx.restore(); for (const item of this.items) { item.afterRender?.(ctx); } } } } export class BatchPath2DRenderer { constructor(onChange) { this.onChange = onChange; this.indexes = new Map(); this.itemParams = new Map(); this.orderedPaths = cache(() => { return Array.from(this.indexes.entries()) .sort(([indexA], [indexB]) => indexB - indexA) .reduce((acc, [_, items]) => { acc.push(...Array.from(items.values())); return acc; }, []); }); } getGroup(zIndex, group) { if (!this.indexes.has(zIndex)) { this.indexes.set(zIndex, new Map()); } const index = this.indexes.get(zIndex); if (!index.has(group)) { index.set(group, new Path2DGroup()); } return index.get(group); } add(item, params) { if (this.itemParams.has(item)) { this.update(item, params); } const bucket = this.getGroup(params.zIndex, params.group); bucket.add(item); this.itemParams.set(item, params); this.orderedPaths.reset(); this.onChange?.(); } update(item, params) { this.delete(item); this.add(item, params); } delete(item) { if (!this.itemParams.has(item)) { return; } const params = this.itemParams.get(item); const bucket = this.getGroup(params.zIndex, params.group); bucket.delete(item); this.itemParams.delete(item); this.orderedPaths.reset(); this.onChange?.(); } }