UNPKG

@antv/g2

Version:

the Grammar of Graphics in Javascript

175 lines 7.83 kB
"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.LegendCategory = void 0; const component_1 = require("@antv/component"); const util_1 = require("@antv/util"); const d3_format_1 = require("d3-format"); const scale_1 = require("@antv/scale"); const marker_1 = require("../utils/marker"); const utils_1 = require("./utils"); function inferShape(scales, markState) { const shapeScale = (0, utils_1.scaleOf)(scales, 'shape'); const colorScale = (0, utils_1.scaleOf)(scales, 'color'); // NOTE!!! // scaleOrdinal.map will mute domain. const shapeScale1 = shapeScale ? shapeScale.clone() : null; // Infer the main shape if multiple marks are used. const shapes = []; for (const [mark, state] of markState) { const namespace = mark.type; const domain = (colorScale === null || colorScale === void 0 ? void 0 : colorScale.getOptions().domain.length) > 0 ? colorScale === null || colorScale === void 0 ? void 0 : colorScale.getOptions().domain : state.data; const shape = domain.map((d, i) => { var _a; if (shapeScale1) return shapeScale1.map(d || 'point'); return ((_a = mark === null || mark === void 0 ? void 0 : mark.style) === null || _a === void 0 ? void 0 : _a.shape) || state.defaultShape || 'point'; }); if (typeof namespace === 'string') shapes.push([namespace, shape]); } if (shapes.length === 0) return ['point', ['point']]; if (shapes.length === 1) return shapes[0]; if (!shapeScale) return shapes[0]; // Evaluate the maximum likelihood of shape const { range } = shapeScale.getOptions(); return shapes .map(([namespace, shape]) => { let sum = 0; for (let i = 0; i < shapes.length; i++) { const targetShape = range[i % range.length]; if (shape[i] === targetShape) sum++; } return [sum / shape.length, [namespace, shape]]; }) .sort((a, b) => b[0] - a[0])[0][1]; } function inferItemMarker(options, context) { const { scales, library, markState } = context; const [mark, shapes] = inferShape(scales, markState); const { itemMarker, itemMarkerSize: size } = options; const create = (name, d) => { var _a, _b, _c; const marker = ((_c = (_b = (_a = library[`mark.${mark}`]) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.shape[name]) === null || _c === void 0 ? void 0 : _c.props.defaultMarker) || (0, util_1.last)(name.split('.')); const radius = typeof size === 'function' ? size(d) : size; return () => (0, marker_1.useMarker)(marker, { color: d.color })(0, 0, radius); }; const shapeOf = (i) => `${shapes[i]}`; const shapeScale = (0, utils_1.scaleOf)(scales, 'shape'); if (shapeScale && !itemMarker) return (d, i) => create(shapeOf(i), d); if (typeof itemMarker === 'function') { return (d, i) => { // @todo Fix this in GUI. // It should pass primitive value rather object. const node = itemMarker(d.id, i); if (typeof node === 'string') return create(node, d); return node; }; } return (d, i) => create(itemMarker || shapeOf(i), d); } function inferItemMarkerOpacity(scales) { const scale = (0, utils_1.scaleOf)(scales, 'opacity'); if (scale) { const { range } = scale.getOptions(); return (d, i) => range[i]; } return undefined; } function inferItemMarkerSize(scales, defaults) { const scale = (0, utils_1.scaleOf)(scales, 'size'); if (scale instanceof scale_1.Identity) return scale.map(NaN) * 2; return defaults; } function inferCategoryStyle(options, context) { const { labelFormatter = (d) => `${d}` } = options; const { scales, theme } = context; const defaultSize = theme.legendCategory.itemMarkerSize; const itemMarkerSize = inferItemMarkerSize(scales, defaultSize); const baseStyle = { itemMarker: inferItemMarker(Object.assign(Object.assign({}, options), { itemMarkerSize }), context), itemMarkerSize: itemMarkerSize, itemMarkerOpacity: inferItemMarkerOpacity(scales), }; const finalLabelFormatter = typeof labelFormatter === 'string' ? (0, d3_format_1.format)(labelFormatter) : labelFormatter; const colorScale = (0, utils_1.scaleOf)(scales, 'color'); const domain = (0, utils_1.domainOf)(scales); const colorOf = colorScale ? (d) => colorScale.map(d) : () => context.theme.color; return Object.assign(Object.assign({}, baseStyle), { data: domain.map((d) => ({ id: d, label: finalLabelFormatter(d), color: colorOf(d), })) }); } function inferLegendShape(value, options, component) { const { position } = options; if (position === 'center') { const { bbox } = value; // to be confirm: if position is center, we should use the width and height of user definition. const { width, height } = bbox; return { width, height }; } const { width, height } = (0, utils_1.inferComponentShape)(value, options, component); return { width, height }; } /** * Guide Component for ordinal color scale. */ const LegendCategory = (options) => { const { labelFormatter, layout, order, orientation, position, size, title, cols, itemMarker } = options, style = __rest(options, ["labelFormatter", "layout", "order", "orientation", "position", "size", "title", "cols", "itemMarker"]); const { gridRow } = style; return (context) => { const { value, theme } = context; const { bbox } = value; const { width, height } = inferLegendShape(value, options, exports.LegendCategory); const finalLayout = (0, utils_1.inferComponentLayout)(position, layout); const legendStyle = Object.assign(Object.assign(Object.assign(Object.assign({ orientation: ['right', 'left', 'center'].includes(position) ? 'vertical' : 'horizontal', width, height, layout: cols !== undefined ? 'grid' : 'flex' }, (cols !== undefined && { gridCol: cols })), (gridRow !== undefined && { gridRow })), { titleText: (0, utils_1.titleContent)(title) }), inferCategoryStyle(options, context)); const { legendCategory: legendTheme = {} } = theme; const categoryStyle = (0, utils_1.adaptor)(Object.assign({}, legendTheme, legendStyle, style)); const layoutWrapper = new utils_1.LegendCategoryLayout({ style: Object.assign(Object.assign({ x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height }, finalLayout), { // @ts-ignore subOptions: categoryStyle }), }); layoutWrapper.appendChild(new component_1.Category({ className: 'legend-category', style: categoryStyle, })); return layoutWrapper; }; }; exports.LegendCategory = LegendCategory; exports.LegendCategory.props = { defaultPosition: 'top', defaultOrder: 1, defaultSize: 40, defaultCrossPadding: [12, 12], defaultPadding: [12, 12], }; //# sourceMappingURL=legendCategory.js.map