import { __extends } from "tslib"; import { AbstractGroup } from '@antv/g-base'; import * as Shape from './shape'; import { applyAttrsToContext, drawChildren, refreshElement } from './util/draw'; import { each, max, min } from '@antv/util'; import { intersectRect } from './util/util'; var Group = /** @class */ (function (_super) { __extends(Group, _super); function Group() { return _super !== null && _super.apply(this, arguments) || this; } /** * 一些方法调用会引起画布变化 * @param {ChangeType} changeType 改变的类型 */ Group.prototype.onCanvasChange = function (changeType) { refreshElement(this, changeType); }; Group.prototype.getShapeBase = function () { return Shape; }; Group.prototype.getGroupBase = function () { return Group; }; // 同 shape 中的方法重复了 Group.prototype._applyClip = function (context, clip) { if (clip) { context.save(); // 将 clip 的属性挂载到 context 上 applyAttrsToContext(context, clip); // 绘制 clip 路径 clip.createPath(context); context.restore(); // 裁剪 context.clip(); clip._afterDraw(); } }; // 这个方法以前直接使用的 getCanvasBBox,由于 group 上没有缓存,所以每次重新计算,导致性能开销比较大 // 大概能够节省全局渲染 15-20% 的性能,如果不在这里加缓存优化后 10W 个节点无法达到 5-6 ms,大概能够 30-40ms Group.prototype.cacheCanvasBBox = function () { var children = this.cfg.children; var xArr = []; var yArr = []; each(children, function (child) { var bbox = child.cfg.cacheCanvasBBox; // isInview 的判定是一旦图形或者分组渲染就要计算是否在视图内, // 这个判定 10W 个图形下差不多能够节省 5-6 ms 的开销 if (bbox && child.cfg.isInView) { xArr.push(bbox.minX, bbox.maxX); yArr.push(bbox.minY, bbox.maxY); } }); var bbox = null; if (xArr.length) { var minX = min(xArr); var maxX = max(xArr); var minY = min(yArr); var maxY = max(yArr); bbox = { minX: minX, minY: minY, x: minX, y: minY, maxX: maxX, maxY: maxY, width: maxX - minX, height: maxY - minY, }; var canvas = this.cfg.canvas; if (canvas) { var viewRange = canvas.getViewRange(); // 如果这个地方判定 isInView == false 设置 bbox 为 false 的话,拾取的性能会更高 // 但是目前 10W 图形的拾取在 2-5ms 内,这个优化意义不大,可以后期观察再看 this.set('isInView', intersectRect(bbox, viewRange)); } } else { this.set('isInView', false); } this.set('cacheCanvasBBox', bbox); }; Group.prototype.draw = function (context, region) { var children = this.cfg.children; var allowDraw = region ? this.cfg.refresh : true; // 局部刷新需要判定 // 这个地方需要判定,在 G6 的场景每个 group 都有 transform 的场景下性能会开销非常大 // 通过 refresh 的判定,可以不刷新没有发生过变化的分组,不在视窗内的分组等等 // 如果想进一步提升局部渲染性能,可以进一步优化 refresh 的判定,依然有潜力 if (children.length && allowDraw) { context.save(); // group 上的矩阵和属性也会应用到上下文上 // 先将 attrs 应用到上下文中,再设置 clip。因为 clip 应该被当前元素的 matrix 所影响 applyAttrsToContext(context, this); this._applyClip(context, this.getClip()); drawChildren(context, children, region); context.restore(); this.cacheCanvasBBox(); } // 这里的成本比较大,如果不绘制则不再 // this.set('cacheCanvasBBox', this.getCanvasBBox()); this.cfg.refresh = null; // 绘制后,消除更新标记 this.set('hasChanged', false); }; // 绘制时被跳过,一般发生在分组隐藏时 Group.prototype.skipDraw = function () { this.set('cacheCanvasBBox', null); this.set('hasChanged', false); }; return Group; }(AbstractGroup)); export default Group; //# sourceMappingURL=group.js.map