123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- /* *
- * (c) 2010-2019 Torstein Honsi
- *
- * License: www.highcharts.com/license
- */
- 'use strict';
- import H from '../parts/Globals.js';
- import '../parts/Utilities.js';
- import '../parts/Options.js';
- import '../parts/Point.js';
- import '../parts/Series.js';
- import '../parts/Interaction.js';
- var isNumber = H.isNumber,
- merge = H.merge,
- noop = H.noop,
- pick = H.pick,
- pInt = H.pInt,
- Series = H.Series,
- seriesType = H.seriesType,
- TrackerMixin = H.TrackerMixin;
- /**
- * Gauges are circular plots displaying one or more values with a dial pointing
- * to values along the perimeter.
- *
- * @sample highcharts/demo/gauge-speedometer/
- * Gauge chart
- *
- * @extends plotOptions.line
- * @excluding animationLimit, boostThreshold, connectEnds, connectNulls,
- * cropThreshold, dashStyle, findNearestPointBy,
- * getExtremesFromAll, marker, negativeColor, pointPlacement,
- * shadow, softThreshold, stacking, states, step, threshold,
- * turboThreshold, xAxis, zoneAxis, zones
- * @product highcharts
- * @optionparent plotOptions.gauge
- */
- seriesType('gauge', 'line', {
- /**
- * When this option is `true`, the dial will wrap around the axes. For
- * instance, in a full-range gauge going from 0 to 360, a value of 400
- * will point to 40\. When `wrap` is `false`, the dial stops at 360.
- *
- * @see [overshoot](#plotOptions.gauge.overshoot)
- *
- * @type {boolean}
- * @default true
- * @since 3.0
- * @product highcharts
- * @apioption plotOptions.gauge.wrap
- */
- /**
- * Data labels for the gauge. For gauges, the data labels are enabled
- * by default and shown in a bordered box below the point.
- *
- * @extends plotOptions.series.dataLabels
- * @since 2.3.0
- * @product highcharts
- */
- dataLabels: {
- /**
- * Enable or disable the data labels.
- *
- * @since 2.3.0
- * @product highcharts highmaps
- */
- enabled: true,
- defer: false,
- /**
- * The y position offset of the label relative to the center of the
- * gauge.
- *
- * @since 2.3.0
- * @product highcharts highmaps
- */
- y: 15,
- /**
- * The border radius in pixels for the gauge's data label.
- *
- * @since 2.3.0
- * @product highcharts highmaps
- */
- borderRadius: 3,
- crop: false,
- /**
- * The vertical alignment of the data label.
- *
- * @product highcharts highmaps
- */
- verticalAlign: 'top',
- /**
- * The Z index of the data labels. A value of 2 display them behind
- * the dial.
- *
- * @since 2.1.5
- * @product highcharts highmaps
- */
- zIndex: 2,
- /**
- * The border width in pixels for the gauge data label.
- *
- * @since 2.3.0
- * @product highcharts highmaps
- */
- borderWidth: 1,
- /**
- * The border color for the data label.
- *
- * @type {Highcharts.ColorString}
- * @default #cccccc
- * @since 2.3.0
- * @product highcharts highmaps
- */
- borderColor: '#cccccc'
- },
- /**
- * Options for the dial or arrow pointer of the gauge.
- *
- * In styled mode, the dial is styled with the
- * `.highcharts-gauge-series .highcharts-dial` rule.
- *
- * @sample {highcharts} highcharts/css/gauge/
- * Styled mode
- *
- * @since 2.3.0
- * @product highcharts
- */
- dial: {},
- /**
- * The length of the dial's base part, relative to the total radius
- * or length of the dial.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-dial/
- * Dial options demonstrated
- *
- * @type {string}
- * @default 70%
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.dial.baseLength
- */
- /**
- * The pixel width of the base of the gauge dial. The base is the part
- * closest to the pivot, defined by baseLength.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-dial/
- * Dial options demonstrated
- *
- * @type {number}
- * @default 3
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.dial.baseWidth
- */
- /**
- * The radius or length of the dial, in percentages relative to the
- * radius of the gauge itself.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-dial/
- * Dial options demonstrated
- *
- * @type {string}
- * @default 80%
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.dial.radius
- */
- /**
- * The length of the dial's rear end, the part that extends out on the
- * other side of the pivot. Relative to the dial's length.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-dial/
- * Dial options demonstrated
- *
- * @type {string}
- * @default 10%
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.dial.rearLength
- */
- /**
- * The width of the top of the dial, closest to the perimeter. The pivot
- * narrows in from the base to the top.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-dial/
- * Dial options demonstrated
- *
- * @type {number}
- * @default 1
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.dial.topWidth
- */
- /**
- * The background or fill color of the gauge's dial.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-dial/
- * Dial options demonstrated
- *
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
- * @default #000000
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.dial.backgroundColor
- */
- /**
- * The border color or stroke of the gauge's dial. By default, the
- * borderWidth is 0, so this must be set in addition to a custom border
- * color.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-dial/
- * Dial options demonstrated
- *
- * @type {Highcharts.ColorString}
- * @default #cccccc
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.dial.borderColor
- */
- /**
- * The width of the gauge dial border in pixels.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-dial/
- * Dial options demonstrated
- *
- * @type {number}
- * @default 0
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.dial.borderWidth
- */
- /**
- * Allow the dial to overshoot the end of the perimeter axis by this
- * many degrees. Say if the gauge axis goes from 0 to 60, a value of
- * 100, or 1000, will show 5 degrees beyond the end of the axis when this
- * option is set to 5.
- *
- * @see [wrap](#plotOptions.gauge.wrap)
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-overshoot/
- * Allow 5 degrees overshoot
- *
- * @type {number}
- * @default 0
- * @since 3.0.10
- * @product highcharts
- * @apioption plotOptions.gauge.overshoot
- */
- /**
- * Options for the pivot or the center point of the gauge.
- *
- * In styled mode, the pivot is styled with the
- * `.highcharts-gauge-series .highcharts-pivot` rule.
- *
- * @sample {highcharts} highcharts/css/gauge/
- * Styled mode
- *
- * @since 2.3.0
- * @product highcharts
- */
- pivot: {},
- /**
- * The pixel radius of the pivot.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
- * Pivot options demonstrated
- *
- * @type {number}
- * @default 5
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.pivot.radius
- */
- /**
- * The border or stroke width of the pivot.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
- * Pivot options demonstrated
- *
- * @type {number}
- * @default 0
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.pivot.borderWidth
- */
- /**
- * The border or stroke color of the pivot. In able to change this,
- * the borderWidth must also be set to something other than the default
- * 0.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
- * Pivot options demonstrated
- *
- * @type {Highcharts.ColorString}
- * @default #cccccc
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.pivot.borderColor
- */
- /**
- * The background color or fill of the pivot.
- *
- * @sample {highcharts} highcharts/plotoptions/gauge-pivot/
- * Pivot options demonstrated
- *
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
- * @default #000000
- * @since 2.3.0
- * @product highcharts
- * @apioption plotOptions.gauge.pivot.backgroundColor
- */
- tooltip: {
- headerFormat: ''
- },
- /**
- * Whether to display this particular series or series type in the
- * legend. Defaults to false for gauge series.
- *
- * @since 2.3.0
- * @product highcharts
- */
- showInLegend: false
- // Prototype members
- }, {
- // chart.angular will be set to true when a gauge series is present,
- // and this will be used on the axes
- angular: true,
- directTouch: true, // #5063
- drawGraph: noop,
- fixedBox: true,
- forceDL: true,
- noSharedTooltip: true,
- trackerGroups: ['group', 'dataLabelsGroup'],
- // Calculate paths etc
- translate: function () {
- var series = this,
- yAxis = series.yAxis,
- options = series.options,
- center = yAxis.center;
- series.generatePoints();
- series.points.forEach(function (point) {
- var dialOptions = merge(options.dial, point.dial),
- radius = (pInt(pick(dialOptions.radius, 80)) * center[2]) /
- 200,
- baseLength = (pInt(pick(dialOptions.baseLength, 70)) * radius) /
- 100,
- rearLength = (pInt(pick(dialOptions.rearLength, 10)) * radius) /
- 100,
- baseWidth = dialOptions.baseWidth || 3,
- topWidth = dialOptions.topWidth || 1,
- overshoot = options.overshoot,
- rotation = yAxis.startAngleRad +
- yAxis.translate(point.y, null, null, null, true);
- // Handle the wrap and overshoot options
- if (isNumber(overshoot)) {
- overshoot = overshoot / 180 * Math.PI;
- rotation = Math.max(
- yAxis.startAngleRad - overshoot,
- Math.min(yAxis.endAngleRad + overshoot, rotation)
- );
- } else if (options.wrap === false) {
- rotation = Math.max(
- yAxis.startAngleRad,
- Math.min(yAxis.endAngleRad, rotation)
- );
- }
- rotation = rotation * 180 / Math.PI;
- point.shapeType = 'path';
- point.shapeArgs = {
- d: dialOptions.path || [
- 'M',
- -rearLength, -baseWidth / 2,
- 'L',
- baseLength, -baseWidth / 2,
- radius, -topWidth / 2,
- radius, topWidth / 2,
- baseLength, baseWidth / 2,
- -rearLength, baseWidth / 2,
- 'z'
- ],
- translateX: center[0],
- translateY: center[1],
- rotation: rotation
- };
- // Positions for data label
- point.plotX = center[0];
- point.plotY = center[1];
- });
- },
- // Draw the points where each point is one needle
- drawPoints: function () {
- var series = this,
- chart = series.chart,
- center = series.yAxis.center,
- pivot = series.pivot,
- options = series.options,
- pivotOptions = options.pivot,
- renderer = chart.renderer;
- series.points.forEach(function (point) {
- var graphic = point.graphic,
- shapeArgs = point.shapeArgs,
- d = shapeArgs.d,
- dialOptions = merge(options.dial, point.dial); // #1233
- if (graphic) {
- graphic.animate(shapeArgs);
- shapeArgs.d = d; // animate alters it
- } else {
- point.graphic = renderer[point.shapeType](shapeArgs)
- .attr({
- // required by VML when animation is false
- rotation: shapeArgs.rotation,
- zIndex: 1
- })
- .addClass('highcharts-dial')
- .add(series.group);
- // Presentational attributes
- if (!chart.styledMode) {
- point.graphic.attr({
- stroke: dialOptions.borderColor || 'none',
- 'stroke-width': dialOptions.borderWidth || 0,
- fill: dialOptions.backgroundColor ||
- '#000000'
- });
- }
- }
- });
- // Add or move the pivot
- if (pivot) {
- pivot.animate({ // #1235
- translateX: center[0],
- translateY: center[1]
- });
- } else {
- series.pivot = renderer.circle(0, 0, pick(pivotOptions.radius, 5))
- .attr({
- zIndex: 2
- })
- .addClass('highcharts-pivot')
- .translate(center[0], center[1])
- .add(series.group);
- // Presentational attributes
- if (!chart.styledMode) {
- series.pivot.attr({
- 'stroke-width': pivotOptions.borderWidth || 0,
- stroke: pivotOptions.borderColor ||
- '#cccccc',
- fill: pivotOptions.backgroundColor ||
- '#000000'
- });
- }
- }
- },
- // Animate the arrow up from startAngle
- animate: function (init) {
- var series = this;
- if (!init) {
- series.points.forEach(function (point) {
- var graphic = point.graphic;
- if (graphic) {
- // start value
- graphic.attr({
- rotation: series.yAxis.startAngleRad * 180 / Math.PI
- });
- // animate
- graphic.animate({
- rotation: point.shapeArgs.rotation
- }, series.options.animation);
- }
- });
- // delete this function to allow it only once
- series.animate = null;
- }
- },
- render: function () {
- this.group = this.plotGroup(
- 'group',
- 'series',
- this.visible ? 'visible' : 'hidden',
- this.options.zIndex,
- this.chart.seriesGroup
- );
- Series.prototype.render.call(this);
- this.group.clip(this.chart.clipRect);
- },
- // Extend the basic setData method by running processData and generatePoints
- // immediately, in order to access the points from the legend.
- setData: function (data, redraw) {
- Series.prototype.setData.call(this, data, false);
- this.processData();
- this.generatePoints();
- if (pick(redraw, true)) {
- this.chart.redraw();
- }
- },
- // If the tracking module is loaded, add the point tracker
- drawTracker: TrackerMixin && TrackerMixin.drawTrackerPoint
- // Point members
- }, {
- // Don't do any hover colors or anything
- setState: function (state) {
- this.state = state;
- }
- });
- /**
- * A `gauge` series. If the [type](#series.gauge.type) option is not
- * specified, it is inherited from [chart.type](#chart.type).
- *
- * @extends series,plotOptions.gauge
- * @excluding animationLimit, boostThreshold, connectEnds, connectNulls,
- * cropThreshold, dashStyle, dataParser, dataURL, findNearestPointBy,
- * getExtremesFromAll, marker, negativeColor, pointPlacement, shadow,
- * softThreshold, stack, stacking, states, step, threshold,
- * turboThreshold, zoneAxis, zones
- * @product highcharts
- * @apioption series.gauge
- */
- /**
- * An array of data points for the series. For the `gauge` series type,
- * points can be given in the following ways:
- *
- * 1. An array of numerical values. In this case, the numerical values will be
- * interpreted as `y` options. Example:
- * ```js
- * data: [0, 5, 3, 5]
- * ```
- *
- * 2. An array of objects with named values. The following snippet shows only a
- * few settings, see the complete options set below. If the total number of
- * data points exceeds the series'
- * [turboThreshold](#series.gauge.turboThreshold), this option is not
- * available.
- * ```js
- * data: [{
- * y: 6,
- * name: "Point2",
- * color: "#00FF00"
- * }, {
- * y: 8,
- * name: "Point1",
- * color: "#FF00FF"
- * }]
- * ```
- *
- * The typical gauge only contains a single data value.
- *
- * @sample {highcharts} highcharts/chart/reflow-true/
- * Numerical values
- * @sample {highcharts} highcharts/series/data-array-of-objects/
- * Config objects
- *
- * @type {Array<number|*>}
- * @extends series.line.data
- * @excluding drilldown, marker, x
- * @product highcharts
- * @apioption series.gauge.data
- */
|