| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- "use strict";
- var __rest = (this && this.__rest) || function (s, e) {
- var t = {};
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
- t[p] = s[p];
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
- t[p[i]] = s[p[i]];
- }
- return t;
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.BrushAxisHighlight = exports.brushAxisHighlight = exports.AXIS_HOT_AREA_CLASS_NAME = exports.AXIS_MAIN_CLASS_NAME = exports.AXIS_LINE_CLASS_NAME = exports.AXIS_CLASS_NAME = void 0;
- const g_1 = require("@antv/g");
- const helper_1 = require("../utils/helper");
- const scale_1 = require("../utils/scale");
- const brushHighlight_1 = require("./brushHighlight");
- const brushXHighlight_1 = require("./brushXHighlight");
- const brushYHighlight_1 = require("./brushYHighlight");
- const utils_1 = require("./utils");
- exports.AXIS_CLASS_NAME = 'axis';
- exports.AXIS_LINE_CLASS_NAME = 'axis-line';
- exports.AXIS_MAIN_CLASS_NAME = 'axis-main-group';
- exports.AXIS_HOT_AREA_CLASS_NAME = 'axis-hot-area';
- function axesOf(container) {
- return container.getElementsByClassName(exports.AXIS_CLASS_NAME);
- }
- function lineOf(axis) {
- return axis.getElementsByClassName(exports.AXIS_LINE_CLASS_NAME)[0];
- }
- function mainGroupOf(axis) {
- return axis.getElementsByClassName(exports.AXIS_MAIN_CLASS_NAME)[0];
- }
- // Use the bounds of main group of axis as the bounds of axis,
- // get rid of grid and title.
- function boundsOfAxis(axis) {
- return mainGroupOf(axis).getLocalBounds();
- }
- // Brush for vertical axis.
- function verticalBrush(axis, _a) {
- var { cross, offsetX, offsetY } = _a, style = __rest(_a, ["cross", "offsetX", "offsetY"]);
- const bounds = boundsOfAxis(axis);
- const axisLine = lineOf(axis);
- const [lineX] = axisLine.getLocalBounds().min;
- const [minX, minY] = bounds.min;
- const [maxX, maxY] = bounds.max;
- const size = (maxX - minX) * 2;
- return {
- brushRegion: brushYHighlight_1.brushYRegion,
- hotZone: new g_1.Rect({
- className: exports.AXIS_HOT_AREA_CLASS_NAME,
- style: Object.assign({
- // If it is not cross, draw brush in both side of axisLine,
- // otherwise the draw brush within bounds area.
- x: cross ? minX : lineX - size / 2, width: cross ? size / 2 : size, y: minY, height: maxY - minY }, style),
- }),
- extent: cross
- ? // If it is cross, the x range is ignored.
- (x, y, x1, y1) => [-Infinity, y, Infinity, y1]
- : (x, y, x1, y1) => [
- Math.floor(minX - offsetX),
- y,
- Math.ceil(maxX - offsetX),
- y1,
- ],
- };
- }
- // Brush for horizontal axis.
- function horizontalBrush(axis, _a) {
- var { offsetY, offsetX, cross = false } = _a, style = __rest(_a, ["offsetY", "offsetX", "cross"]);
- const bounds = boundsOfAxis(axis);
- const axisLine = lineOf(axis);
- const [, lineY] = axisLine.getLocalBounds().min;
- const [minX, minY] = bounds.min;
- const [maxX, maxY] = bounds.max;
- const size = maxY - minY;
- return {
- brushRegion: brushXHighlight_1.brushXRegion,
- hotZone: new g_1.Rect({
- className: exports.AXIS_HOT_AREA_CLASS_NAME,
- style: Object.assign({ x: minX, width: maxX - minX,
- // If it is not cross, draw brush in both side of axisLine,
- // otherwise the draw brush within bounds area.
- y: cross ? minY : lineY - size, height: cross ? size : size * 2 }, style),
- }),
- extent: cross
- ? // If it is cross, the y range is ignored.
- (x, y, x1, y1) => [x, -Infinity, x1, Infinity]
- : (x, y, x1, y1) => [
- x,
- Math.floor(minY - offsetY),
- x1,
- Math.ceil(maxY - offsetY),
- ],
- };
- }
- function brushAxisHighlight(root, _a) {
- var { axes: axesOf, // given root, return axes
- elements: elementsOf, // given root, return elements
- points: pointsOf, // given shape, return control points
- horizontal: isHorizontal, // given axis, return direction
- datum, // given shape, return datum
- offsetY, // offsetY for shape area
- offsetX, // offsetX for shape area
- reverse = false, state = {}, emitter, coordinate } = _a, rest = __rest(_a, ["axes", "elements", "points", "horizontal", "datum", "offsetY", "offsetX", "reverse", "state", "emitter", "coordinate"]) // style
- ;
- const elements = elementsOf(root);
- const axes = axesOf(root);
- const valueof = (0, utils_1.createValueof)(elements, datum);
- const { setState, removeState } = (0, utils_1.useState)(state, valueof);
- const axisExtent = new Map();
- const brushStyle = (0, helper_1.subObject)(rest, 'mask');
- // Only some of shape's points in all mask, it is selected.
- const brushed = (points) => Array.from(axisExtent.values()).every(([x, y, x1, y1]) => points.some(([x0, y0]) => {
- return x0 >= x && x0 <= x1 && y0 >= y && y0 <= y1;
- }));
- const scales = axes.map((d) => d.attributes.scale);
- const extentOf = (D) => (D.length > 2 ? [D[0], D[D.length - 1]] : D);
- const indexDomain = new Map();
- const initIndexDomain = () => {
- indexDomain.clear();
- for (let i = 0; i < axes.length; i++) {
- const scale = scales[i];
- const { domain } = scale.getOptions();
- indexDomain.set(i, extentOf(domain));
- }
- };
- initIndexDomain();
- // Update element when brush changed.
- const updateElement = (i, emit) => {
- const selectedElements = [];
- for (const element of elements) {
- const points = pointsOf(element);
- if (brushed(points)) {
- setState(element, 'active');
- selectedElements.push(element);
- }
- else
- setState(element, 'inactive');
- }
- indexDomain.set(i, selectionOf(selectedElements, i));
- if (!emit)
- return;
- // Emit events.
- const selection = () => {
- if (!cross)
- return Array.from(indexDomain.values());
- const S = [];
- for (const [index, domain] of indexDomain) {
- const scale = scales[index];
- const { name } = scale.getOptions();
- if (name === 'x')
- S[0] = domain;
- else
- S[1] = domain;
- }
- return S;
- };
- emitter.emit('brushAxis:highlight', {
- nativeEvent: true,
- data: {
- selection: selection(),
- },
- });
- };
- const clearElement = (emit) => {
- for (const element of elements)
- removeState(element, 'active', 'inactive');
- initIndexDomain();
- if (!emit)
- return;
- emitter.emit('brushAxis:remove', { nativeEvent: true });
- };
- const selectionOf = (selected, i) => {
- const scale = scales[i];
- const { name } = scale.getOptions();
- const domain = selected.map((d) => {
- const data = d.__data__;
- return scale.invert(data[name]);
- });
- return extentOf((0, scale_1.domainOf)(scale, domain));
- };
- // Distinguish between parallel coordinates and normal charts.
- const cross = axes.some(isHorizontal) && axes.some((d) => !isHorizontal(d));
- const handlers = [];
- for (let i = 0; i < axes.length; i++) {
- const axis = axes[i];
- const createBrush = isHorizontal(axis) ? horizontalBrush : verticalBrush;
- const { hotZone, brushRegion, extent } = createBrush(axis, {
- offsetY,
- offsetX,
- cross,
- zIndex: 999,
- fill: 'transparent', // Make it interactive.
- });
- axis.parentNode.appendChild(hotZone);
- const brushHandler = (0, brushHighlight_1.brush)(hotZone, Object.assign(Object.assign({}, brushStyle), { reverse,
- brushRegion,
- brushended(emit) {
- axisExtent.delete(axis);
- if (Array.from(axisExtent.entries()).length === 0)
- clearElement(emit);
- else
- updateElement(i, emit);
- },
- brushed(x, y, x1, y1, emit) {
- axisExtent.set(axis, extent(x, y, x1, y1));
- updateElement(i, emit);
- } }));
- handlers.push(brushHandler);
- }
- const onRemove = (event = {}) => {
- const { nativeEvent } = event;
- if (nativeEvent)
- return;
- handlers.forEach((d) => d.remove());
- };
- const rangeOf = (domain, scale, axis) => {
- const [d0, d1] = domain;
- const maybeStep = (scale) => (scale.getStep ? scale.getStep() : 0);
- const x = abstractOf(d0, scale, axis);
- const x1 = abstractOf(d1, scale, axis) + maybeStep(scale);
- if (isHorizontal(axis))
- return [x, -Infinity, x1, Infinity];
- return [-Infinity, x, Infinity, x1];
- };
- const abstractOf = (x, scale, axis) => {
- const { height, width } = coordinate.getOptions();
- const scale1 = scale.clone();
- if (isHorizontal(axis))
- scale1.update({ range: [0, width] });
- else
- scale1.update({ range: [height, 0] });
- return scale1.map(x);
- };
- const onHighlight = (event) => {
- const { nativeEvent } = event;
- if (nativeEvent)
- return;
- const { selection } = event.data;
- for (let i = 0; i < handlers.length; i++) {
- const domain = selection[i];
- const handler = handlers[i];
- const axis = axes[i];
- if (domain) {
- const scale = scales[i];
- handler.move(...rangeOf(domain, scale, axis), false);
- }
- else {
- handler.remove();
- }
- }
- };
- emitter.on('brushAxis:remove', onRemove);
- emitter.on('brushAxis:highlight', onHighlight);
- return () => {
- handlers.forEach((d) => d.destroy());
- emitter.off('brushAxis:remove', onRemove);
- emitter.off('brushAxis:highlight', onHighlight);
- };
- }
- exports.brushAxisHighlight = brushAxisHighlight;
- /**
- * @todo Support mask size.
- */
- function BrushAxisHighlight(options) {
- return (target, _, emitter) => {
- const { container, view, options: viewOptions } = target;
- const plotArea = (0, utils_1.selectPlotArea)(container);
- const { x: x0, y: y0 } = plotArea.getBBox();
- const { coordinate } = view;
- return brushAxisHighlight(container, Object.assign({ elements: utils_1.selectG2Elements, axes: axesOf, offsetY: y0, offsetX: x0, points: (element) => element.__data__.points, horizontal: (axis) => {
- const { startPos: [sx, sy], endPos: [ex, ey], } = axis.attributes;
- // attention, non-horizontal does not mean vertical
- // it may has a specific degree angle
- return sx !== ex && sy === ey;
- }, datum: (0, utils_1.createDatumof)(view), state: (0, utils_1.mergeState)(viewOptions, [
- 'active',
- ['inactive', { opacity: 0.5 }],
- ]), coordinate,
- emitter }, options));
- };
- }
- exports.BrushAxisHighlight = BrushAxisHighlight;
- //# sourceMappingURL=brushAxisHighlight.js.map
|