import { __assign } from "tslib"; import { contains, filter, find, hasKey, isArray, isNil, isNumberEqual, isObject, memoize, values, } from '@antv/util'; import { FIELD_ORIGIN, GROUP_ATTRS } from '../constant'; import { getName } from './scale'; function snapEqual(v1, v2, scale) { var value1 = scale.translate(v1); var value2 = scale.translate(v2); return isNumberEqual(value1, value2); } function getXValueByPoint(point, geometry) { var coordinate = geometry.coordinate; var xScale = geometry.getXScale(); var range = xScale.range; var rangeMax = range[range.length - 1]; var rangeMin = range[0]; var invertPoint = coordinate.invert(point); var xValue = invertPoint.x; if (coordinate.isPolar && xValue > (1 + rangeMax) / 2) { xValue = rangeMin; // 极坐标下,scale 的 range 被做过特殊处理 } return xScale.translate(xScale.invert(xValue)); } function filterYValue(data, point, geometry) { var coordinate = geometry.coordinate; var yScale = geometry.getYScale(); var yField = yScale.field; var invertPoint = coordinate.invert(point); var yValue = yScale.invert(invertPoint.y); var result = find(data, function (obj) { var originData = obj[FIELD_ORIGIN]; return originData[yField][0] <= yValue && originData[yField][1] >= yValue; }); return result || data[data.length - 1]; } var getXDistance = memoize(function (scale) { if (scale.isCategory) { return 1; } var scaleValues = scale.values; // values 是无序的 var length = scaleValues.length; var min = scale.translate(scaleValues[0]); var max = min; for (var index = 0; index < length; index++) { var value = scaleValues[index]; // 时间类型需要 translate var numericValue = scale.translate(value); if (numericValue < min) { min = numericValue; } if (numericValue > max) { max = numericValue; } } return (max - min) / (length - 1); }); function getTooltipTitle(originData, geometry, title) { var titleField = title; if (!title) { var positionAttr = geometry.getAttribute('position'); var fields = positionAttr.getFields(); titleField = fields[0]; } var scales = geometry.scales; if (scales[titleField]) { // 如果创建了该字段对应的 scale,则通过 scale.getText() 方式取值,因为用户可能对数据进行了格式化 return scales[titleField].getText(originData[titleField]); } // 如果没有对应的 scale,则从原始数据中取值,如果原始数据中仍不存在,则直接放回 title 值 return hasKey(originData, titleField) ? originData[titleField] : titleField; } function getAttributesForLegend(geometry) { var attributes = values(geometry.attributes); return filter(attributes, function (attribute) { return contains(GROUP_ATTRS, attribute.type); }); } function getTooltipValueScale(geometry) { var attributes = getAttributesForLegend(geometry); var scale; for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { var attribute = attributes_1[_i]; var tmpScale = attribute.getScale(attribute.type); if (tmpScale && tmpScale.isLinear) { // 如果指定字段是非 position 的,同时是连续的 scale = tmpScale; break; } } var xScale = geometry.getXScale(); var yScale = geometry.getYScale(); return scale || yScale || xScale; } function getTooltipValue(originData, valueScale) { var field = valueScale.field; var value = originData[field]; if (isArray(value)) { var texts = value.map(function (eachValue) { return valueScale.getText(eachValue); }); return texts.join('-'); } return valueScale.getText(value); } // 根据原始数据获取 tooltip item 中 name 值 function getTooltipName(originData, geometry) { var nameScale; var groupScales = geometry.getGroupScales(); if (groupScales.length) { // 如果存在分组类型,取第一个分组类型 nameScale = groupScales[0]; } if (nameScale) { var field = nameScale.field; return nameScale.getText(originData[field]); } var valueScale = getTooltipValueScale(geometry); return getName(valueScale); } /** * @ignore * Finds data from geometry by point * @param point canvas point * @param data an item of geometry.dataArray * @param geometry * @returns */ export function findDataByPoint(point, data, geometry) { if (data.length === 0) { return null; } var geometryType = geometry.type; var xScale = geometry.getXScale(); var yScale = geometry.getYScale(); var xField = xScale.field; var yField = yScale.field; var rst = null; // 热力图采用最小逼近策略查找 point 击中的数据 if (geometryType === 'heatmap' || geometryType === 'point') { // 将 point 画布坐标转换为原始数据值 var coordinate = geometry.coordinate; var invertPoint = coordinate.invert(point); // 转换成归一化的数据 var x = xScale.invert(invertPoint.x); // 转换为原始值 var y = yScale.invert(invertPoint.y); // 转换为原始值 var min = Infinity; for (var index = 0; index < data.length; index++) { var obj = data[index]; var originData = obj[FIELD_ORIGIN]; var range = Math.pow((originData[xField] - x), 2) + Math.pow((originData[yField] - y), 2); if (range < min) { min = range; rst = obj; } } return rst; } // 其他 Geometry 类型按照 x 字段数据进行查找 var first = data[0]; var last = data[data.length - 1]; var xValue = getXValueByPoint(point, geometry); var firstXValue = first[FIELD_ORIGIN][xField]; var firstYValue = first[FIELD_ORIGIN][yField]; var lastXValue = last[FIELD_ORIGIN][xField]; var isYArray = yScale.isLinear && isArray(firstYValue); // 考虑 x 维度相同,y 是数组区间的情况 // 如果 x 的值是数组 if (isArray(firstXValue)) { for (var index = 0; index < data.length; index++) { var record = data[index]; var originData = record[FIELD_ORIGIN]; // xValue 在 originData[xField] 的数值区间内 if (xScale.translate(originData[xField][0]) <= xValue && xScale.translate(originData[xField][1]) >= xValue) { if (isYArray) { // 层叠直方图场景,x 和 y 都是数组区间 if (!isArray(rst)) { rst = []; } rst.push(record); } else { rst = record; break; } } } if (isArray(rst)) { rst = filterYValue(rst, point, geometry); } } else { var next = void 0; if (!xScale.isLinear && xScale.type !== 'timeCat') { // x 轴对应的数据为非线性以及非时间类型的数据采用遍历查找 for (var index = 0; index < data.length; index++) { var record = data[index]; var originData = record[FIELD_ORIGIN]; if (snapEqual(originData[xField], xValue, xScale)) { if (isYArray) { if (!isArray(rst)) { rst = []; } rst.push(record); } else { rst = record; break; } } else if (xScale.translate(originData[xField]) <= xValue) { last = record; next = data[index + 1]; } } if (isArray(rst)) { rst = filterYValue(rst, point, geometry); } } else { // x 轴对应的数据为线性以及时间类型,进行二分查找,性能更好 if ((xValue > xScale.translate(lastXValue) || xValue < xScale.translate(firstXValue)) && (xValue > xScale.max || xValue < xScale.min)) { // 不在数据范围内 return null; } var firstIdx = 0; var lastIdx = data.length - 1; var middleIdx = void 0; while (firstIdx <= lastIdx) { middleIdx = Math.floor((firstIdx + lastIdx) / 2); var item = data[middleIdx][FIELD_ORIGIN][xField]; if (snapEqual(item, xValue, xScale)) { return data[middleIdx]; } if (xScale.translate(item) <= xScale.translate(xValue)) { firstIdx = middleIdx + 1; last = data[middleIdx]; next = data[middleIdx + 1]; } else { if (lastIdx === 0) { last = data[0]; } lastIdx = middleIdx - 1; } } } if (last && next) { // 计算最逼近的 if (Math.abs(xScale.translate(last[FIELD_ORIGIN][xField]) - xValue) > Math.abs(xScale.translate(next[FIELD_ORIGIN][xField]) - xValue)) { last = next; } } } var distance = getXDistance(geometry.getXScale()); // 每个分类间的平均间距 if (!rst && Math.abs(xScale.translate(last[FIELD_ORIGIN][xField]) - xValue) <= distance / 2) { rst = last; } return rst; } /** * @ignore * Gets tooltip items * @param data * @param geometry * @param [title] * @returns */ export function getTooltipItems(data, geometry, title) { if (title === void 0) { title = ''; } var originData = data[FIELD_ORIGIN]; var tooltipTitle = getTooltipTitle(originData, geometry, title); var tooltipOption = geometry.tooltipOption; var defaultColor = geometry.theme.defaultColor; var items = []; var name; var value; function addItem(itemName, itemValue) { if (!isNil(itemValue) && itemValue !== '') { // 值为 null的时候,忽视 var item = { title: tooltipTitle, data: originData, mappingData: data, name: itemName || tooltipTitle, value: itemValue, color: data.color || defaultColor, marker: true, }; items.push(item); } } if (isObject(tooltipOption)) { var fields = tooltipOption.fields, callback = tooltipOption.callback; if (callback) { // 用户定义了回调函数 var callbackParams = fields.map(function (field) { return data[FIELD_ORIGIN][field]; }); var cfg = callback.apply(void 0, callbackParams); var itemCfg = __assign({ data: data[FIELD_ORIGIN], mappingData: data, title: tooltipTitle, color: data.color || defaultColor, marker: true }, cfg); items.push(itemCfg); } else { var scales = geometry.scales; for (var _i = 0, fields_1 = fields; _i < fields_1.length; _i++) { var field = fields_1[_i]; if (!isNil(originData[field])) { // 字段数据为null, undefined 时不显示 var scale = scales[field]; name = getName(scale); value = scale.getText(originData[field]); addItem(name, value); } } } } else { var valueScale = getTooltipValueScale(geometry); if (!isNil(originData[valueScale.field])) { // 字段数据为null ,undefined时不显示 value = getTooltipValue(originData, valueScale); name = getTooltipName(originData, geometry); addItem(name, value); } } return items; } //# sourceMappingURL=tooltip.js.map