devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
287 lines (249 loc) • 11.9 kB
JavaScript
var _isFinite = isFinite,
registerComponent = require("../../core/component_registrator"),
objectUtils = require("../../core/utils/object"),
extend = require("../../core/utils/extend").extend,
each = require("../../core/utils/iterator").each,
dxBaseGauge = require("./base_gauge").dxBaseGauge,
dxGauge = require("./common").dxGauge,
vizUtils = require("../core/utils"),
_normalizeAngle = vizUtils.normalizeAngle,
_getCosAndSin = vizUtils.getCosAndSin,
circularIndicatorsModule = require("./circular_indicators"),
createIndicatorCreator = require("./common").createIndicatorCreator,
CircularRangeContainer = require("./circular_range_container"),
ThemeManager = require("./theme_manager"),
_abs = Math.abs,
_max = Math.max,
_min = Math.min,
_round = Math.round,
_each = each,
PI = Math.PI;
function getSides(startAngle, endAngle) {
var startCosSin = _getCosAndSin(startAngle),
endCosSin = _getCosAndSin(endAngle),
startCos = startCosSin.cos,
startSin = startCosSin.sin,
endCos = endCosSin.cos,
endSin = endCosSin.sin;
return {
left: startSin <= 0 && endSin >= 0 || startSin <= 0 && endSin <= 0 && startCos <= endCos || startSin >= 0 && endSin >= 0 && startCos >= endCos ? -1 : _min(startCos, endCos, 0),
right: startSin >= 0 && endSin <= 0 || startSin >= 0 && endSin >= 0 && startCos >= endCos || startSin <= 0 && endSin <= 0 && startCos <= endCos ? 1 : _max(startCos, endCos, 0),
up: startCos <= 0 && endCos >= 0 || startCos <= 0 && endCos <= 0 && startSin >= endSin || startCos >= 0 && endCos >= 0 && startSin <= endSin ? -1 : -_max(startSin, endSin, 0),
down: startCos >= 0 && endCos <= 0 || startCos >= 0 && endCos >= 0 && startSin <= endSin || startCos <= 0 && endCos <= 0 && startSin >= endSin ? 1 : -_min(startSin, endSin, 0)
};
}
var dxCircularGauge = dxGauge.inherit({
_rootClass: "dxg-circular-gauge",
_factoryMethods: {
rangeContainer: 'createCircularRangeContainer',
indicator: 'createCircularIndicator'
},
_gridSpacingFactor: 17,
_scaleTypes: {
type: "polarAxes",
drawingType: "circular"
},
_updateScaleTickIndent: function _updateScaleTickIndent(scaleOptions) {
var indentFromTick = scaleOptions.label.indentFromTick,
length = scaleOptions.tick.length,
textParams = this._scale.measureLabels(extend({}, this._canvas)),
tickCorrection = length;
if (scaleOptions.orientation === "inside") {
tickCorrection = 0;
} else if (scaleOptions.orientation === "center") {
tickCorrection = 0.5 * length;
}
scaleOptions.label.indentFromAxis = indentFromTick >= 0 ? indentFromTick + tickCorrection : indentFromTick - tickCorrection - _max(textParams.width, textParams.height);
this._scale.updateOptions(scaleOptions);
},
_setupCodomain: function _setupCodomain() {
var that = this,
geometry = that.option("geometry") || {},
startAngle = geometry.startAngle,
endAngle = geometry.endAngle,
sides;
startAngle = _isFinite(startAngle) ? _normalizeAngle(startAngle) : 225;
endAngle = _isFinite(endAngle) ? _normalizeAngle(endAngle) : -45;
if (_abs(startAngle - endAngle) < 1) {
endAngle -= 360;
sides = { left: -1, up: -1, right: 1, down: 1 };
} else {
startAngle < endAngle && (endAngle -= 360);
sides = getSides(startAngle, endAngle);
}
that._area = {
x: 0,
y: 0,
radius: 100,
startCoord: startAngle,
endCoord: endAngle,
sides: sides
};
that._translator.setCodomain(startAngle, endAngle);
},
_shiftScale: function _shiftScale(layout) {
var scale = this._scale,
centerCoords,
canvas = scale.getCanvas();
canvas.width = canvas.height = layout.radius * 2;
scale.draw(canvas);
centerCoords = scale.getCenter();
scale.shift({ right: layout.x - centerCoords.x, bottom: layout.y - centerCoords.y });
},
_getScaleLayoutValue: function _getScaleLayoutValue() {
return this._area.radius;
},
_getTicksOrientation: function _getTicksOrientation(scaleOptions) {
return scaleOptions.orientation;
},
_getTicksCoefficients: function _getTicksCoefficients(options) {
var coefs = { inner: 0, outer: 1 };
if (options.orientation === "inside") {
coefs.inner = 1;
coefs.outer = 0;
} else if (options.orientation === "center") {
coefs.inner = coefs.outer = 0.5;
}
return coefs;
},
_correctScaleIndents: function _correctScaleIndents(result, indentFromTick, textParams) {
if (indentFromTick >= 0) {
result.horizontalOffset = indentFromTick + textParams.width;
result.verticalOffset = indentFromTick + textParams.height;
} else {
result.horizontalOffset = result.verticalOffset = 0;
result.min -= -indentFromTick + _max(textParams.width, textParams.height);
}
result.inverseHorizontalOffset = textParams.width / 2;
result.inverseVerticalOffset = textParams.height / 2;
},
_measureMainElements: function _measureMainElements(elements, scaleMeasurement) {
var that = this,
radius = that._area.radius,
maxRadius = 0,
minRadius = Infinity,
maxHorizontalOffset = 0,
maxVerticalOffset = 0,
maxInverseHorizontalOffset = 0,
maxInverseVerticalOffset = 0,
scale = that._scale;
_each(elements.concat(scale), function (_, element) {
var bounds = element.measure ? element.measure({ radius: radius - element.getOffset() }) : scaleMeasurement;
bounds.min > 0 && (minRadius = _min(minRadius, bounds.min));
bounds.max > 0 && (maxRadius = _max(maxRadius, bounds.max));
bounds.horizontalOffset > 0 && (maxHorizontalOffset = _max(maxHorizontalOffset, bounds.max + bounds.horizontalOffset));
bounds.verticalOffset > 0 && (maxVerticalOffset = _max(maxVerticalOffset, bounds.max + bounds.verticalOffset));
bounds.inverseHorizontalOffset > 0 && (maxInverseHorizontalOffset = _max(maxInverseHorizontalOffset, bounds.inverseHorizontalOffset));
bounds.inverseVerticalOffset > 0 && (maxInverseVerticalOffset = _max(maxInverseVerticalOffset, bounds.inverseVerticalOffset));
});
maxHorizontalOffset = _max(maxHorizontalOffset - maxRadius, 0);
maxVerticalOffset = _max(maxVerticalOffset - maxRadius, 0);
return {
minRadius: minRadius,
maxRadius: maxRadius,
horizontalMargin: maxHorizontalOffset,
verticalMargin: maxVerticalOffset,
inverseHorizontalMargin: maxInverseHorizontalOffset,
inverseVerticalMargin: maxInverseVerticalOffset
};
},
_applyMainLayout: function _applyMainLayout(elements, scaleMeasurement) {
var measurements = this._measureMainElements(elements, scaleMeasurement),
area = this._area,
sides = area.sides,
margins = {
left: (sides.left < -0.1 ? measurements.horizontalMargin : measurements.inverseHorizontalMargin) || 0,
right: (sides.right > 0.1 ? measurements.horizontalMargin : measurements.inverseHorizontalMargin) || 0,
top: (sides.up < -0.1 ? measurements.verticalMargin : measurements.inverseVerticalMargin) || 0,
bottom: (sides.down > 0.1 ? measurements.verticalMargin : measurements.inverseVerticalMargin) || 0
},
rect = selectRectByAspectRatio(this._innerRect, (sides.down - sides.up) / (sides.right - sides.left), margins),
radius = _min(getWidth(rect) / (sides.right - sides.left), getHeight(rect) / (sides.down - sides.up)),
x,
y;
radius = radius - measurements.maxRadius + area.radius;
x = rect.left - getWidth(rect) * sides.left / (sides.right - sides.left);
y = rect.top - getHeight(rect) * sides.up / (sides.down - sides.up);
area.x = _round(x);
area.y = _round(y);
area.radius = radius;
rect.left -= margins.left;
rect.right += margins.right;
rect.top -= margins.top;
rect.bottom += margins.bottom;
this._innerRect = rect;
},
_getElementLayout: function _getElementLayout(offset) {
return { x: this._area.x, y: this._area.y, radius: _round(this._area.radius - offset) };
},
_getApproximateScreenRange: function _getApproximateScreenRange() {
var that = this,
area = that._area,
r = _min(that._canvas.width / (area.sides.right - area.sides.left), that._canvas.height / (area.sides.down - area.sides.up));
r > area.totalRadius && (r = area.totalRadius);
r = 0.8 * r;
return -that._translator.getCodomainRange() * r * PI / 180;
},
_getDefaultSize: function _getDefaultSize() {
return { width: 300, height: 300 };
},
_factory: objectUtils.clone(dxBaseGauge.prototype._factory)
});
function getWidth(rect) {
return rect.right - rect.left;
}
function getHeight(rect) {
return rect.bottom - rect.top;
}
function selectRectByAspectRatio(srcRect, aspectRatio, margins) {
var rect = extend({}, srcRect),
selfAspectRatio,
width = 0,
height = 0;
margins = margins || {};
if (aspectRatio > 0) {
rect.left += margins.left || 0;
rect.right -= margins.right || 0;
rect.top += margins.top || 0;
rect.bottom -= margins.bottom || 0;
if (getWidth(rect) > 0 && getHeight(rect) > 0) {
selfAspectRatio = getHeight(rect) / getWidth(rect);
if (selfAspectRatio > 1) {
aspectRatio < selfAspectRatio ? width = getWidth(rect) : height = getHeight(rect);
} else {
aspectRatio > selfAspectRatio ? height = getHeight(rect) : width = getWidth(rect);
}
width > 0 || (width = height / aspectRatio);
height > 0 || (height = width * aspectRatio);
width = (getWidth(rect) - width) / 2;
height = (getHeight(rect) - height) / 2;
rect.left += width;
rect.right -= width;
rect.top += height;
rect.bottom -= height;
} else {
rect.left = rect.right = (rect.left + rect.right) / 2;
rect.top = rect.bottom = (rect.top + rect.bottom) / 2;
}
}
return rect;
}
///#DEBUG
dxCircularGauge._TESTS_selectRectByAspectRatio = selectRectByAspectRatio;
///#ENDDEBUG
var indicators = dxCircularGauge.prototype._factory.indicators = {};
dxCircularGauge.prototype._factory.createIndicator = createIndicatorCreator(indicators);
indicators._default = circularIndicatorsModule._default;
indicators["rectangleneedle"] = circularIndicatorsModule["rectangleneedle"];
indicators["triangleneedle"] = circularIndicatorsModule["triangleneedle"];
indicators["twocolorneedle"] = circularIndicatorsModule["twocolorneedle"];
indicators["trianglemarker"] = circularIndicatorsModule["trianglemarker"];
indicators["textcloud"] = circularIndicatorsModule["textcloud"];
indicators["rangebar"] = circularIndicatorsModule["rangebar"];
dxCircularGauge.prototype._factory.RangeContainer = CircularRangeContainer;
dxCircularGauge.prototype._factory.ThemeManager = ThemeManager.inherit({
_subTheme: "_circular"
});
registerComponent("dxCircularGauge", dxCircularGauge);
module.exports = dxCircularGauge;
;