From 0b639b813e3e1ae37fce33d790d1f9c47f96c604 Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 7 Nov 2024 11:09:38 +0800 Subject: [PATCH] refactor: support optimize massive attrs clone (#1820) * refactor: support optimize massive attrs clone * chore: commit changeset --- .changeset/strong-worms-dream.md | 7 +++ __tests__/demos/perf/index.ts | 1 + __tests__/demos/perf/massive-attrs.ts | 59 +++++++++++++++++++ packages/g-components/src/Arrow.ts | 13 ++++ packages/g-components/src/Sector.ts | 11 ++++ packages/g-components/src/Sector2.ts | 11 ++++ packages/g-lite/src/css/StyleValueRegistry.ts | 21 ++++++- packages/g-lite/src/display-objects/Circle.ts | 10 ++++ .../src/display-objects/CustomElement.ts | 54 ----------------- .../src/display-objects/DisplayObject.ts | 45 ++++++++++++++ .../g-lite/src/display-objects/Ellipse.ts | 11 ++++ packages/g-lite/src/display-objects/Group.ts | 6 ++ packages/g-lite/src/display-objects/HTML.ts | 10 ++++ packages/g-lite/src/display-objects/Image.ts | 14 +++++ packages/g-lite/src/display-objects/Line.ts | 16 +++++ packages/g-lite/src/display-objects/Path.ts | 12 ++++ .../g-lite/src/display-objects/Polygon.ts | 13 ++++ .../g-lite/src/display-objects/Polyline.ts | 11 ++++ packages/g-lite/src/display-objects/Rect.ts | 12 ++++ packages/g-lite/src/display-objects/Text.ts | 38 +++++++++++- packages/g-lite/src/global-runtime.ts | 7 +++ packages/g-plugin-device-renderer/src/Mesh.ts | 9 +++ .../src/lights/Fog.ts | 8 +++ .../src/lights/Light.ts | 5 ++ 24 files changed, 345 insertions(+), 59 deletions(-) create mode 100644 .changeset/strong-worms-dream.md create mode 100644 __tests__/demos/perf/massive-attrs.ts diff --git a/.changeset/strong-worms-dream.md b/.changeset/strong-worms-dream.md new file mode 100644 index 000000000..a74fc0a35 --- /dev/null +++ b/.changeset/strong-worms-dream.md @@ -0,0 +1,7 @@ +--- +'@antv/g-plugin-device-renderer': patch +'@antv/g-components': patch +'@antv/g-lite': patch +--- + +optimize massive attrs clone diff --git a/__tests__/demos/perf/index.ts b/__tests__/demos/perf/index.ts index efcf468e5..4dd1f67f2 100644 --- a/__tests__/demos/perf/index.ts +++ b/__tests__/demos/perf/index.ts @@ -2,3 +2,4 @@ export { circles } from './circles'; export { rects } from './rect'; export { image } from './image'; export { attrUpdate } from './attr-update'; +export { massiveAttrs } from './massive-attrs'; diff --git a/__tests__/demos/perf/massive-attrs.ts b/__tests__/demos/perf/massive-attrs.ts new file mode 100644 index 000000000..39226c6f9 --- /dev/null +++ b/__tests__/demos/perf/massive-attrs.ts @@ -0,0 +1,59 @@ +import { Rect, runtime } from '@antv/g'; + +export async function massiveAttrs(context) { + const { canvas, gui } = context; + + runtime.enableMassiveParsedStyleAssignOptimization = true; + + await canvas.ready; + + console.time('massiveAttrs'); + + for (let i = 0; i < 10000; i++) { + const rect = new Rect({ + style: { + x: Math.random() * 640, + y: Math.random() * 640, + width: 10 + Math.random() * 40, + height: 10 + Math.random() * 40, + fill: '#1890FF', + stroke: '#F04864', + lineWidth: 4, + + // extra attrs + 'attr-a': 1, + 'attr-b': 2, + 'attr-c': 3, + 'attr-d': 4, + 'attr-e': 5, + 'attr-f': 6, + 'attr-g': 7, + 'attr-h': 8, + 'attr-i': 9, + 'attr-j': 10, + 'attr-k': 11, + 'attr-l': 12, + 'attr-m': 13, + 'attr-n': 14, + 'attr-o': 15, + 'attr-p': 16, + 'attr-q': 17, + 'attr-r': 18, + 'attr-s': 19, + 'attr-t': 20, + 'attr-u': 21, + 'attr-v': 22, + 'attr-w': 23, + 'attr-x': 24, + 'attr-y': 25, + 'attr-z': 26, + }, + }); + + canvas.appendChild(rect); + } + + canvas.addEventListener('rerender', () => { + console.timeEnd('massiveAttrs'); + }); +} diff --git a/packages/g-components/src/Arrow.ts b/packages/g-components/src/Arrow.ts index 3ba4a93d2..a4806101b 100644 --- a/packages/g-components/src/Arrow.ts +++ b/packages/g-components/src/Arrow.ts @@ -44,6 +44,19 @@ export interface ArrowStyleProps extends BaseStyleProps { export class Arrow extends CustomElement { static tag = 'arrow'; + static PARSED_STYLE_LIST = new Set([ + ...CustomElement.PARSED_STYLE_LIST, + 'body', + 'startHead', + 'endHead', + 'startHeadOffset', + 'endHeadOffset', + 'stroke', + 'lineWidth', + 'opacity', + 'strokeOpacity', + ]); + private body: Line | Path | Polyline; private startHead?: DisplayObject; private endHead?: DisplayObject; diff --git a/packages/g-components/src/Sector.ts b/packages/g-components/src/Sector.ts index ef31e9ea4..8d037d4c6 100644 --- a/packages/g-components/src/Sector.ts +++ b/packages/g-components/src/Sector.ts @@ -154,6 +154,17 @@ export interface SectorStyleProps extends BaseStyleProps { } export class Sector extends CustomElement { + static PARSED_STYLE_LIST = new Set([ + ...CustomElement.PARSED_STYLE_LIST, + 'startAngle', + 'endAngle', + 'sr', + 'sr0', + 'sradius', + 'sx', + 'sy', + ]); + static tag = 'sector'; private path: Path; diff --git a/packages/g-components/src/Sector2.ts b/packages/g-components/src/Sector2.ts index 92f6aa98d..46fb4f61b 100644 --- a/packages/g-components/src/Sector2.ts +++ b/packages/g-components/src/Sector2.ts @@ -137,6 +137,17 @@ function computeArcSweep(startAngle: number, endAngle: number) { } export class Sector extends Path { + static PARSED_STYLE_LIST = new Set([ + ...Path.PARSED_STYLE_LIST, + 'x', + 'y', + 'sr', + 'sr0', + 'radius', + 'startAngle', + 'endAngle', + ]); + // parsedStyle: any; constructor(config) { super(config); diff --git a/packages/g-lite/src/css/StyleValueRegistry.ts b/packages/g-lite/src/css/StyleValueRegistry.ts index 3c7112cb8..6c3a30ddf 100644 --- a/packages/g-lite/src/css/StyleValueRegistry.ts +++ b/packages/g-lite/src/css/StyleValueRegistry.ts @@ -2,7 +2,7 @@ import { isNil, isUndefined } from '@antv/util'; import { vec3 } from 'gl-matrix'; import type { DisplayObject } from '../display-objects'; import { EMPTY_PARSED_PATH } from '../display-objects/constants'; -import type { GlobalRuntime } from '../global-runtime'; +import { runtime, type GlobalRuntime } from '../global-runtime'; import { GeometryAABBUpdater } from '../services'; import { AABB } from '../shapes'; import type { BaseStyleProps, Tuple3Number } from '../types'; @@ -660,7 +660,7 @@ export class DefaultStyleValueRegistry implements StyleValueRegistry { const oldClipPath = object.parsedStyle.clipPath; const oldOffsetPath = object.parsedStyle.offsetPath; - Object.assign(object.parsedStyle, attributes); + assignParsedStyle(object, attributes); let needUpdateGeometry = !!options.forceUpdateGeometry; if (!needUpdateGeometry) { @@ -1000,3 +1000,20 @@ export class DefaultStyleValueRegistry implements StyleValueRegistry { } } } + +function assignParsedStyle( + object: DisplayObject, + attributes: Record, +) { + if (!runtime.enableMassiveParsedStyleAssignOptimization) { + Object.assign(object.parsedStyle, attributes); + return; + } + + const list = (object.constructor as typeof DisplayObject).PARSED_STYLE_LIST; + for (const key in attributes) { + if (list.has(key)) { + object.parsedStyle[key] = attributes[key]; + } + } +} diff --git a/packages/g-lite/src/display-objects/Circle.ts b/packages/g-lite/src/display-objects/Circle.ts index 884971fbb..d1c8ffcb6 100644 --- a/packages/g-lite/src/display-objects/Circle.ts +++ b/packages/g-lite/src/display-objects/Circle.ts @@ -41,6 +41,16 @@ export class Circle extends DisplayObject< CircleStyleProps, ParsedCircleStyleProps > { + static PARSED_STYLE_LIST: Set = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'cx', + 'cy', + 'cz', + 'r', + 'isBillboard', + 'isSizeAttenuation', + ]); + constructor(options: DisplayObjectConfig = {}) { super({ type: Shape.CIRCLE, diff --git a/packages/g-lite/src/display-objects/CustomElement.ts b/packages/g-lite/src/display-objects/CustomElement.ts index 87cfe11e8..7c71a6091 100644 --- a/packages/g-lite/src/display-objects/CustomElement.ts +++ b/packages/g-lite/src/display-objects/CustomElement.ts @@ -11,10 +11,6 @@ export interface BaseCustomElementStyleProps extends BaseStyleProps {} export abstract class CustomElement< CustomElementStyleProps, > extends DisplayObject { - // static get observedAttributes(): string[] { - // return []; - // } - isCustomElement = true; // private shadowNodes: DisplayObject[] = []; @@ -46,54 +42,4 @@ export abstract class CustomElement< oldParsedValue?: any, newParsedValue?: any, ): void; - - // private handleMounted = (e: FederatedEvent) => { - // if (e.target === this) { - // // this.shadowNodes.forEach((node) => { - // // // every child and its children should turn into a shadow node - // // // a shadow node doesn't mean to be unrenderable, it's just unsearchable in scenegraph - // // node.shadow = true; - // // }); - - // if (this.connectedCallback) { - // this.connectedCallback(); - // } - // } - // }; - - // private handleUnmounted = (e: FederatedEvent) => { - // if (e.target === this) { - - // } - // }; - - // private handleChildInserted = (e: FederatedEvent) => { - // (e.target as DisplayObject).forEach((node) => { - // // append children like other shapes after mounted - // if (!this.isConnected) { - // this.shadowNodes.push(node as DisplayObject); - // } - // }); - // }; - - // private handleChildRemoved = (e: FederatedEvent) => { - // (e.target as DisplayObject).forEach((node) => { - // node.shadow = false; - // }); - // }; - - // private handleAttributeChanged = ( - // e: MutationEvent, - // ) => { - // // only listen itself - // // RangeError: Maximum call stack size exceeded - // if (e.target !== this) { - // return; - // } - - // const { attrName, prevValue, newValue } = e; - // if (this.attributeChangedCallback) { - // this.attributeChangedCallback(attrName as Key, prevValue, newValue); - // } - // }; } diff --git a/packages/g-lite/src/display-objects/DisplayObject.ts b/packages/g-lite/src/display-objects/DisplayObject.ts index 8d98739a9..2766e3d93 100644 --- a/packages/g-lite/src/display-objects/DisplayObject.ts +++ b/packages/g-lite/src/display-objects/DisplayObject.ts @@ -71,6 +71,51 @@ export class DisplayObject< StyleProps extends BaseStyleProps = any, ParsedStyleProps extends ParsedBaseStyleProps = any, > extends Element { + static PARSED_STYLE_LIST = new Set([ + 'class', + 'className', + 'clipPath', + 'cursor', + 'display', + 'draggable', + 'droppable', + 'fill', + 'fillOpacity', + 'fillRule', + 'filter', + 'increasedLineWidthForHitTesting', + 'lineCap', + 'lineDash', + 'lineDashOffset', + 'lineJoin', + 'lineWidth', + 'miterLimit', + 'hitArea', + 'offsetDistance', + 'offsetPath', + 'offsetX', + 'offsetY', + 'opacity', + 'pointerEvents', + 'shadowColor', + 'shadowType', + 'shadowBlur', + 'shadowOffsetX', + 'shadowOffsetY', + 'stroke', + 'strokeOpacity', + 'strokeWidth', + 'strokeLinecap', + 'strokeLineJoin', + 'strokeDasharray', + 'strokeDashoffset', + 'transform', + 'transformOrigin', + 'textTransform', + 'visibility', + 'zIndex', + ]); + /** * contains style props in constructor's params, eg. fill, stroke... */ diff --git a/packages/g-lite/src/display-objects/Ellipse.ts b/packages/g-lite/src/display-objects/Ellipse.ts index ce92aebbd..9bfff28b8 100644 --- a/packages/g-lite/src/display-objects/Ellipse.ts +++ b/packages/g-lite/src/display-objects/Ellipse.ts @@ -25,6 +25,17 @@ export class Ellipse extends DisplayObject< EllipseStyleProps, ParsedEllipseStyleProps > { + static PARSED_STYLE_LIST: Set = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'cx', + 'cy', + 'cz', + 'rx', + 'ry', + 'isBillboard', + 'isSizeAttenuation', + ]); + constructor(options: DisplayObjectConfig = {}) { super({ type: Shape.ELLIPSE, diff --git a/packages/g-lite/src/display-objects/Group.ts b/packages/g-lite/src/display-objects/Group.ts index 2ec8c8344..8d675abc8 100644 --- a/packages/g-lite/src/display-objects/Group.ts +++ b/packages/g-lite/src/display-objects/Group.ts @@ -25,6 +25,12 @@ export interface ParsedGroupStyleProps extends ParsedBaseStyleProps { */ export class Group extends DisplayObject { + static PARSED_STYLE_LIST: Set = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'width', + 'height', + ]); + constructor(options: DisplayObjectConfig = {}) { super({ type: Shape.GROUP, diff --git a/packages/g-lite/src/display-objects/HTML.ts b/packages/g-lite/src/display-objects/HTML.ts index 3edaf0b26..06beb2e11 100644 --- a/packages/g-lite/src/display-objects/HTML.ts +++ b/packages/g-lite/src/display-objects/HTML.ts @@ -27,6 +27,16 @@ export interface ParsedHTMLStyleProps extends ParsedBaseStyleProps { * @see https://github.com/pmndrs/drei#html */ export class HTML extends DisplayObject { + static PARSED_STYLE_LIST: Set = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'x', + 'y', + '$el', + 'innerHTML', + 'width', + 'height', + ]); + constructor({ style, ...rest }: DisplayObjectConfig = {}) { super({ type: Shape.HTML, diff --git a/packages/g-lite/src/display-objects/Image.ts b/packages/g-lite/src/display-objects/Image.ts index 8c7c494eb..c9471336c 100644 --- a/packages/g-lite/src/display-objects/Image.ts +++ b/packages/g-lite/src/display-objects/Image.ts @@ -43,6 +43,20 @@ export class Image extends DisplayObject< ImageStyleProps, ParsedImageStyleProps > { + static PARSED_STYLE_LIST: Set = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'x', + 'y', + 'z', + 'src', + 'width', + 'height', + 'isBillboard', + 'billboardRotation', + 'isSizeAttenuation', + 'keepAspectRatio', + ]); + constructor(options: DisplayObjectConfig = {}) { super({ type: Shape.IMAGE, diff --git a/packages/g-lite/src/display-objects/Line.ts b/packages/g-lite/src/display-objects/Line.ts index c08d8f7ee..13d59f8a7 100644 --- a/packages/g-lite/src/display-objects/Line.ts +++ b/packages/g-lite/src/display-objects/Line.ts @@ -81,6 +81,22 @@ export interface ParsedLineStyleProps extends ParsedBaseStyleProps { * Also support for using marker. */ export class Line extends DisplayObject { + static PARSED_STYLE_LIST: Set = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'x1', + 'y1', + 'x2', + 'y2', + 'z1', + 'z2', + 'isBillboard', + 'isSizeAttenuation', + 'markerStart', + 'markerEnd', + 'markerStartOffset', + 'markerEndOffset', + ]); + private markerStartAngle = 0; private markerEndAngle = 0; diff --git a/packages/g-lite/src/display-objects/Path.ts b/packages/g-lite/src/display-objects/Path.ts index 46141eb02..30ad9ff6a 100644 --- a/packages/g-lite/src/display-objects/Path.ts +++ b/packages/g-lite/src/display-objects/Path.ts @@ -106,6 +106,18 @@ export interface ParsedPathStyleProps extends ParsedBaseStyleProps { isSizeAttenuation?: boolean; } export class Path extends DisplayObject { + static PARSED_STYLE_LIST: Set = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'd', + 'markerStart', + 'markerMid', + 'markerEnd', + 'markerStartOffset', + 'markerEndOffset', + 'isBillboard', + 'isSizeAttenuation', + ]); + private markerStartAngle = 0; private markerEndAngle = 0; diff --git a/packages/g-lite/src/display-objects/Polygon.ts b/packages/g-lite/src/display-objects/Polygon.ts index dda42b4c0..c8e19cfb8 100644 --- a/packages/g-lite/src/display-objects/Polygon.ts +++ b/packages/g-lite/src/display-objects/Polygon.ts @@ -50,6 +50,19 @@ export class Polygon extends DisplayObject< PolygonStyleProps, ParsedPolygonStyleProps > { + static PARSED_STYLE_LIST: Set = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'points', + 'markerStart', + 'markerMid', + 'markerEnd', + 'markerStartOffset', + 'markerEndOffset', + 'isClosed', + 'isBillboard', + 'isSizeAttenuation', + ]); + private markerStartAngle = 0; private markerEndAngle = 0; diff --git a/packages/g-lite/src/display-objects/Polyline.ts b/packages/g-lite/src/display-objects/Polyline.ts index 7f439fbce..c937c8ec2 100644 --- a/packages/g-lite/src/display-objects/Polyline.ts +++ b/packages/g-lite/src/display-objects/Polyline.ts @@ -58,6 +58,17 @@ export interface ParsedPolylineStyleProps extends ParsedBaseStyleProps { * Polyline inherits the marker-related capabilities of Polygon. */ export class Polyline extends Polygon { + static PARSED_STYLE_LIST = new Set([ + ...Polygon.PARSED_STYLE_LIST, + 'points', + 'markerStart', + 'markerMid', + 'markerEnd', + 'markerStartOffset', + 'markerEndOffset', + 'isBillboard', + ]); + constructor({ style, ...rest diff --git a/packages/g-lite/src/display-objects/Rect.ts b/packages/g-lite/src/display-objects/Rect.ts index 1bec77bec..62f4c857f 100644 --- a/packages/g-lite/src/display-objects/Rect.ts +++ b/packages/g-lite/src/display-objects/Rect.ts @@ -29,6 +29,18 @@ export interface ParsedRectStyleProps extends ParsedBaseStyleProps { } export class Rect extends DisplayObject { + static PARSED_STYLE_LIST: Set = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'x', + 'y', + 'z', + 'width', + 'height', + 'isBillboard', + 'isSizeAttenuation', + 'radius', + ]); + constructor(options: DisplayObjectConfig = {}) { super({ type: Shape.RECT, diff --git a/packages/g-lite/src/display-objects/Text.ts b/packages/g-lite/src/display-objects/Text.ts index 2255d6b89..b59445aed 100644 --- a/packages/g-lite/src/display-objects/Text.ts +++ b/packages/g-lite/src/display-objects/Text.ts @@ -216,7 +216,6 @@ export interface ParsedTextStyleProps extends ParsedBaseStyleProps { fontVariant?: 'normal' | 'small-caps' | string; lineHeight?: number; letterSpacing?: number; - // whiteSpace?: 'pre'; leading?: number; wordWrap?: boolean; wordWrapWidth?: number; @@ -229,8 +228,6 @@ export interface ParsedTextStyleProps extends ParsedBaseStyleProps { textDecorationStyle?: TextDecorationStyle | string; textPathSide?: 'left' | 'right'; textPathStartOffset?: number; - // dropShadow?: boolean; - // dropShadowDistance?: number; metrics?: TextMetrics; dx?: number; dy?: number; @@ -240,6 +237,41 @@ export interface ParsedTextStyleProps extends ParsedBaseStyleProps { * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGTextElement */ export class Text extends DisplayObject { + static PARSED_STYLE_LIST: Set = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'x', + 'y', + 'z', + 'isBillboard', + 'billboardRotation', + 'isSizeAttenuation', + 'text', + 'textAlign', + 'textBaseline', + 'fontStyle', + 'fontSize', + 'fontFamily', + 'fontWeight', + 'fontVariant', + 'lineHeight', + 'letterSpacing', + 'leading', + 'wordWrap', + 'wordWrapWidth', + 'maxLines', + 'textOverflow', + 'isOverflowing', + 'textPath', + 'textDecorationLine', + 'textDecorationColor', + 'textDecorationStyle', + 'textPathSide', + 'textPathStartOffset', + 'metrics', + 'dx', + 'dy', + ]); + /** * @see https://developer.mozilla.org/en-US/docs/Web/API/SVGTextContentElement#constants */ diff --git a/packages/g-lite/src/global-runtime.ts b/packages/g-lite/src/global-runtime.ts index dfc8cd13c..498249bb4 100644 --- a/packages/g-lite/src/global-runtime.ts +++ b/packages/g-lite/src/global-runtime.ts @@ -73,6 +73,12 @@ export interface GlobalRuntime { enableStyleSyntax: boolean; enableSizeAttenuation: boolean; + + /** + * Only clone properties that are listed in the `PARSED_STYLE_LIST` of the display object. + * default false + */ + enableMassiveParsedStyleAssignOptimization?: boolean; } /** @@ -82,6 +88,7 @@ const geometryUpdaterFactory: Record> = (() => { const rectUpdater = new RectUpdater(); const polylineUpdater = new PolylineUpdater(); return { + [Shape.FRAGMENT]: null, [Shape.CIRCLE]: new CircleUpdater(), [Shape.ELLIPSE]: new EllipseUpdater(), [Shape.RECT]: rectUpdater, diff --git a/packages/g-plugin-device-renderer/src/Mesh.ts b/packages/g-plugin-device-renderer/src/Mesh.ts index 427335171..ef87fdbe6 100644 --- a/packages/g-plugin-device-renderer/src/Mesh.ts +++ b/packages/g-plugin-device-renderer/src/Mesh.ts @@ -26,6 +26,15 @@ export interface ParsedMeshStyleProps extends ParsedBaseStyleProps { export class Mesh extends DisplayObject< GeometryProps & MeshStyleProps > { + static PARSED_STYLE_LIST = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'x', + 'y', + 'z', + 'geometry', + 'material', + ]); + constructor({ style, ...rest diff --git a/packages/g-plugin-device-renderer/src/lights/Fog.ts b/packages/g-plugin-device-renderer/src/lights/Fog.ts index 08da3edc7..9be8fa950 100644 --- a/packages/g-plugin-device-renderer/src/lights/Fog.ts +++ b/packages/g-plugin-device-renderer/src/lights/Fog.ts @@ -17,6 +17,14 @@ export interface FogProps extends BaseStyleProps { end: number; } export class Fog extends DisplayObject { + static PARSED_STYLE_LIST = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'type', + 'density', + 'start', + 'end', + ]); + static tag = 'fog'; constructor({ style, ...rest }: DisplayObjectConfig = {}) { diff --git a/packages/g-plugin-device-renderer/src/lights/Light.ts b/packages/g-plugin-device-renderer/src/lights/Light.ts index 4a4a2763b..1218d26e8 100644 --- a/packages/g-plugin-device-renderer/src/lights/Light.ts +++ b/packages/g-plugin-device-renderer/src/lights/Light.ts @@ -6,6 +6,11 @@ export interface LightProps extends BaseStyleProps { intensity?: number; } export abstract class Light extends DisplayObject { + static PARSED_STYLE_LIST = new Set([ + ...DisplayObject.PARSED_STYLE_LIST, + 'intensity', + ]); + static tag = 'light'; abstract define: string;