UNPKG

@antv/g2plot

Version:

An interactive and responsive charting library

182 lines 8.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.conversionTag = void 0; var tslib_1 = require("tslib"); var g2_1 = require("@antv/g2"); var util_1 = require("@antv/util"); var utils_1 = require("../utils"); var conversion_1 = require("../utils/conversion"); function getConversionTagOptionsWithDefaults(options, horizontal) { return (0, utils_1.deepAssign)({ size: horizontal ? 32 : 80, spacing: horizontal ? 8 : 12, offset: horizontal ? 32 : 0, arrow: options.arrow !== false && { headSize: 12, style: { fill: 'rgba(0, 0, 0, 0.05)', }, }, text: options.text !== false && { style: { fontSize: 12, fill: 'rgba(0, 0, 0, 0.85)', textAlign: 'center', textBaseline: 'middle', }, formatter: conversion_1.conversionTagFormatter, }, }, options); } function parsePoints(coordinate, element) { // @ts-ignore return (0, util_1.map)(element.getModel().points, function (point) { return coordinate.convertPoint(point); }); } function renderArrowTag(config, elemPrev, elemNext) { var view = config.view, geometry = config.geometry, group = config.group, options = config.options, horizontal = config.horizontal; var offset = options.offset, size = options.size, arrow = options.arrow; var coordinate = view.getCoordinate(); var pointPrev = parsePoints(coordinate, elemPrev)[3]; var pointNext = parsePoints(coordinate, elemNext)[0]; var totalHeight = pointNext.y - pointPrev.y; var totalWidth = pointNext.x - pointPrev.x; if (typeof arrow === 'boolean') { return; } var headSize = arrow.headSize; var spacing = options.spacing; var points; if (horizontal) { if ((totalWidth - headSize) / 2 < spacing) { // 当柱间距不足容纳箭头尖与间隔时,画三角并挤占间隔 spacing = Math.max(1, (totalWidth - headSize) / 2); points = [ [pointPrev.x + spacing, pointPrev.y - offset], [pointPrev.x + spacing, pointPrev.y - offset - size], [pointNext.x - spacing, pointNext.y - offset - size / 2], ]; } else { // 当柱间距足够时,画完整图形并留出间隔。 points = [ [pointPrev.x + spacing, pointPrev.y - offset], [pointPrev.x + spacing, pointPrev.y - offset - size], [pointNext.x - spacing - headSize, pointNext.y - offset - size], [pointNext.x - spacing, pointNext.y - offset - size / 2], [pointNext.x - spacing - headSize, pointNext.y - offset], ]; } } else { if ((totalHeight - headSize) / 2 < spacing) { // 当柱间距不足容纳箭头尖与间隔时,画三角并挤占间隔 spacing = Math.max(1, (totalHeight - headSize) / 2); points = [ [pointPrev.x + offset, pointPrev.y + spacing], [pointPrev.x + offset + size, pointPrev.y + spacing], [pointNext.x + offset + size / 2, pointNext.y - spacing], ]; } else { // 当柱间距足够时,画完整图形并留出间隔。 points = [ [pointPrev.x + offset, pointPrev.y + spacing], [pointPrev.x + offset + size, pointPrev.y + spacing], [pointNext.x + offset + size, pointNext.y - spacing - headSize], [pointNext.x + offset + size / 2, pointNext.y - spacing], [pointNext.x + offset, pointNext.y - spacing - headSize], ]; } } group.addShape('polygon', { id: "".concat(view.id, "-conversion-tag-arrow-").concat(geometry.getElementId(elemPrev.getModel().mappingData)), name: 'conversion-tag-arrow', origin: { element: elemPrev, nextElement: elemNext, }, attrs: tslib_1.__assign(tslib_1.__assign({}, (arrow.style || {})), { points: points }), }); } function renderTextTag(config, elemPrev, elemNext) { var _a, _b, _c; var view = config.view, geometry = config.geometry, group = config.group, options = config.options, field = config.field, horizontal = config.horizontal; var offset = options.offset, size = options.size; if (typeof options.text === 'boolean') { return; } var coordinate = view.getCoordinate(); var text = ((_a = options.text) === null || _a === void 0 ? void 0 : _a.formatter) && ((_b = options.text) === null || _b === void 0 ? void 0 : _b.formatter(elemPrev.getData()[field], elemNext.getData()[field])); var pointPrev = parsePoints(coordinate, elemPrev)[horizontal ? 3 : 0]; var pointNext = parsePoints(coordinate, elemNext)[horizontal ? 0 : 3]; var textShape = group.addShape('text', { id: "".concat(view.id, "-conversion-tag-text-").concat(geometry.getElementId(elemPrev.getModel().mappingData)), name: 'conversion-tag-text', origin: { element: elemPrev, nextElement: elemNext, }, attrs: tslib_1.__assign(tslib_1.__assign({}, (((_c = options.text) === null || _c === void 0 ? void 0 : _c.style) || {})), { text: text, x: horizontal ? (pointPrev.x + pointNext.x) / 2 : pointPrev.x + offset + size / 2, y: horizontal ? pointPrev.y - offset - size / 2 : (pointPrev.y + pointNext.y) / 2 }), }); if (horizontal) { var totalWidth = pointNext.x - pointPrev.x; var textWidth = textShape.getBBox().width; if (textWidth > totalWidth) { var cWidth = textWidth / text.length; var cEnd = Math.max(1, Math.ceil(totalWidth / cWidth) - 1); var textAdjusted = "".concat(text.slice(0, cEnd), "..."); textShape.attr('text', textAdjusted); } } } function renderTag(options, elemPrev, elemNext) { renderArrowTag(options, elemPrev, elemNext); renderTextTag(options, elemPrev, elemNext); } /** * 返回支持转化率组件的 adaptor,适用于柱形图/条形图 * @param field 用户转化率计算的字段 * @param horizontal 是否水平方向的转化率 * @param disabled 是否禁用 */ function conversionTag(field, horizontal, disabled) { if (horizontal === void 0) { horizontal = true; } if (disabled === void 0) { disabled = false; } return function (params) { var options = params.options, chart = params.chart; var conversionTag = options.conversionTag, theme = options.theme; if (conversionTag && !disabled) { // 有转化率组件时,柱子宽度占比自动为 1/3 chart.theme((0, utils_1.deepAssign)({}, (0, util_1.isObject)(theme) ? theme : (0, g2_1.getTheme)(theme), { columnWidthRatio: 1 / 3, })); // 使用 shape annotation 绘制转化率组件 chart.annotation().shape({ render: function (container, view) { var group = container.addGroup({ id: "".concat(chart.id, "-conversion-tag-group"), name: 'conversion-tag-group', }); var interval = (0, util_1.find)(chart.geometries, function (geom) { return geom.type === 'interval'; }); var config = { view: view, geometry: interval, group: group, field: field, horizontal: horizontal, options: getConversionTagOptionsWithDefaults(conversionTag, horizontal), }; var elements = interval.elements; (0, util_1.each)(elements, function (elem, idx) { if (idx > 0) { renderTag(config, elements[idx - 1], elem); } }); }, }); } return params; }; } exports.conversionTag = conversionTag; //# sourceMappingURL=conversion-tag.js.map