highcharts
Version:
JavaScript charting framework
243 lines (207 loc) • 7.3 kB
JavaScript
'use strict';
import H from '../../parts/Globals.js';
import '../../parts/Utilities.js';
var Annotation = H.Annotation,
CrookedLine = Annotation.types.crookedLine,
ControlPoint = Annotation.ControlPoint,
MockPoint = Annotation.MockPoint;
function getSecondCoordinate(p1, p2, x) {
return (p2.y - p1.y) / (p2.x - p1.x) * (x - p1.x) + p1.y;
}
/**
* @class
* @extends Annotation.CrookedLine
* @memberOf Annotation
**/
function Tunnel() {
CrookedLine.apply(this, arguments);
}
H.extendAnnotation(
Tunnel,
CrookedLine,
/** @lends Annotation.Tunnel# */
{
getPointsOptions: function () {
var pointsOptions =
CrookedLine.prototype.getPointsOptions.call(this);
pointsOptions[2] = this.heightPointOptions(pointsOptions[1]);
pointsOptions[3] = this.heightPointOptions(pointsOptions[0]);
return pointsOptions;
},
getControlPointsOptions: function () {
return this.getPointsOptions().slice(0, 2);
},
heightPointOptions: function (pointOptions) {
var heightPointOptions = H.merge(pointOptions);
heightPointOptions.y += this.options.typeOptions.height;
return heightPointOptions;
},
addControlPoints: function () {
CrookedLine.prototype.addControlPoints.call(this);
var options = this.options,
controlPoint = new ControlPoint(
this.chart,
this,
H.merge(
options.controlPointOptions,
options.typeOptions.heightControlPoint
),
2
);
this.controlPoints.push(controlPoint);
options.typeOptions.heightControlPoint = controlPoint.options;
},
addShapes: function () {
this.addLine();
this.addBackground();
},
addLine: function () {
var line = this.initShape(
H.merge(this.options.typeOptions.line, {
type: 'path',
points: [
this.points[0],
this.points[1],
function (target) {
var pointOptions = MockPoint.pointToOptions(
target.annotation.points[2]
);
pointOptions.command = 'M';
return pointOptions;
},
this.points[3]
]
}),
false
);
this.options.typeOptions.line = line.options;
},
addBackground: function () {
var background = this.initShape(H.merge(
this.options.typeOptions.background,
{
type: 'path',
points: this.points.slice()
}
));
this.options.typeOptions.background = background.options;
},
/**
* Translate start or end ("left" or "right") side of the tunnel.
*
* @param {number} dx - the amount of x translation
* @param {number} dy - the amount of y translation
* @param {boolean} [end] - whether to translate start or end side
*/
translateSide: function (dx, dy, end) {
var topIndex = Number(end),
bottomIndex = topIndex === 0 ? 3 : 2;
this.translatePoint(dx, dy, topIndex);
this.translatePoint(dx, dy, bottomIndex);
},
/**
* Translate height of the tunnel.
*
* @param {number} dh - the amount of height translation
*/
translateHeight: function (dh) {
this.translatePoint(0, dh, 2);
this.translatePoint(0, dh, 3);
this.options.typeOptions.height =
this.points[3].y - this.points[0].y;
}
},
/**
* A tunnel annotation.
*
* @extends annotations.crookedLine
* @sample highcharts/annotations-advanced/tunnel/
* Tunnel
* @product highstock
* @optionparent annotations.tunnel
*/
{
typeOptions: {
xAxis: 0,
yAxis: 0,
/**
* Background options.
*
* @type {Object}
* @excluding height, point, points, r, type, width, markerEnd,
* markerStart
*/
background: {
fill: 'rgba(130, 170, 255, 0.4)',
strokeWidth: 0
},
line: {
strokeWidth: 1
},
/**
* The height of the annotation in terms of yAxis.
*/
height: -2,
/**
* Options for the control point which controls
* the annotation's height.
*
* @extends annotations.crookedLine.controlPointOptions
* @excluding positioner, events
*/
heightControlPoint: {
positioner: function (target) {
var startXY = MockPoint.pointToPixels(target.points[2]),
endXY = MockPoint.pointToPixels(target.points[3]),
x = (startXY.x + endXY.x) / 2;
return {
x: x - this.graphic.width / 2,
y: getSecondCoordinate(startXY, endXY, x) -
this.graphic.height / 2
};
},
events: {
drag: function (e, target) {
if (
target.chart.isInsidePlot(
e.chartX - target.chart.plotLeft,
e.chartY - target.chart.plotTop
)
) {
target.translateHeight(
this.mouseMoveToTranslation(e).y
);
target.redraw(false);
}
}
}
}
},
/**
* @extends annotations.crookedLine.controlPointOptions
* @excluding positioner, events
*/
controlPointOptions: {
events: {
drag: function (e, target) {
if (
target.chart.isInsidePlot(
e.chartX - target.chart.plotLeft,
e.chartY - target.chart.plotTop
)
) {
var translation = this.mouseMoveToTranslation(e);
target.translateSide(
translation.x,
translation.y,
this.index
);
target.redraw(false);
}
}
}
}
}
);
Annotation.types.tunnel = Tunnel;
export default Tunnel;