361 lines
9.7 KiB
Java
361 lines
9.7 KiB
Java
import { each, isArray } from '@antv/util';
|
||
import { catmullRom2bezier, getLinePath } from '../../geometry/shape/util/path';
|
||
import { toPoints } from '../../util/bbox';
|
||
import isPolygonsIntersect from '@antv/path-util/lib/is-polygons-intersect';
|
||
function getMaskBBox(context, tolerance) {
|
||
var event = context.event;
|
||
var maskShape = event.target;
|
||
var maskBBox = maskShape.getCanvasBBox();
|
||
// 如果 bbox 过小则不返回
|
||
if (!(maskBBox.width >= tolerance || maskBBox.height >= tolerance)) {
|
||
return null;
|
||
}
|
||
return maskBBox;
|
||
}
|
||
function getMaskPath(context, tolerance) {
|
||
var event = context.event;
|
||
var maskShape = event.target;
|
||
var maskBBox = maskShape.getCanvasBBox();
|
||
// 如果 bbox 过小则不返回
|
||
if (!(maskBBox.width >= tolerance || maskBBox.height >= tolerance)) {
|
||
return null;
|
||
}
|
||
return maskShape.attr('path');
|
||
}
|
||
/**
|
||
* 获取当前事件相关的图表元素
|
||
* @param context 交互的上下文
|
||
* @ignore
|
||
*/
|
||
export function getCurrentElement(context) {
|
||
var event = context.event;
|
||
var element;
|
||
var target = event.target;
|
||
if (target) {
|
||
element = target.get('element');
|
||
}
|
||
return element;
|
||
}
|
||
/**
|
||
* 获取委托对象
|
||
* @param context 上下文
|
||
* @ignore
|
||
*/
|
||
export function getDelegationObject(context) {
|
||
var event = context.event;
|
||
var target = event.target;
|
||
var delegateObject;
|
||
if (target) {
|
||
delegateObject = target.get('delegateObject');
|
||
}
|
||
return delegateObject;
|
||
}
|
||
export function isElementChange(context) {
|
||
var event = context.event.gEvent;
|
||
// 在同一个 element 内部移动,label 和 shape 之间
|
||
if (event && event.fromShape && event.toShape && event.fromShape.get('element') === event.toShape.get('element')) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
/**
|
||
* 是否是列表组件
|
||
* @param delegateObject 委托对象
|
||
* @ignore
|
||
*/
|
||
export function isList(delegateObject) {
|
||
return delegateObject && delegateObject.component && delegateObject.component.isList();
|
||
}
|
||
/**
|
||
* 是否是滑块组件
|
||
* @param delegateObject 委托对象
|
||
* @ignore
|
||
*/
|
||
export function isSlider(delegateObject) {
|
||
return delegateObject && delegateObject.component && delegateObject.component.isSlider();
|
||
}
|
||
/**
|
||
* 是否由 mask 触发
|
||
* @param context 上下文
|
||
* @ignore
|
||
*/
|
||
export function isMask(context) {
|
||
var event = context.event;
|
||
var target = event.target;
|
||
return target && target.get('name') === 'mask';
|
||
}
|
||
/**
|
||
* 获取被遮挡的 elements
|
||
* @param context 上下文
|
||
* @ignore
|
||
*/
|
||
export function getMaskedElements(context, tolerance) {
|
||
var target = context.event.target;
|
||
if (target.get('type') === 'path') {
|
||
var maskPath = getMaskPath(context, tolerance);
|
||
if (!maskPath) {
|
||
return;
|
||
}
|
||
return getElementsByPath(context.view, maskPath);
|
||
}
|
||
var maskBBox = getMaskBBox(context, tolerance);
|
||
// 如果 bbox 过小则不返回
|
||
if (!maskBBox) {
|
||
return null;
|
||
}
|
||
return getIntersectElements(context.view, maskBBox);
|
||
}
|
||
/**
|
||
* @ignore
|
||
*/
|
||
export function getSiblingMaskElements(context, sibling, tolerance) {
|
||
var maskBBox = getMaskBBox(context, tolerance);
|
||
// 如果 bbox 过小则不返回
|
||
if (!maskBBox) {
|
||
return null;
|
||
}
|
||
var view = context.view;
|
||
var start = getSiblingPoint(view, sibling, { x: maskBBox.x, y: maskBBox.y });
|
||
var end = getSiblingPoint(view, sibling, { x: maskBBox.maxX, y: maskBBox.maxY });
|
||
var box = {
|
||
minX: start.x,
|
||
minY: start.y,
|
||
maxX: end.x,
|
||
maxY: end.y
|
||
};
|
||
return getIntersectElements(sibling, box);
|
||
}
|
||
/**
|
||
* 获取所有的图表元素
|
||
* @param view View/Chart
|
||
* @ignore
|
||
*/
|
||
export function getElements(view) {
|
||
var geometries = view.geometries;
|
||
var rst = [];
|
||
each(geometries, function (geom) {
|
||
var elements = geom.elements;
|
||
rst = rst.concat(elements);
|
||
});
|
||
if (view.views && view.views.length) {
|
||
each(view.views, function (subView) {
|
||
rst = rst.concat(getElements(subView));
|
||
});
|
||
}
|
||
return rst;
|
||
}
|
||
/**
|
||
* 获取所有的图表元素
|
||
* @param view View/Chart
|
||
* @param field 字段名
|
||
* @param value 字段值
|
||
* @ignore
|
||
*/
|
||
export function getElementsByField(view, field, value) {
|
||
var elements = getElements(view);
|
||
return elements.filter(function (el) {
|
||
return getElementValue(el, field) === value;
|
||
});
|
||
}
|
||
/**
|
||
* 根据状态名获取图表元素
|
||
* @param view View/Chart
|
||
* @param stateName 状态名
|
||
* @ignore
|
||
*/
|
||
export function getElementsByState(view, stateName) {
|
||
var geometries = view.geometries;
|
||
var rst = [];
|
||
each(geometries, function (geom) {
|
||
var elements = geom.getElementsBy(function (el) { return el.hasState(stateName); });
|
||
rst = rst.concat(elements);
|
||
});
|
||
return rst;
|
||
}
|
||
/**
|
||
* 获取图表元素对应字段的值
|
||
* @param element 图表元素
|
||
* @param field 字段名
|
||
* @ignore
|
||
*/
|
||
export function getElementValue(element, field) {
|
||
var model = element.getModel();
|
||
var record = model.data;
|
||
var value;
|
||
if (isArray(record)) {
|
||
value = record[0][field];
|
||
}
|
||
else {
|
||
value = record[field];
|
||
}
|
||
return value;
|
||
}
|
||
/**
|
||
* 两个包围盒是否相交
|
||
* @param box1 包围盒1
|
||
* @param box2 包围盒2
|
||
* @ignore
|
||
*/
|
||
export function intersectRect(box1, box2) {
|
||
return !(box2.minX > box1.maxX || box2.maxX < box1.minX || box2.minY > box1.maxY || box2.maxY < box1.minY);
|
||
}
|
||
/**
|
||
* 获取包围盒内的图表元素
|
||
* @param view View/Chart
|
||
* @param box 包围盒
|
||
* @ignore
|
||
*/
|
||
export function getIntersectElements(view, box) {
|
||
var elements = getElements(view);
|
||
var rst = [];
|
||
each(elements, function (el) {
|
||
var shape = el.shape;
|
||
var shapeBBox = shape.getCanvasBBox();
|
||
if (intersectRect(box, shapeBBox)) {
|
||
rst.push(el);
|
||
}
|
||
});
|
||
return rst;
|
||
}
|
||
function pathToPoints(path) {
|
||
var points = [];
|
||
each(path, function (seg) {
|
||
var command = seg[0];
|
||
if (command !== 'A') {
|
||
for (var i = 1; i < seg.length; i = i + 2) {
|
||
points.push([seg[i], seg[i + 1]]);
|
||
}
|
||
}
|
||
else {
|
||
var length_1 = seg.length;
|
||
points.push([seg[length_1 - 2], seg[length_1 - 1]]);
|
||
}
|
||
});
|
||
return points;
|
||
}
|
||
/**
|
||
* 获取包围盒内的图表元素
|
||
* @param view View/Chart
|
||
* @param path 路径
|
||
* @ignore
|
||
*/
|
||
export function getElementsByPath(view, path) {
|
||
var elements = getElements(view);
|
||
var points = pathToPoints(path);
|
||
var rst = elements.filter(function (el) {
|
||
var shape = el.shape;
|
||
var shapePoints;
|
||
if (shape.get('type') === 'path') {
|
||
shapePoints = pathToPoints(shape.attr('path'));
|
||
}
|
||
else {
|
||
var shapeBBox = shape.getCanvasBBox();
|
||
shapePoints = toPoints(shapeBBox);
|
||
}
|
||
return isPolygonsIntersect(points, shapePoints);
|
||
});
|
||
return rst;
|
||
}
|
||
/**
|
||
* 获取当前 View 的所有组件
|
||
* @param view View/Chart
|
||
* @ignore
|
||
*/
|
||
export function getComponents(view) {
|
||
return view.getComponents().map(function (co) { return co.component; });
|
||
}
|
||
/** @ignore */
|
||
export function distance(p1, p2) {
|
||
var dx = p2.x - p1.x;
|
||
var dy = p2.y - p1.y;
|
||
return Math.sqrt(dx * dx + dy * dy);
|
||
}
|
||
/** @ignore */
|
||
export function getSpline(points, z) {
|
||
if (points.length <= 2) {
|
||
return getLinePath(points, false);
|
||
}
|
||
var first = points[0];
|
||
var arr = [];
|
||
each(points, function (point) {
|
||
arr.push(point.x);
|
||
arr.push(point.y);
|
||
});
|
||
var path = catmullRom2bezier(arr, z, null);
|
||
path.unshift(['M', first.x, first.y]);
|
||
return path;
|
||
}
|
||
/**
|
||
* 检测点是否在包围盒内
|
||
* @param box 包围盒
|
||
* @param point 点
|
||
* @ignore
|
||
*/
|
||
export function isInBox(box, point) {
|
||
return box.x <= point.x && box.maxX >= point.x && box.y <= point.y && box.maxY > point.y;
|
||
}
|
||
/**
|
||
* 获取同 view 同一级的 views
|
||
* @param view 当前 view
|
||
* @returns 同一级的 views
|
||
* @ignore
|
||
*/
|
||
export function getSilbings(view) {
|
||
var parent = view.parent;
|
||
var siblings = null;
|
||
if (parent) {
|
||
siblings = parent.views.filter(function (sub) { return sub !== view; });
|
||
}
|
||
return siblings;
|
||
}
|
||
function point2Normalize(view, point) {
|
||
var coord = view.getCoordinate();
|
||
return coord.invert(point);
|
||
}
|
||
/**
|
||
* 将 view 上的一点转换成另一个 view 的点
|
||
* @param view 当前的 view
|
||
* @param sibling 同一层级的 view
|
||
* @param point 指定点
|
||
* @ignore
|
||
*/
|
||
export function getSiblingPoint(view, sibling, point) {
|
||
var normalPoint = point2Normalize(view, point);
|
||
return sibling.getCoordinate().convert(normalPoint);
|
||
}
|
||
/**
|
||
* 是否在记录中,临时因为所有的 view 中的数据不是引用,而使用的方法
|
||
* 不同 view 上对数据的引用不相等,导致无法直接用 includes
|
||
* 假设 x, y 值相等时是同一条数据,这个假设不完全正确,而改成 isEqual 则成本太高
|
||
* 后面改成同一个引用时可以修改回来
|
||
* @param records
|
||
* @param record
|
||
* @param xFiled
|
||
* @param yField
|
||
* @returns
|
||
* @ignore
|
||
*/
|
||
export function isInRecords(records, record, xFiled, yField) {
|
||
var isIn = false;
|
||
each(records, function (r) {
|
||
if (r[xFiled] === record[xFiled] && r[yField] === record[yField]) {
|
||
isIn = true;
|
||
return false;
|
||
}
|
||
});
|
||
return isIn;
|
||
}
|
||
// 级联获取 field 对应的 scale,如果 view 上没有,遍历子 view
|
||
export function getScaleByField(view, field) {
|
||
var scale = view.getScaleByField(field);
|
||
if (!scale && view.views) {
|
||
each(view.views, function (subView) {
|
||
scale = getScaleByField(subView, field);
|
||
if (scale) {
|
||
return false; // 终止循环
|
||
}
|
||
});
|
||
}
|
||
return scale;
|
||
}
|
||
//# sourceMappingURL=util.js.map |