devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
480 lines (478 loc) • 20.4 kB
JavaScript
/**
* DevExtreme (cjs/viz/series/points/range_symbol_point.js)
* Version: 24.2.6
* Build date: Mon Mar 17 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
exports.default = void 0;
var _iterator = require("../../../core/utils/iterator");
var _extend2 = require("../../../core/utils/extend");
var _common = require("../../../core/utils/common");
var _label = require("./label");
var _symbol_point = _interopRequireDefault(require("./symbol_point"));
var _type = require("../../../core/utils/type");
function _interopRequireDefault(e) {
return e && e.__esModule ? e : {
default: e
}
}
const _extend = _extend2.extend;
const _math = Math;
const _abs = _math.abs;
const _min = _math.min;
const _max = _math.max;
const _round = _math.round;
const DEFAULT_IMAGE_WIDTH = 20;
const DEFAULT_IMAGE_HEIGHT = 20;
var _default = exports.default = _extend({}, _symbol_point.default, {
deleteLabel: function() {
this._topLabel.dispose();
this._topLabel = null;
this._bottomLabel.dispose();
this._bottomLabel = null
},
hideMarker: function(type) {
const graphic = this.graphic;
const marker = graphic && graphic[type + "Marker"];
const label = this["_" + type + "Label"];
if (marker && "hidden" !== marker.attr("visibility")) {
marker.attr({
visibility: "hidden"
})
}
label.draw(false)
},
setInvisibility: function() {
this.hideMarker("top");
this.hideMarker("bottom")
},
clearVisibility: function() {
const graphic = this.graphic;
const topMarker = graphic && graphic.topMarker;
const bottomMarker = graphic && graphic.bottomMarker;
if (topMarker && topMarker.attr("visibility")) {
topMarker.attr({
visibility: null
})
}
if (bottomMarker && bottomMarker.attr("visibility")) {
bottomMarker.attr({
visibility: null
})
}
},
clearMarker: function() {
const graphic = this.graphic;
const topMarker = graphic && graphic.topMarker;
const bottomMarker = graphic && graphic.bottomMarker;
const emptySettings = this._emptySettings;
topMarker && topMarker.attr(emptySettings);
bottomMarker && bottomMarker.attr(emptySettings)
},
_getLabelPosition: function(markerType) {
let position;
const labelsInside = "inside" === this._options.label.position;
if (!this._options.rotated) {
position = "top" === markerType ^ labelsInside ? "top" : "bottom"
} else {
position = "top" === markerType ^ labelsInside ? "right" : "left"
}
return position
},
_getLabelMinFormatObject: function() {
return {
index: 0,
argument: this.initialArgument,
value: this.initialMinValue,
seriesName: this.series.name,
originalValue: this.originalMinValue,
originalArgument: this.originalArgument,
point: this
}
},
_updateLabelData: function() {
const maxFormatObject = this._getLabelFormatObject();
maxFormatObject.index = 1;
this._topLabel.setData(maxFormatObject);
this._bottomLabel.setData(this._getLabelMinFormatObject())
},
_updateLabelOptions: function() {
const options = this._options.label;
(!this._topLabel || !this._bottomLabel) && this._createLabel();
this._topLabel.setOptions(options);
this._bottomLabel.setOptions(options)
},
_createLabel: function() {
const options = {
renderer: this.series._renderer,
labelsGroup: this.series._labelsGroup,
point: this
};
this._topLabel = new _label.Label(options);
this._bottomLabel = new _label.Label(options)
},
_getGraphicBBox: function(location) {
const options = this._options;
const images = this._getImage(options.image);
const image = "top" === location ? this._checkImage(images.top) : this._checkImage(images.bottom);
let bBox;
const coord = this._getPositionFromLocation(location);
if (options.visible) {
bBox = image ? this._getImageBBox(coord.x, coord.y) : this._getSymbolBBox(coord.x, coord.y, options.styles.normal.r)
} else {
bBox = {
x: coord.x,
y: coord.y,
width: 0,
height: 0
}
}
return bBox
},
_getPositionFromLocation: function(location) {
let x;
let y;
const isTop = "top" === location;
if (!this._options.rotated) {
x = this.x;
y = isTop ? _min(this.y, this.minY) : _max(this.y, this.minY)
} else {
x = isTop ? _max(this.x, this.minX) : _min(this.x, this.minX);
y = this.y
}
return {
x: x,
y: y
}
},
_checkOverlay: function(bottomCoord, topCoord, topValue) {
return bottomCoord < topCoord + topValue
},
_getOverlayCorrections: function(topCoords, bottomCoords) {
const rotated = this._options.rotated;
const coordSelector = !rotated ? "y" : "x";
const valueSelector = !rotated ? "height" : "width";
const visibleArea = this.series.getValueAxis().getVisibleArea();
const minBound = visibleArea[0];
const maxBound = visibleArea[1];
let delta = _round((topCoords[coordSelector] + topCoords[valueSelector] - bottomCoords[coordSelector]) / 2);
let coord1 = topCoords[coordSelector] - delta;
let coord2 = bottomCoords[coordSelector] + delta;
if (coord1 < minBound) {
delta = minBound - coord1;
coord1 += delta;
coord2 += delta
} else if (coord2 + bottomCoords[valueSelector] > maxBound) {
delta = maxBound - coord2 - bottomCoords[valueSelector];
coord1 += delta;
coord2 += delta
}
return {
coord1: coord1,
coord2: coord2
}
},
_checkLabelsOverlay: function(topLocation) {
const that = this;
const topCoords = that._topLabel.getBoundingRect();
const bottomCoords = that._bottomLabel.getBoundingRect();
let corrections = {};
if (!that._options.rotated) {
if ("top" === topLocation) {
if (this._checkOverlay(bottomCoords.y, topCoords.y, topCoords.height)) {
corrections = this._getOverlayCorrections(topCoords, bottomCoords);
that._topLabel.shift(topCoords.x, corrections.coord1);
that._bottomLabel.shift(bottomCoords.x, corrections.coord2)
}
} else if (this._checkOverlay(topCoords.y, bottomCoords.y, bottomCoords.height)) {
corrections = this._getOverlayCorrections(bottomCoords, topCoords);
that._topLabel.shift(topCoords.x, corrections.coord2);
that._bottomLabel.shift(bottomCoords.x, corrections.coord1)
}
} else if ("top" === topLocation) {
if (this._checkOverlay(topCoords.x, bottomCoords.x, bottomCoords.width)) {
corrections = this._getOverlayCorrections(bottomCoords, topCoords);
that._topLabel.shift(corrections.coord2, topCoords.y);
that._bottomLabel.shift(corrections.coord1, bottomCoords.y)
}
} else if (this._checkOverlay(bottomCoords.x, topCoords.x, topCoords.width)) {
corrections = this._getOverlayCorrections(topCoords, bottomCoords);
that._topLabel.shift(corrections.coord1, topCoords.y);
that._bottomLabel.shift(corrections.coord2, bottomCoords.y)
}
},
_drawLabel: function() {
const that = this;
const labels = [];
const notInverted = that._options.rotated ? that.x >= that.minX : that.y < that.minY;
const customVisibility = that._getCustomLabelVisibility();
const topLabel = that._topLabel;
const bottomLabel = that._bottomLabel;
topLabel.pointPosition = notInverted ? "top" : "bottom";
bottomLabel.pointPosition = notInverted ? "bottom" : "top";
if ((that.series.getLabelVisibility() || customVisibility) && that.hasValue() && false !== customVisibility) {
false !== that.visibleTopMarker && labels.push(topLabel);
false !== that.visibleBottomMarker && labels.push(bottomLabel);
(0, _iterator.each)(labels, (function(_, label) {
label.draw(true)
}));
that._checkLabelsOverlay(that._topLabel.pointPosition)
} else {
topLabel.draw(false);
bottomLabel.draw(false)
}
},
_getImage: function(imageOption) {
const image = {};
if ((0, _type.isDefined)(imageOption)) {
if ("string" === typeof imageOption) {
image.top = image.bottom = imageOption
} else {
image.top = {
url: "string" === typeof imageOption.url ? imageOption.url : imageOption.url && imageOption.url.rangeMaxPoint,
width: "number" === typeof imageOption.width ? imageOption.width : imageOption.width && imageOption.width.rangeMaxPoint,
height: "number" === typeof imageOption.height ? imageOption.height : imageOption.height && imageOption.height.rangeMaxPoint
};
image.bottom = {
url: "string" === typeof imageOption.url ? imageOption.url : imageOption.url && imageOption.url.rangeMinPoint,
width: "number" === typeof imageOption.width ? imageOption.width : imageOption.width && imageOption.width.rangeMinPoint,
height: "number" === typeof imageOption.height ? imageOption.height : imageOption.height && imageOption.height.rangeMinPoint
}
}
}
return image
},
_checkSymbol: function(oldOptions, newOptions) {
const oldSymbol = oldOptions.symbol;
const newSymbol = newOptions.symbol;
const symbolChanged = "circle" === oldSymbol && "circle" !== newSymbol || "circle" !== oldSymbol && "circle" === newSymbol;
const oldImages = this._getImage(oldOptions.image);
const newImages = this._getImage(newOptions.image);
const topImageChanged = this._checkImage(oldImages.top) !== this._checkImage(newImages.top);
const bottomImageChanged = this._checkImage(oldImages.bottom) !== this._checkImage(newImages.bottom);
return symbolChanged || topImageChanged || bottomImageChanged
},
_getSettingsForTwoMarkers: function(style) {
const options = this._options;
const settings = {};
const x = options.rotated ? _min(this.x, this.minX) : this.x;
const y = options.rotated ? this.y : _min(this.y, this.minY);
const radius = style.r;
const points = this._populatePointShape(options.symbol, radius);
settings.top = _extend({
translateX: x + this.width,
translateY: y,
r: radius
}, style);
settings.bottom = _extend({
translateX: x,
translateY: y + this.height,
r: radius
}, style);
if (points) {
settings.top.points = settings.bottom.points = points
}
return settings
},
_hasGraphic: function() {
return this.graphic && this.graphic.topMarker && this.graphic.bottomMarker
},
_drawOneMarker: function(renderer, markerType, imageSettings, settings) {
const that = this;
const graphic = that.graphic;
if (graphic[markerType]) {
that._updateOneMarker(markerType, settings)
} else {
graphic[markerType] = that._createMarker(renderer, graphic, imageSettings, settings)
}
},
_drawMarker: function(renderer, group, animationEnabled, firstDrawing, style) {
const that = this;
const settings = that._getSettingsForTwoMarkers(style || that._getStyle());
const image = that._getImage(that._options.image);
if (that._checkImage(image.top)) {
settings.top = that._getImageSettings(settings.top, image.top)
}
if (that._checkImage(image.bottom)) {
settings.bottom = that._getImageSettings(settings.bottom, image.bottom)
}
that.graphic = that.graphic || renderer.g().append(group);
that.visibleTopMarker && that._drawOneMarker(renderer, "topMarker", image.top, settings.top);
that.visibleBottomMarker && that._drawOneMarker(renderer, "bottomMarker", image.bottom, settings.bottom)
},
_getSettingsForTracker: function(radius) {
const rotated = this._options.rotated;
return {
translateX: rotated ? _min(this.x, this.minX) - radius : this.x - radius,
translateY: rotated ? this.y - radius : _min(this.y, this.minY) - radius,
width: this.width + 2 * radius,
height: this.height + 2 * radius
}
},
isInVisibleArea: function() {
const rotated = this._options.rotated;
const argument = !rotated ? this.x : this.y;
const maxValue = !rotated ? _max(this.minY, this.y) : _max(this.minX, this.x);
const minValue = !rotated ? _min(this.minY, this.y) : _min(this.minX, this.x);
let tmp;
let visibleTopMarker;
let visibleBottomMarker;
let visibleRangeArea = true;
const visibleArgArea = this.series.getArgumentAxis().getVisibleArea();
const visibleValArea = this.series.getValueAxis().getVisibleArea();
const notVisibleByArg = visibleArgArea[1] < argument || visibleArgArea[0] > argument;
const notVisibleByVal = visibleValArea[0] > minValue && visibleValArea[0] > maxValue || visibleValArea[1] < minValue && visibleValArea[1] < maxValue;
if (notVisibleByArg || notVisibleByVal) {
visibleTopMarker = visibleBottomMarker = visibleRangeArea = false
} else {
visibleTopMarker = visibleValArea[0] <= minValue && visibleValArea[1] > minValue;
visibleBottomMarker = visibleValArea[0] < maxValue && visibleValArea[1] >= maxValue;
if (rotated) {
tmp = visibleTopMarker;
visibleTopMarker = visibleBottomMarker;
visibleBottomMarker = tmp
}
}
this.visibleTopMarker = visibleTopMarker;
this.visibleBottomMarker = visibleBottomMarker;
return visibleRangeArea
},
getTooltipParams: function() {
const that = this;
let x;
let y;
const rotated = that._options.rotated;
const minValue = !rotated ? _min(that.y, that.minY) : _min(that.x, that.minX);
const side = !rotated ? "height" : "width";
const visibleArea = that._getVisibleArea();
const minVisible = rotated ? visibleArea.minX : visibleArea.minY;
const maxVisible = rotated ? visibleArea.maxX : visibleArea.maxY;
const min = _max(minVisible, minValue);
const max = _min(maxVisible, minValue + that[side]);
if (!rotated) {
x = that.x;
y = min + (max - min) / 2
} else {
y = that.y;
x = min + (max - min) / 2
}
return {
x: x,
y: y,
offset: 0
}
},
_translate: function() {
const rotated = this._options.rotated;
_symbol_point.default._translate.call(this);
this.height = rotated ? 0 : _abs(this.minY - this.y);
this.width = rotated ? _abs(this.x - this.minX) : 0
},
hasCoords: function() {
return _symbol_point.default.hasCoords.call(this) && !(null === this.minX || null === this.minY)
},
_updateData: function(data) {
_symbol_point.default._updateData.call(this, data);
this.minValue = this.initialMinValue = this.originalMinValue = data.minValue
},
_getImageSettings: function(settings, image) {
return {
href: image.url || image.toString(),
width: image.width || 20,
height: image.height || 20,
translateX: settings.translateX,
translateY: settings.translateY
}
},
getCrosshairData: function(x, y) {
const rotated = this._options.rotated;
const minX = this.minX;
const minY = this.minY;
const vx = this.vx;
const vy = this.vy;
const value = this.value;
const minValue = this.minValue;
const argument = this.argument;
const coords = {
axis: this.series.axis,
x: vx,
y: vy,
yValue: value,
xValue: argument
};
if (rotated) {
coords.yValue = argument;
if (_abs(vx - x) < _abs(minX - x)) {
coords.xValue = value
} else {
coords.x = minX;
coords.xValue = minValue
}
} else if (_abs(vy - y) >= _abs(minY - y)) {
coords.y = minY;
coords.yValue = minValue
}
return coords
},
_updateOneMarker: function(markerType, settings) {
this.graphic && this.graphic[markerType] && this.graphic[markerType].attr(settings)
},
_updateMarker: function(animationEnabled, style) {
this._drawMarker(void 0, void 0, false, false, style)
},
_getFormatObject: function(tooltip) {
const initialMinValue = this.initialMinValue;
const initialValue = this.initialValue;
const initialArgument = this.initialArgument;
const minValue = tooltip.formatValue(initialMinValue);
const value = tooltip.formatValue(initialValue);
return {
argument: initialArgument,
argumentText: tooltip.formatValue(initialArgument, "argument"),
valueText: minValue + " - " + value,
rangeValue1Text: minValue,
rangeValue2Text: value,
rangeValue1: initialMinValue,
rangeValue2: initialValue,
seriesName: this.series.name,
point: this,
originalMinValue: this.originalMinValue,
originalValue: this.originalValue,
originalArgument: this.originalArgument
}
},
getLabel: function() {
return [this._topLabel, this._bottomLabel]
},
getLabels: function() {
return [this._topLabel, this._bottomLabel]
},
getBoundingRect: _common.noop,
coordsIn: function(x, y) {
const trackerRadius = this._storeTrackerR();
const xCond = x >= this.x - trackerRadius && x <= this.x + trackerRadius;
const yCond = y >= this.y - trackerRadius && y <= this.y + trackerRadius;
if (this._options.rotated) {
return yCond && (xCond || x >= this.minX - trackerRadius && x <= this.minX + trackerRadius)
} else {
return xCond && (yCond || y >= this.minY - trackerRadius && y <= this.minY + trackerRadius)
}
},
getMaxValue: function() {
if ("discrete" !== this.series.valueAxisType) {
return this.minValue > this.value ? this.minValue : this.value
}
return this.value
},
getMinValue: function() {
if ("discrete" !== this.series.valueAxisType) {
return this.minValue < this.value ? this.minValue : this.value
}
return this.minValue
}
});
module.exports = exports.default;
module.exports.default = exports.default;