diff --git a/src/runtime/mark.ts b/src/runtime/mark.ts index 1340de5abc..177f36acc6 100644 --- a/src/runtime/mark.ts +++ b/src/runtime/mark.ts @@ -7,15 +7,11 @@ import { G2Mark, G2TransformOptions, G2EncodeOptions, + G2Context, } from './types/options'; import { MarkProps } from './types/mark'; import { NormalizedEncodeSpec, EncodeComponent, Encode } from './types/encode'; -import { - ColumnOf, - TransformContext, - Transform, - TransformComponent, -} from './types/transform'; +import { ColumnOf, Transform, TransformComponent } from './types/transform'; import { applyDefaults, applyDataTransform, @@ -33,11 +29,9 @@ import { export async function initializeMark( partialMark: G2Mark, partialProps: MarkProps, - library: G2Library, - createCanvas: () => HTMLCanvasElement, + context: G2Library, ): Promise<[G2Mark, G2MarkState]> { // Apply transform to mark to derive indices, data, encode, etc,. - const context = { library, createCanvas }; const [I, transformedMark] = await applyMarkTransform( partialMark, partialProps, @@ -144,7 +138,7 @@ export function createColumnOf(library: G2Library): ColumnOf { async function applyMarkTransform( mark: G2Mark, props: MarkProps, - context: TransformContext, + context: G2Context, ): Promise<[number[], G2Mark]> { const { library } = context; const [useTransform] = useLibrary< diff --git a/src/runtime/plot.ts b/src/runtime/plot.ts index f9f10242aa..13c8ab3de5 100644 --- a/src/runtime/plot.ts +++ b/src/runtime/plot.ts @@ -1,5 +1,5 @@ import { Vector2 } from '@antv/coord'; -import { DisplayObject, IAnimation as GAnimation, HTML, Rect } from '@antv/g'; +import { DisplayObject, IAnimation as GAnimation, Rect } from '@antv/g'; import { deepMix, upperFirst, isArray } from '@antv/util'; import { group, groups } from 'd3-array'; import { format } from 'd3-format'; @@ -96,9 +96,10 @@ type Store = Map G2ViewTree>; export async function plot( options: T, selection: Selection, - library: G2Library, context: G2Context, ): Promise { + const { library } = context; + const [useComposition] = useLibrary< G2CompositionOptions, CompositionComponent, @@ -122,8 +123,6 @@ export async function plot( .filter(defined), ); - const { createCanvas } = context; - const typeOf = (node: G2ViewTree) => { const { type } = node; if (typeof type === 'function') { @@ -170,7 +169,7 @@ export async function plot( const state = nodeState.get(node); const [view, children] = state ? initializeState(state, node, library) - : await initializeView(node, library, createCanvas); + : await initializeView(node, context); viewNode.set(view, node); views.push(view); @@ -185,9 +184,7 @@ export async function plot( // should sync position scales among facets normally. if (transformedNodes.every(isStandardView)) { const states = await Promise.all( - transformedNodes.map((d) => - initializeMarks(d, library, createCanvas), - ), + transformedNodes.map((d) => initializeMarks(d, context)), ); // Note!!! // This will mutate scales for marks. @@ -202,9 +199,7 @@ export async function plot( // Apply transform to get data in advance for non-mark composition // node, which makes sure that composition node can preprocess the // data to produce more nodes based on it. - const n = isMark(node) - ? node - : await applyTransform(node, library, createCanvas); + const n = isMark(node) ? node : await applyTransform(node, context); const N = transform(n); if (Array.isArray(N)) discovered.push(...N); else if (typeof N === 'function') nodeGenerators.push(N()); @@ -228,12 +223,12 @@ export async function plot( .attr('id', (view) => view.key) .call(applyTranslate) .each(function (view, i, element) { - plotView(view, select(element), transitions, library, context); + plotView(view, select(element), transitions, context); enterContainer.set(view, element); }), (update) => update.call(applyTranslate).each(function (view, i, element) { - plotView(view, select(element), transitions, library, context); + plotView(view, select(element), transitions, context); updateContainer.set(view, element); }), (exit) => @@ -266,12 +261,7 @@ export async function plot( oldStore || new Map G2ViewTree>(); const setState = (key, reducer = (x) => x) => store.set(key, reducer); const options = viewNode.get(view); - const update = createUpdateView( - select(container), - options, - library, - context, - ); + const update = createUpdateView(select(container), options, context); return { view, container, @@ -378,7 +368,7 @@ export async function plot( const keyframe = new Promise(async (resolve) => { for (const node of nodeGenerator) { const sizedNode = { width, height, ...node }; - await plot(sizedNode, selection, library, context); + await plot(sizedNode, selection, context); } resolve(); }); @@ -430,9 +420,9 @@ function definedInteraction(library: G2Library) { function createUpdateView( selection: Selection, options: G2ViewTree, - library: G2Library, context: G2Context, ): G2ViewInstance['update'] { + const { library } = context; const createDefinedInteraction = definedInteraction(library); const filter = (d) => d[1] && d[1].props && d[1].props.reapplyWhenUpdate; const interactions = inferInteraction(options); @@ -443,20 +433,16 @@ function createUpdateView( return async (newOptions, source, callback) => { const transitions = []; - const [newView, newChildren] = await initializeView( - newOptions, - library, - context.createCanvas, - ); - plotView(newView, selection, transitions, library, context); + const [newView, newChildren] = await initializeView(newOptions, context); + plotView(newView, selection, transitions, context); // Update interaction need to reapply when update. for (const name of updates.filter((d) => d !== source)) { - updateInteraction(name, selection, newOptions, newView, library, context); + updateInteraction(name, selection, newOptions, newView, context); } for (const child of newChildren) { - plot(child, selection, library, context); + plot(child, selection, context); } callback(); return { options: newOptions, view: newView }; @@ -468,9 +454,10 @@ function updateInteraction( selection: Selection, options: G2ViewTree, view: G2ViewDescriptor, - library: G2Library, context: G2Context, ) { + const { library } = context; + const [useInteraction] = useLibrary< G2InteractionOptions, InteractionComponent, @@ -510,10 +497,11 @@ function updateInteraction( async function initializeView( options: G2View, - library: G2Library, - createCanvas: () => HTMLCanvasElement, + context: G2Context, ): Promise<[G2ViewDescriptor, G2ViewTree[]]> { - const flattenOptions = await transformMarks(options, library, createCanvas); + const { library } = context; + + const flattenOptions = await transformMarks(options, context); const mergedOptions = bubbleOptions(flattenOptions); @@ -526,7 +514,7 @@ async function initializeView( options.marks = [...mergedOptions.marks, ...mergedOptions.components]; const transformedOptions = coordinate2Transform(mergedOptions, library); - const state = await initializeMarks(transformedOptions, library); + const state = await initializeMarks(transformedOptions, context); return initializeState(state, transformedOptions, library); } @@ -564,9 +552,10 @@ function bubbleOptions(options: G2View): G2View { async function transformMarks( options: G2View, - library: G2Library, - createCanvas: () => HTMLCanvasElement, + context: G2Context, ): Promise { + const { library } = context; + const [useMark, createMark] = useLibrary( 'mark', library, @@ -582,13 +571,13 @@ async function transformMarks( const components = []; const discovered = [...marks]; const { width, height } = computeRoughPlotSize(options); - const context = { options, width, height }; + const markOptions = { options, width, height }; // Pre order traversal. while (discovered.length) { const [node] = discovered.splice(0, 1); // Apply data transform to get data. - const mark = (await applyTransform(node, library, createCanvas)) as G2Mark; + const mark = (await applyTransform(node, context)) as G2Mark; const { type = error('G2Mark type is required.'), key } = mark; // For components. @@ -607,7 +596,7 @@ async function transformMarks( }; // Convert composite mark to marks. - const marks = await useMark(newMark, context); + const marks = await useMark(newMark, markOptions); const M = Array.isArray(marks) ? marks : [marks]; discovered.unshift(...M.map((d, i) => ({ ...d, key: `${key}-${i}` }))); } @@ -619,9 +608,10 @@ async function transformMarks( async function initializeMarks( options: G2View, - library: G2Library, - createCanvas?: () => HTMLCanvasElement, + context: G2Context, ): Promise> { + const { library } = context; + const [useTheme] = useLibrary( 'theme', library, @@ -643,12 +633,7 @@ async function initializeMarks( for (const markOptions of partialMarks) { const { type } = markOptions; const { props = {} } = createMark(type); - const markAndState = await initializeMark( - markOptions, - props, - library, - createCanvas, - ); + const markAndState = await initializeMark(markOptions, props, context); if (markAndState) { const [initializedMark, state] = markAndState; markState.set(initializedMark, state); @@ -880,9 +865,9 @@ async function plotView( view: G2ViewDescriptor, selection: Selection, transitions: GAnimation[], - library: G2Library, context: G2Context, ): Promise { + const { library } = context; const { components, theme, @@ -1040,13 +1025,7 @@ async function plotView( const { data } = state; const { key, class: cls, type } = mark; const viewNode = selection.select(`#${key}`); - const shapeFunction = createMarkShapeFunction( - mark, - state, - view, - library, - context, - ); + const shapeFunction = createMarkShapeFunction(mark, state, view, context); const enterFunction = createEnterFunction(mark, state, view, library); const updateFunction = createUpdateFunction(mark, state, view, library); const exitFunction = createExitFunction(mark, state, view, library); @@ -1506,13 +1485,14 @@ function createMarkShapeFunction( mark: G2Mark, state: G2MarkState, view: G2ViewDescriptor, - library: G2Library, context: G2Context, ): ( data: Record, index: number, element?: DisplayObject, ) => DisplayObject { + const { library } = context; + const [useShape] = useLibrary( 'shape', library, @@ -1710,10 +1690,8 @@ function inferInteraction( async function applyTransform( node: T, - library: G2Library, - createCanvas: () => HTMLCanvasElement, + context: G2Context, ): Promise { - const context = { library, createCanvas }; const { data, ...rest } = node; if (data == undefined) return node; const [, { data: newData }] = await applyDataTransform([], { data }, context); diff --git a/src/runtime/render.ts b/src/runtime/render.ts index 80b70bde82..c0caea2b16 100644 --- a/src/runtime/render.ts +++ b/src/runtime/render.ts @@ -92,9 +92,7 @@ export function render( // Make sure that plot chart after container is ready for every time. const selection = select(canvas.document.documentElement); canvas.ready - .then(() => - plot({ ...keyed, width, height, depth }, selection, library, context), - ) + .then(() => plot({ ...keyed, width, height, depth }, selection, context)) .then(() => { // Place the center of whole scene at z axis' origin. if (depth) { @@ -147,7 +145,7 @@ export function renderToMountedElement( emitter.emit(ChartEvent.BEFORE_RENDER); // Plot the chart and mutate context. // Make sure that plot chart after container is ready for every time. - plot({ ...keyed, width, height }, selection, library, context) + plot({ ...keyed, width, height }, selection, context) .then(() => { context.canvas?.requestAnimationFrame(() => { emitter.emit(ChartEvent.AFTER_RENDER); diff --git a/src/runtime/transform.ts b/src/runtime/transform.ts index d5e7974160..095caa86bf 100644 --- a/src/runtime/transform.ts +++ b/src/runtime/transform.ts @@ -12,15 +12,14 @@ import { isFullTooltip } from '../utils/mark'; import { useLibrary } from './library'; import { createColumnOf } from './mark'; import { Data, DataComponent } from './types/data'; -import { G2Mark, G2DataOptions } from './types/options'; -import { TransformContext } from './types/transform'; +import { G2Mark, G2DataOptions, G2Context } from './types/options'; import { isPosition } from './scale'; // @todo Add more defaults. export function applyDefaults( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): [number[], G2Mark] { const { encode = {}, scale = {}, transform = [], ...rest } = mark; return [I, { ...rest, encode, scale, transform }]; @@ -29,7 +28,7 @@ export function applyDefaults( export async function applyDataTransform( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): Promise<[number[], G2Mark]> { const { library } = context; const { data } = mark; @@ -62,7 +61,7 @@ export async function applyDataTransform( export function flatEncode( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): [number[], G2Mark] { const { encode } = mark; if (!encode) return [I, mark]; @@ -83,7 +82,7 @@ export function flatEncode( export function inferChannelsType( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): [number[], G2Mark] { const { encode, data } = mark; if (!encode) return [I, mark]; @@ -98,7 +97,7 @@ export function inferChannelsType( export function maybeVisualChannel( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): [number[], G2Mark] { const { encode } = mark; if (!encode) return [I, mark]; @@ -113,7 +112,7 @@ export function maybeVisualChannel( export function extractColumns( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): [number[], G2Mark] { const { encode, data } = mark; if (!encode) return [I, mark]; @@ -129,7 +128,7 @@ export function extractColumns( export function normalizeTooltip( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): [number[], G2Mark] { const { tooltip = {} } = mark; if (isUnset(tooltip)) return [I, mark]; @@ -145,7 +144,7 @@ export function normalizeTooltip( export function extractTooltip( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): [number[], G2Mark] { const { data, encode, tooltip = {} } = mark; if (isUnset(tooltip)) return [I, mark]; @@ -212,7 +211,7 @@ export function extractTooltip( export function maybeArrayField( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): [number[], G2Mark] { const { encode, ...rest } = mark; if (!encode) return [I, mark]; @@ -250,7 +249,7 @@ export function maybeArrayField( export function addGuideToScale( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): [number[], G2Mark] { const { axis = {}, legend = {}, slider = {}, scrollbar = {} } = mark; const normalize = (guide: boolean | Record, channel: string) => { @@ -298,7 +297,7 @@ export function addGuideToScale( export function maybeNonAnimate( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ): [number[], G2Mark] { const { animate } = mark; if (animate || animate === undefined) return [I, mark]; diff --git a/src/runtime/types/data.ts b/src/runtime/types/data.ts index f46aca2e70..062b0390e2 100644 --- a/src/runtime/types/data.ts +++ b/src/runtime/types/data.ts @@ -1,11 +1,11 @@ -import { TransformContext } from './transform'; +import { G2Context } from './options'; export type DataOptions = Record; export type DataProps = Record; export type DataComponent = { - (options?: O, context?: TransformContext): Data; + (options?: O, context?: G2Context): Data; props: DataProps; }; diff --git a/src/runtime/types/transform.ts b/src/runtime/types/transform.ts index 61a0fa5685..9372fcfeda 100644 --- a/src/runtime/types/transform.ts +++ b/src/runtime/types/transform.ts @@ -1,10 +1,5 @@ import { ColumnValue, NormalizedEncodeSpec } from './encode'; -import { G2Library, G2Mark } from './options'; - -export type TransformContext = { - library: G2Library; - createCanvas: () => HTMLCanvasElement; -}; +import { G2Context, G2Mark } from './options'; export type TransformOptions = Record; @@ -19,7 +14,7 @@ export type TransformComponent = export type Transform = ( I: number[], mark: G2Mark, - context: TransformContext, + context: G2Context, ) => [number[], G2Mark] | Promise<[number[], G2Mark]>; export type TransformSpec = {