Skip to content

Commit

Permalink
refactor: remove this in selection
Browse files Browse the repository at this point in the history
  • Loading branch information
hustcc committed Aug 25, 2023
1 parent ffc8096 commit 8ecafb5
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 57 deletions.
11 changes: 7 additions & 4 deletions __tests__/unit/utils/selection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,18 +353,21 @@ describe('select', () => {
const data = [1, 2, 3];
const s1 = selection.selectAll('rect');
expect(
s1.each(function (d, i) {
s1.each(function (d, i, element) {
expect(d).toBe(data[i]);
expect(this).toBe(R[i]);
expect(element).toBe(R[i]);
}),
).toBe(s1);
});

it('Selection.call() should call the callback for the selection', () => {
const group = new Group();
const selection = select(group);
const append = (selection: Selection, node: DisplayObject) =>
selection.append(() => node);
const append = (
selection: Selection,
parent: G2Element,
node: DisplayObject,
) => selection.append(() => node);
selection.call(append, new Rect({}));
expect(group.childNodes.length).toBe(1);
});
Expand Down
8 changes: 6 additions & 2 deletions src/interaction/brushHighlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DisplayObject, Rect, Path } from '@antv/g';
import { subObject, omitPrefixObject } from '../utils/helper';
import { selectionOf, pixelsOf } from '../utils/scale';
import { createElement } from '../utils/createElement';
import { select, Selection } from '../utils/selection';
import { G2Element, select, Selection } from '../utils/selection';
import {
selectG2Elements,
selectPlotArea,
Expand Down Expand Up @@ -37,7 +37,11 @@ function bboxOf(root: DisplayObject) {
return [0, 0, width, height];
}

function applyStyle(selection: Selection, style: Record<string, any>) {
function applyStyle(
selection: Selection,
parent: G2Element,
style: Record<string, any>,
) {
for (const [key, value] of Object.entries(style)) {
selection.style(key, value);
}
Expand Down
91 changes: 54 additions & 37 deletions src/runtime/plot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,20 +217,20 @@ export async function plot<T extends G2ViewTree>(
.attr('className', VIEW_CLASS_NAME)
.attr('id', (view) => view.key)
.call(applyTranslate)
.each(function (view) {
plotView(view, select(this), transitions, library, context);
enterContainer.set(view, this);
.each(function (view, i, element) {
plotView(view, select(element), transitions, library, context);
enterContainer.set(view, element);
}),
(update) =>
update.call(applyTranslate).each(function (view) {
plotView(view, select(this), transitions, library, context);
updateContainer.set(view, this);
update.call(applyTranslate).each(function (view, i, element) {
plotView(view, select(element), transitions, library, context);
updateContainer.set(view, element);
}),
(exit) =>
exit
.each(function () {
.each(function (d, i, element) {
// Remove existed interactions.
const interactions = this['nameInteraction'].values();
const interactions = element['nameInteraction'].values();
for (const interaction of interactions) {
interaction.destroy();
}
Expand Down Expand Up @@ -775,8 +775,8 @@ async function plotView(
.style('y', (i) => areaLayouts[i].y)
.style('width', (i) => areaLayouts[i].width)
.style('height', (i) => areaLayouts[i].height)
.each(function (i) {
applyStyle(select(this), areaStyles[i]);
.each(function (i, d, element) {
applyStyle(select(element), areaStyles[i]);
});
let px = 0;
let py = 0;
Expand Down Expand Up @@ -847,7 +847,11 @@ async function plotView(
),
),
(update) =>
update.transition(function (options: G2GuideComponentOptions) {
update.transition(function (
options: G2GuideComponentOptions,
i,
element,
) {
const { preserve = false } = options;
if (preserve) return;
const newComponent = renderComponent(
Expand All @@ -858,7 +862,7 @@ async function plotView(
markState,
);
const { attributes } = newComponent;
const [node] = this.childNodes;
const [node] = element.childNodes;
return node.update(attributes);
}),
)
Expand Down Expand Up @@ -933,8 +937,8 @@ async function plotView(
// Using attribute as alternative for other classNames.
.attr('className', ELEMENT_CLASS_NAME)
.attr('markType', type)
.transition(function (data) {
return enterFunction(data, [this]);
.transition(function (data, i, element) {
return enterFunction(data, [element]);
}),
(update) =>
update.call((selection) => {
Expand All @@ -944,14 +948,15 @@ async function plotView(
return [x, y];
});
selection
.transition(function (data, index) {
maybeFacetElement(this, parent, origin);
.transition(function (data, index, element) {
maybeFacetElement(element, parent, origin);
const node = shapeFunction(data, index);
const animation = updateFunction(data, [this], [node]);
const animation = updateFunction(data, [element], [node]);
if (animation !== null) return animation;
if (this.nodeName === node.nodeName) copyAttributes(this, node);
if (element.nodeName === node.nodeName)
copyAttributes(element, node);
else {
this.parentNode.replaceChild(node, this);
element.parentNode.replaceChild(node, element);
node.className = ELEMENT_CLASS_NAME;
// @ts-ignore
node.markType = type;
Expand All @@ -963,11 +968,11 @@ async function plotView(
}),
(exit) => {
return exit
.each(function () {
this.__removed__ = true;
.each(function (d, i, element) {
element.__removed__ = true;
})
.transition(function (data) {
return exitFunction(data, [this]);
.transition(function (data, i, element) {
return exitFunction(data, [element]);
})
.remove();
},
Expand All @@ -977,25 +982,33 @@ async function plotView(
.append(shapeFunction)
.attr('className', ELEMENT_CLASS_NAME)
.attr('markType', type)
.transition(function (data) {
.transition(function (data, i, element) {
// Remove merged elements after animation finishing.
const { __fromElements__: fromElements } = this;
const transition = updateFunction(data, fromElements, [this]);
const exit = new Selection(fromElements, null, this.parentNode);
const { __fromElements__: fromElements } = element;
const transition = updateFunction(data, fromElements, [element]);
const exit = new Selection(
fromElements,
null,
element.parentNode,
);
exit.transition(transition).remove();
return transition;
}),
(split) =>
split
.transition(function (data) {
.transition(function (data, i, element) {
// Append splitted shapes.
const enter = new Selection([], this.__toData__, this.parentNode);
const enter = new Selection(
[],
element.__toData__,
element.parentNode,
);
const toElements = enter
.append(shapeFunction)
.attr('className', ELEMENT_CLASS_NAME)
.attr('markType', type)
.nodes();
return updateFunction(data, [this], toElements);
return updateFunction(data, [element], toElements);
})
// Remove elements to be splitted after animation finishing.
.remove(),
Expand Down Expand Up @@ -1071,11 +1084,11 @@ function plotLabel(
.append((d) => labelShapeFunction.get(d)(d))
.attr('className', LABEL_CLASS_NAME),
(update) =>
update.each(function (d) {
update.each(function (d, i, element) {
// @todo Handle Label with different type.
const shapeFunction = labelShapeFunction.get(d);
const node = shapeFunction(d);
copyAttributes(this, node);
copyAttributes(element, node);
}),
(exit) => exit.remove(),
)
Expand Down Expand Up @@ -1568,8 +1581,8 @@ function updateBBox(selection: Selection) {

function animateBBox(selection: Selection, extent: [number, number]) {
const [delay, duration] = extent;
selection.transition(function (data) {
const { x, y, width, height } = this.style;
selection.transition(function (data, i, element) {
const { x, y, width, height } = element.style;
const {
paddingLeft,
paddingTop,
Expand All @@ -1592,7 +1605,7 @@ function animateBBox(selection: Selection, extent: [number, number]) {
height: innerHeight,
},
];
return this.animate(keyframes, { delay, duration, fill: 'both' });
return element.animate(keyframes, { delay, duration, fill: 'both' });
});
}

Expand All @@ -1606,7 +1619,11 @@ function shapeName(mark, name) {
* Create and update layer for each mark.
* All the layers created here are treated as main layers.
*/
function updateLayers(selection: Selection, marks: G2Mark[]) {
function updateLayers(
selection: Selection,
parent: G2Element,
marks: G2Mark[],
) {
const facet = (d) => (d.class !== undefined ? `${d.class}` : '');

// Skip for empty selection, it can't append nodes.
Expand Down Expand Up @@ -1645,7 +1662,7 @@ function className(...names: string[]): string {
return names.map((d) => `.${d}`).join('');
}

function applyClip(selection, clip?: boolean) {
function applyClip(selection, parent: G2Element, clip?: boolean) {
if (!selection.node()) return;
selection.style('clipPath', (data) => {
if (!clip) return null;
Expand Down
5 changes: 3 additions & 2 deletions src/shape/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { Linear } from '@antv/scale';
import { lowerFirst } from '@antv/util';
import { extent } from 'd3-array';
import { Path as D3Path } from 'd3-path';
import { G2Theme, Primitive, Vector2, Vector3 } from '../runtime';
import { Primitive, Vector2, Vector3 } from '../runtime';
import { indexOf } from '../utils/array';
import { isPolar, isTranspose } from '../utils/coordinate';
import { Selection } from '../utils/selection';
import { G2Element, Selection } from '../utils/selection';
import { angle, angleWithQuadrant, dist, sub } from '../utils/vector';

export function applyStyle(
selection: Selection,
parent: G2Element,
style: Record<string, Primitive>,
) {
for (const [key, value] of Object.entries(style)) {
Expand Down
28 changes: 16 additions & 12 deletions src/utils/selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,49 +365,53 @@ export class Selection<T = any> {
);
}

each(callback: (datum: T, index: number) => any): Selection<T> {
each(callback: (datum: T, index: number, element) => any): Selection<T> {
for (let i = 0; i < this._elements.length; i++) {
const element = this._elements[i];
const datum = element.__data__;
callback.call(element, datum, i);
callback(datum, i, element);
}
return this;
}

attr(key: string, value: any): Selection<T> {
const callback = typeof value !== 'function' ? () => value : value;
return this.each(function (d, i) {
if (value !== undefined) this[key] = callback.call(this, d, i);
return this.each(function (d, i, element) {
if (value !== undefined) element[key] = callback(d, i, element);
});
}

style(key: string, value: any): Selection<T> {
const callback = typeof value !== 'function' ? () => value : value;
return this.each(function (d, i) {
if (value !== undefined) this.style[key] = callback.call(this, d, i);
return this.each(function (d, i, element) {
if (value !== undefined) element.style[key] = callback(d, i, element);
});
}

transition(value: any): Selection<T> {
const callback = typeof value !== 'function' ? () => value : value;
const { _transitions: T } = this;
return this.each(function (d, i) {
T[i] = callback.call(this, d, i);
return this.each(function (d, i, element) {
T[i] = callback(d, i, element);
});
}

on(event: string, handler: any) {
this.each(function () {
this.addEventListener(event, handler);
this.each(function (d, i, element) {
element.addEventListener(event, handler);
});
return this;
}

call(
callback: (selection: Selection<T>, ...args: any[]) => any,
callback: (
selection: Selection<T>,
parent: G2Element,
...args: any[]
) => any,
...args: any[]
): Selection<T> {
callback.call(this._parent, this, ...args);
callback(this, this._parent, ...args);
return this;
}

Expand Down

0 comments on commit 8ecafb5

Please sign in to comment.