@visactor/vgrammar-core
Version:
VGrammar is a visual grammar library
284 lines (257 loc) • 16.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.Crosshair = exports.generatePolygonCrosshairAttributes = exports.generateCircleCrosshairAttributes = exports.generateSectorCrosshairAttributes = exports.generateRingCrosshairAttributes = exports.generateRectCrosshairAttributes = exports.generateLineCrosshairAttributes = void 0;
const vutils_1 = require("@visactor/vutils"), vrender_components_1 = require("@visactor/vrender-components"), base_1 = require("./base"), enums_1 = require("../graph/enums"), vscale_1 = require("@visactor/vscale"), util_1 = require("../parse/util"), computeCrosshairStartEnd = (point, scale, type, groupSize, config, offset = 0) => {
var _a, _b;
const start = {
x: 0,
y: 0
}, end = {
x: 0,
y: 0
}, radius = "angle" === type ? null !== (_a = null == config ? void 0 : config.radius) && void 0 !== _a ? _a : Math.min(groupSize.width, groupSize.height) / 2 : null, center = "angle" === type ? null !== (_b = null == config ? void 0 : config.center) && void 0 !== _b ? _b : {
x: groupSize.width / 2,
y: groupSize.height / 2
} : null;
let current = 0;
if ((0, vscale_1.isDiscrete)(scale.type)) {
if ("x" === type) current = scale.scale(scale.invert(point.x)); else if ("y" === type) current = scale.scale(scale.invert(point.y)); else if ("angle" === type) {
const angle = (0, vutils_1.clampRadian)((0, vutils_1.getAngleByPoint)(center, point) + 2 * Math.PI);
current = scale.scale(scale.invert(angle));
}
} else (0, vscale_1.isContinuous)(scale.type) && ("x" === type ? current = point.x : "y" === type ? current = point.y : "angle" === type && (current = (0,
vutils_1.getAngleByPoint)(center, point)));
switch (current += offset, type) {
case "x":
start.x = current, start.y = 0, end.x = current, end.y = groupSize.height;
break;
case "y":
start.x = 0, start.y = current, end.x = groupSize.width, end.y = current;
break;
case "angle":
start.x = center.x, start.y = center.y, end.x = center.x + radius * Math.cos(current),
end.y = center.y + radius * Math.sin(current);
}
return {
start: start,
end: end
};
}, computeRadiusOfTangential = (point, scale, type, groupSize, config, addition) => {
var _a, _b, _c;
const center = null !== (_b = null !== (_a = null == addition ? void 0 : addition.center) && void 0 !== _a ? _a : null == config ? void 0 : config.center) && void 0 !== _b ? _b : {
x: groupSize.width / 2,
y: groupSize.height / 2
};
let currentRadius = 0;
if ((0, vscale_1.isDiscrete)(scale.type)) {
const offset = "band" === scale.type ? scale.bandwidth() / 2 : 0, radius = Math.sqrt((point.x - center.x) ** 2 + (point.y - center.y) ** 2);
currentRadius = scale.scale(scale.invert(radius)) + offset;
} else if ((0, vscale_1.isContinuous)(scale.type)) {
const maxRadius = null !== (_c = null == config ? void 0 : config.radius) && void 0 !== _c ? _c : Math.min(groupSize.width, groupSize.height) / 2;
currentRadius = Math.min(maxRadius, Math.sqrt((point.x - center.x) ** 2 + (point.y - center.y) ** 2));
}
return {
radius: currentRadius,
center: center
};
}, generateLineCrosshairAttributes = (point, scale, type, groupSize, config, theme, addition) => {
var _a, _b, _c;
const crosshairTheme = null === (_a = null == theme ? void 0 : theme.components) || void 0 === _a ? void 0 : _a.lineCrosshair, offset = "band" === scale.type ? scale.bandwidth() / 2 : 0, points = computeCrosshairStartEnd(point, scale, type, groupSize, {
radius: null !== (_b = null == addition ? void 0 : addition.radius) && void 0 !== _b ? _b : null == config ? void 0 : config.radius,
center: null !== (_c = null == addition ? void 0 : addition.center) && void 0 !== _c ? _c : null == config ? void 0 : config.center
}, offset);
return (0, vutils_1.merge)({}, crosshairTheme, points, null != addition ? addition : {});
};
exports.generateLineCrosshairAttributes = generateLineCrosshairAttributes;
const generateRectCrosshairAttributes = (point, scale, type, groupSize, config, theme, addition) => {
var _a, _b, _c;
const crosshairTheme = null === (_a = null == theme ? void 0 : theme.components) || void 0 === _a ? void 0 : _a.rectCrosshair, defaultSize = "band" === scale.type || "point" === scale.type ? scale.step() : void 0, customRectStyle = null == addition ? void 0 : addition.rectStyle, size = null != defaultSize ? defaultSize : "y" === type ? null !== (_b = null == customRectStyle ? void 0 : customRectStyle.width) && void 0 !== _b ? _b : crosshairTheme.rectStyle.width : null !== (_c = null == customRectStyle ? void 0 : customRectStyle.height) && void 0 !== _c ? _c : crosshairTheme.rectStyle.height, points = computeCrosshairStartEnd(point, scale, type, groupSize, config, "band" === scale.type ? 0 : -size / 2), rectStyle = {};
"x" === type ? rectStyle.width = size : rectStyle.height = size;
const attribute = (0, vutils_1.merge)({}, crosshairTheme, {
start: points.start,
end: points.end,
rectStyle: rectStyle
}, null != addition ? addition : {});
return "x" === type ? attribute.rectStyle.height = attribute.end.y - attribute.start.y : attribute.rectStyle.width = attribute.end.x - attribute.start.x,
attribute;
};
exports.generateRectCrosshairAttributes = generateRectCrosshairAttributes;
const generateRingCrosshairAttributes = (point, scale, type, groupSize, config, theme, addition) => {
var _a;
const crosshairTheme = null === (_a = null == theme ? void 0 : theme.components) || void 0 === _a ? void 0 : _a.circleCrosshair, {center: center, radius: radius} = computeRadiusOfTangential(point, scale, 0, groupSize, config, addition), startAngle = crosshairTheme.startAngle, endAngle = crosshairTheme.endAngle, deltaRadius = "band" === scale.type || "point" === scale.type ? scale.step() : 0;
return (0, vutils_1.merge)({}, crosshairTheme, {
center: center,
innerRadius: radius - deltaRadius / 2,
radius: radius + deltaRadius / 2,
startAngle: startAngle,
endAngle: endAngle
}, null != addition ? addition : {});
};
exports.generateRingCrosshairAttributes = generateRingCrosshairAttributes;
const generateSectorCrosshairAttributes = (point, scale, type, groupSize, config, theme, addition) => {
var _a, _b, _c, _d, _e;
const crosshairTheme = null === (_a = null == theme ? void 0 : theme.components) || void 0 === _a ? void 0 : _a.sectorCrosshair, radius = null !== (_c = null !== (_b = null == addition ? void 0 : addition.radius) && void 0 !== _b ? _b : null == config ? void 0 : config.radius) && void 0 !== _c ? _c : Math.min(groupSize.width, groupSize.height) / 2, center = null !== (_e = null !== (_d = null == addition ? void 0 : addition.center) && void 0 !== _d ? _d : null == config ? void 0 : config.center) && void 0 !== _e ? _e : {
x: groupSize.width / 2,
y: groupSize.height / 2
}, defaultAngle = crosshairTheme.endAngle - crosshairTheme.startAngle, angle = "band" === scale.type || "point" === scale.type ? scale.step() : defaultAngle;
let currentAngle = 0;
if ((0, vscale_1.isDiscrete)(scale.type)) {
const angle = (0, vutils_1.clampRadian)((0, vutils_1.getAngleByPoint)(center, point) + 2 * Math.PI);
currentAngle = scale.scale(scale.invert(angle)) + ("band" === scale.type ? scale.bandwidth() / 2 : 0);
} else (0, vscale_1.isContinuous)(scale.type) && (currentAngle = (0, vutils_1.getAngleByPoint)(center, point));
const startAngle = currentAngle - angle / 2, endAngle = currentAngle + angle / 2;
return (0, vutils_1.merge)({}, crosshairTheme, {
center: center,
radius: radius,
startAngle: startAngle,
endAngle: endAngle
}, null != addition ? addition : {});
};
exports.generateSectorCrosshairAttributes = generateSectorCrosshairAttributes;
const generateCircleCrosshairAttributes = (point, scale, type, groupSize, config, theme, addition) => {
var _a;
const crosshairTheme = null === (_a = null == theme ? void 0 : theme.components) || void 0 === _a ? void 0 : _a.circleCrosshair, {center: center, radius: radius} = computeRadiusOfTangential(point, scale, 0, groupSize, config, addition), startAngle = crosshairTheme.startAngle, endAngle = crosshairTheme.endAngle;
return (0, vutils_1.merge)({}, crosshairTheme, {
center: center,
radius: radius,
startAngle: startAngle,
endAngle: endAngle
}, null != addition ? addition : {});
};
exports.generateCircleCrosshairAttributes = generateCircleCrosshairAttributes;
const generatePolygonCrosshairAttributes = (point, scale, type, groupSize, config, theme, addition) => {
var _a;
const crosshairTheme = null === (_a = null == theme ? void 0 : theme.components) || void 0 === _a ? void 0 : _a.circleCrosshair, {center: center, radius: radius} = computeRadiusOfTangential(point, scale, 0, groupSize, config, addition), startAngle = crosshairTheme.startAngle, endAngle = crosshairTheme.endAngle;
return (0, vutils_1.merge)({}, crosshairTheme, {
center: center,
radius: radius,
startAngle: startAngle,
endAngle: endAngle
}, null != addition ? addition : {});
};
exports.generatePolygonCrosshairAttributes = generatePolygonCrosshairAttributes;
class Crosshair extends base_1.BaseInteraction {
constructor(view, options) {
var _a, _b;
super(view, options), this.type = Crosshair.type, this.handleCrosshairShow = event => {
var _a;
if (!this._crosshairComponent) return;
const groupGraphicItem = this._container.getGroupGraphicItem(), point = {
x: 0,
y: 0
}, globalTransMatrix = groupGraphicItem.globalTransMatrix, containerPoint = {
x: globalTransMatrix.e,
y: globalTransMatrix.f
};
if (globalTransMatrix.transformPoint(event.canvas, point), point.x < 0 || point.x > groupGraphicItem.attribute.width || point.y < 0 || point.y > groupGraphicItem.attribute.height) return void this._crosshairComponent.hideAll();
const crosshairType = null !== (_a = this.options.crosshairType) && void 0 !== _a ? _a : "x", groupSize = {
width: groupGraphicItem.attribute.width,
height: groupGraphicItem.attribute.height
}, scale = ((0, vutils_1.isString)(this.options.scale) ? this.view.getScaleById(this.options.scale) : this.options.scale).getScale(), config = {
center: this.options.center,
radius: this.options.radius
}, theme = this.view.getCurrentTheme(), addition = (0, util_1.invokeFunctionType)(this.options.attributes, this.parameters(), {}, {});
let attributes = {};
switch (this.getCrosshairComponentType()) {
case enums_1.CrosshairEnum.lineCrosshair:
attributes = (0, exports.generateLineCrosshairAttributes)(point, scale, crosshairType, groupSize, config, theme, addition);
break;
case enums_1.CrosshairEnum.rectCrosshair:
attributes = (0, exports.generateRectCrosshairAttributes)(point, scale, crosshairType, groupSize, config, theme, addition);
break;
case enums_1.CrosshairEnum.sectorCrosshair:
attributes = (0, exports.generateSectorCrosshairAttributes)(point, scale, crosshairType, groupSize, config, theme, addition);
break;
case enums_1.CrosshairEnum.circleCrosshair:
attributes = (0, exports.generateCircleCrosshairAttributes)(point, scale, crosshairType, groupSize, config, theme, addition);
break;
case enums_1.CrosshairEnum.polygonCrosshair:
attributes = (0, exports.generatePolygonCrosshairAttributes)(point, scale, crosshairType, groupSize, config, theme, addition);
break;
case enums_1.CrosshairEnum.ringCrosshair:
attributes = (0, exports.generateRingCrosshairAttributes)(point, scale, crosshairType, groupSize, config, theme, addition);
}
this.getCrosshairComponentType() !== enums_1.CrosshairEnum.circleCrosshair && (attributes.x = containerPoint.x,
attributes.y = containerPoint.y), this._crosshairComponent.showAll(), this._crosshairComponent.setAttributes(attributes);
}, this.handleCrosshairHide = () => {
this._crosshairComponent && this._crosshairComponent.hideAll();
}, this.options = Object.assign({}, Crosshair.defaultOptions, options), this._container = null !== (_b = null === (_a = view.getMarksBySelector(this.options.container)) || void 0 === _a ? void 0 : _a[0]) && void 0 !== _b ? _b : view.rootMark;
}
getEvents() {
return [ {
type: this.options.trigger,
handler: this.handleCrosshairShow
}, {
type: this.options.triggerOff,
handler: this.handleCrosshairHide
} ];
}
getCrosshairComponentType() {
var _a, _b;
if (this._crosshairComponentType) return this._crosshairComponentType;
const shape = null !== (_a = this.options.crosshairShape) && void 0 !== _a ? _a : "line", type = null !== (_b = this.options.crosshairType) && void 0 !== _b ? _b : "x";
return this._crosshairComponentType = "rect" === shape ? "angle" === type ? enums_1.CrosshairEnum.sectorCrosshair : "radius" === type ? enums_1.CrosshairEnum.ringCrosshair : "radius-polygon" === type ? enums_1.CrosshairEnum.polygonCrosshair : enums_1.CrosshairEnum.rectCrosshair : "radius" === type ? enums_1.CrosshairEnum.circleCrosshair : "radius-polygon" === type ? enums_1.CrosshairEnum.polygonCrosshair : enums_1.CrosshairEnum.lineCrosshair,
this._crosshairComponentType;
}
getDefaultCrosshairAttribute() {
var _a;
const type = null !== (_a = this.options.crosshairType) && void 0 !== _a ? _a : "x";
return "radius" === type || "radius-polygon" === type ? {
center: {
x: 0,
y: 0
},
zIndex: -1
} : {
start: {
x: 0,
y: 0
},
end: {
x: 0,
y: 0
},
zIndex: -1
};
}
bind() {
super.bind();
const stage = this.view.renderer.stage();
if (!this._crosshairComponent && stage) {
switch (this.getCrosshairComponentType()) {
case enums_1.CrosshairEnum.lineCrosshair:
this._crosshairComponent = new vrender_components_1.LineCrosshair(this.getDefaultCrosshairAttribute());
break;
case enums_1.CrosshairEnum.rectCrosshair:
this._crosshairComponent = new vrender_components_1.RectCrosshair(this.getDefaultCrosshairAttribute());
break;
case enums_1.CrosshairEnum.sectorCrosshair:
this._crosshairComponent = new vrender_components_1.SectorCrosshair(this.getDefaultCrosshairAttribute());
break;
case enums_1.CrosshairEnum.circleCrosshair:
this._crosshairComponent = new vrender_components_1.CircleCrosshair(this.getDefaultCrosshairAttribute());
break;
case enums_1.CrosshairEnum.polygonCrosshair:
this._crosshairComponent = new vrender_components_1.PolygonCrosshair(this.getDefaultCrosshairAttribute());
break;
case enums_1.CrosshairEnum.ringCrosshair:
this._crosshairComponent = new vrender_components_1.SectorCrosshair(this.getDefaultCrosshairAttribute());
}
stage.defaultLayer.appendChild(this._crosshairComponent);
}
}
unbind() {
super.unbind();
const stage = this.view.renderer.stage();
this._crosshairComponent && stage && (stage.defaultLayer.removeChild(this._crosshairComponent),
this._crosshairComponent.release(), this._crosshairComponent = null);
}
}
exports.Crosshair = Crosshair, Crosshair.type = "crosshair", Crosshair.defaultOptions = {
trigger: "pointermove",
triggerOff: "pointerleave",
crosshairType: "x",
crosshairShape: "line"
};
//# sourceMappingURL=crosshair.js.map