UNPKG

highcharts

Version:
211 lines (210 loc) 6.05 kB
/* * * * Author: Paweł Lysy * * * */ 'use strict'; import Controllable from './Controllable.js'; import ControllablePath from './ControllablePath.js'; import { defined, merge } from '../../../Shared/Utilities.js'; /* * * * Class * * */ /** * A controllable ellipse class. * * @internal * @requires modules/annotations * * @class * @name Highcharts.AnnotationControllableEllipse * * @param {Highcharts.Annotation} annotation an annotation instance * @param {Highcharts.AnnotationsShapeOptions} options a shape's options * @param {number} index of the Ellipse */ class ControllableEllipse extends Controllable { /* * * * Constructor * * */ constructor(annotation, options, index) { super(annotation, options, index, 'shape'); /* * * * Properties * * */ this.type = 'ellipse'; } /* * * * Functions * * */ init(annotation, options, index) { if (defined(options.yAxis)) { options.points.forEach((point) => { if (point && typeof point !== 'string') { point.yAxis = options.yAxis; } }); } if (defined(options.xAxis)) { options.points.forEach((point) => { if (point && typeof point !== 'string') { point.xAxis = options.xAxis; } }); } super.init(annotation, options, index); } /** * Render the element. * * @param {Highcharts.SVGElement} parent * Parent SVG element. */ render(parent) { this.graphic = this.annotation.chart.renderer.createElement('ellipse') .attr(this.attrsFromOptions(this.options)) .add(parent); super.render(); } /** * Translate the points. Mostly used to handle dragging of the ellipse. */ translate(dx, dy) { super.translateShape(dx, dy, true); } /** * Get the distance from the line to the point. * * @param {object} point1 * First point which is on the line * @param {object} point2 * Second point * @param {number} x0 * Point's x value from which you want to calculate the distance from * @param {number} y0 * Point's y value from which you want to calculate the distance from */ getDistanceFromLine(point1, point2, x0, y0) { return Math.abs((point2.y - point1.y) * x0 - (point2.x - point1.x) * y0 + point2.x * point1.y - point2.y * point1.x) / Math.sqrt((point2.y - point1.y) * (point2.y - point1.y) + (point2.x - point1.x) * (point2.x - point1.x)); } /** * The function calculates the svg attributes of the ellipse, and returns * all parameters necessary to draw the ellipse. * * @param {Highcharts.BBoxObject} position * Absolute position of the first point in points array * @param {Highcharts.BBoxObject} position2 * Absolute position of the second point in points array */ getAttrs(position, position2) { const x1 = position.x, y1 = position.y, x2 = position2.x, y2 = position2.y, cx = (x1 + x2) / 2, cy = (y1 + y2) / 2, rx = Math.sqrt((x1 - x2) * (x1 - x2) / 4 + (y1 - y2) * (y1 - y2) / 4), tan = (y2 - y1) / (x2 - x1); let angle = Math.atan(tan) * 180 / Math.PI; if (cx < x1) { angle += 180; } const ry = this.getRY(); return { cx, cy, rx, ry, angle }; } /** * Get the value of minor radius of the ellipse. */ getRY() { const yAxis = this.getYAxis(); return defined(yAxis) ? Math.abs(yAxis.toPixels(this.options.ry) - yAxis.toPixels(0)) : this.options.ry; } /** * Get the yAxis object to which the ellipse is pinned. */ getYAxis() { const yAxisIndex = this.options.yAxis; return this.chart.yAxis[yAxisIndex]; } /** * Get the absolute coordinates of the MockPoint. * * @param {Highcharts.AnnotationPointType} point * MockPoint that is added through options */ getAbsolutePosition(point) { return this.anchor(point).absolutePosition; } /** * Redraw the element. * * @param {boolean} [animation] * Display an animation */ redraw(animation) { if (this.graphic) { const position = this.getAbsolutePosition(this.points[0]), position2 = this.getAbsolutePosition(this.points[1]), attrs = this.getAttrs(position, position2); if (position) { this.graphic[animation ? 'animate' : 'attr']({ cx: attrs.cx, cy: attrs.cy, rx: attrs.rx, ry: attrs.ry, rotation: attrs.angle, rotationOriginX: attrs.cx, rotationOriginY: attrs.cy }); } else { this.graphic.attr({ x: 0, y: -9e9 }); } this.graphic.placed = Boolean(position); } super.redraw(animation); } /** * Set the radius Y. * * @param {number} ry * A radius in y direction to be set */ setYRadius(ry) { const shapes = this.annotation.userOptions.shapes; this.options.ry = ry; if (shapes && shapes[0]) { shapes[0].ry = ry; shapes[0].ry = ry; } } } /* * * * Static Properties * * */ /** * A map object which allows to map options attributes to element * attributes. * * @name Highcharts.AnnotationControllableEllipse.attrsMap * @type {Highcharts.Dictionary<string>} */ ControllableEllipse.attrsMap = merge(ControllablePath.attrsMap, { ry: 'ry' }); /* * * * Default Export * * */ /** @internal */ export default ControllableEllipse;