1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942 |
- /* *
- * (c) 2009-2017 Highsoft, Black Label
- *
- * License: www.highcharts.com/license
- */
- /**
- * @interface Highcharts.AnnotationAnchorObject
- *//**
- * Relative to the plot area position
- * @name Highcharts.AnnotationAnchorObject#relativePosition
- * @type {Highcharts.AnnotationAnchorPositionObject}
- *//**
- * Absolute position
- * @name Highcharts.AnnotationAnchorObject#absolutePosition
- * @type {Highcharts.AnnotationAnchorPositionObject}
- */
- /**
- * An object which denotes an anchor position
- *
- * @interface Highcharts.AnnotationAnchorPositionObject
- *//**
- * @name Highcharts.AnnotationAnchorPositionObject#x
- * @property {number}
- *//**
- * @name Highcharts.AnnotationAnchorPositionObject#y
- * @property {number}
- *//**
- * @name Highcharts.AnnotationAnchorPositionObject#height
- * @property {number}
- *//**
- * @name Highcharts.AnnotationAnchorPositionObject#width
- * @property {number}
- */
- /**
- * A mock point label configuration.
- *
- * @private
- * @interface Highcharts.MockLabelOptionsObject
- *//**
- * X value translated to x axis scale
- * @name Highcharts.MockLabelOptionsObject#x
- * @type {number|undefined}
- *//**
- * Y value translated to y axis scale
- * @name Highcharts.MockLabelOptionsObject#y
- * @type {number|undefined}
- *//**
- * @name Highcharts.MockLabelOptionsObject#point
- * @type {Highcharts.Point}
- */
- /**
- * A mock point configuration.
- *
- * @todo Make official
- *
- * @private
- * @interface Highcharts.MockPointOptionsObject
- *//**
- * x value for the point in xAxis scale or pixels
- * @name Highcharts.MockPointOptionsObject#x
- * @type {number}
- *//**
- * y value for the point in yAxis scale or pixels
- * @name Highcharts.MockPointOptionsObject#y
- * @type {number}
- *//**
- * xAxis index or id
- * @name Highcharts.MockPointOptionsObject#xAxis
- * @type {number|string|undefined}
- *//**
- * yAxis index or id
- * @name Highcharts.MockPointOptionsObject#yAxis
- * @property {number|string|undefined}
- */
- 'use strict';
- import H from '../parts/Globals.js';
- import '../parts/Utilities.js';
- import '../parts/Chart.js';
- import '../parts/Series.js';
- import '../parts/Tooltip.js';
- var merge = H.merge,
- addEvent = H.addEvent,
- extend = H.extend,
- isString = H.isString,
- isNumber = H.isNumber,
- defined = H.defined,
- isObject = H.isObject,
- erase = H.erase,
- find = H.find,
- format = H.format,
- pick = H.pick,
- objectEach = H.objectEach,
- uniqueKey = H.uniqueKey,
- destroyObjectProperties = H.destroyObjectProperties,
- tooltipPrototype = H.Tooltip.prototype,
- seriesPrototype = H.Series.prototype,
- chartPrototype = H.Chart.prototype;
- /* ************************************************************************** *
- *
- * MARKER SECTION
- * Contains objects and functions for adding a marker element to a path
- * element
- *
- * ************************************************************************** */
- /**
- * Options for configuring markers for annotations.
- *
- * An example of the arrow marker:
- * ```
- * {
- * arrow: {
- * id: 'arrow',
- * tagName: 'marker',
- * refY: 5,
- * refX: 5,
- * markerWidth: 10,
- * markerHeight: 10,
- * children: [{
- * tagName: 'path',
- * attrs: {
- * d: 'M 0 0 L 10 5 L 0 10 Z',
- * strokeWidth: 0
- * }
- * }]
- * }
- * }
- * ```
- *
- * @sample highcharts/annotations/custom-markers/
- * Define a custom marker for annotations
- * @sample highcharts/css/annotations-markers/
- * Define markers in a styled mode
- *
- * @type {Highcharts.Dictionary<Highcharts.SVGAttributes>}
- * @since 6.0.0
- * @apioption defs
- */
- var defaultMarkers = {
- arrow: {
- tagName: 'marker',
- render: false,
- id: 'arrow',
- refY: 5,
- refX: 5,
- markerWidth: 10,
- markerHeight: 10,
- children: [{
- tagName: 'path',
- d: 'M 0 0 L 10 5 L 0 10 Z', // triangle (used as an arrow)
- strokeWidth: 0
- }]
- }
- };
- var MarkerMixin = {
- markerSetter: function (markerType) {
- return function (value) {
- this.attr(markerType, 'url(#' + value + ')');
- };
- }
- };
- extend(MarkerMixin, {
- markerEndSetter: MarkerMixin.markerSetter('marker-end'),
- markerStartSetter: MarkerMixin.markerSetter('marker-start')
- });
- H.SVGRenderer.prototype.addMarker = function (id, markerOptions) {
- var options = { id: id };
- if (!this.styledMode) {
- var attrs = {
- stroke: markerOptions.color || 'none',
- fill: markerOptions.color || 'rgba(0, 0, 0, 0.75)'
- };
- options.children = markerOptions.children.map(function (child) {
- return merge(attrs, child);
- });
- }
- var marker = this.definition(merge({
- markerWidth: 20,
- markerHeight: 20,
- refX: 0,
- refY: 0,
- orient: 'auto'
- }, markerOptions, options));
- marker.id = id;
- return marker;
- };
- /* ************************************************************************** *
- *
- * MOCK POINT
- *
- * ************************************************************************** */
- /**
- * A trimmed point object which imitates {@link Highchart.Point} class.
- * It is created when there is a need of pointing to some chart's position
- * using axis values or pixel values
- *
- * @private
- * @class
- * @name Highcharts.MockPoint
- *
- * @param {Highcharts.Chart} chart
- * The chart object
- *
- * @param {Highcharts.MockPointOptionsObject} options
- * The options object
- */
- var MockPoint = H.MockPoint = function (chart, options) {
- this.mock = true;
- this.series = {
- visible: true,
- chart: chart,
- getPlotBox: seriesPrototype.getPlotBox
- };
- // this.plotX
- // this.plotY
- /* Those might not exist if a specific axis was not found/defined */
- // this.x?
- // this.y?
- this.init(chart, options);
- };
- /**
- * A factory function for creating a mock point object
- *
- * @function Highcharts.MockPoint#mockPoint
- *
- * @param {Highcharts.MockPointOptionsObject} mockPointOptions
- *
- * @return {Highcharts.MockPoint}
- * A mock point
- */
- var mockPoint = H.mockPoint = function (chart, mockPointOptions) {
- return new MockPoint(chart, mockPointOptions);
- };
- /**
- * @private
- * @class
- * @name Highcharts.MockPoint
- */
- MockPoint.prototype = {
- /**
- * Initialisation of the mock point
- *
- * @function Highcharts.MockPoint#init
- *
- * @param {Highcharts.Chart} chart
- * A chart object to which the mock point is attached
- *
- * @param {Highcharts.MockPointOptionsObject} options
- * A config for the mock point
- */
- init: function (chart, options) {
- var xAxisId = options.xAxis,
- xAxis = defined(xAxisId) ?
- chart.xAxis[xAxisId] || chart.get(xAxisId) :
- null,
- yAxisId = options.yAxis,
- yAxis = defined(yAxisId) ?
- chart.yAxis[yAxisId] || chart.get(yAxisId) :
- null;
- if (xAxis) {
- this.x = options.x;
- this.series.xAxis = xAxis;
- } else {
- this.plotX = options.x;
- }
- if (yAxis) {
- this.y = options.y;
- this.series.yAxis = yAxis;
- } else {
- this.plotY = options.y;
- }
- },
- /**
- * Update of the point's coordinates (plotX/plotY)
- *
- * @function Highcharts.MockPoint#translate
- */
- translate: function () {
- var series = this.series,
- xAxis = series.xAxis,
- yAxis = series.yAxis;
- if (xAxis) {
- this.plotX = xAxis.toPixels(this.x, true);
- }
- if (yAxis) {
- this.plotY = yAxis.toPixels(this.y, true);
- }
- this.isInside = this.isInsidePane();
- },
- /**
- * Returns a box to which an item can be aligned to
- *
- * @function Highcharts.MockPoint#alignToBox
- *
- * @param {boolean} [forceTranslate=false]
- * Whether to update the point's coordinates
- *
- * @return {Array<number,number,number,number>}
- * A quadruple of numbers which denotes x, y, width and height of
- * the box
- **/
- alignToBox: function (forceTranslate) {
- if (forceTranslate) {
- this.translate();
- }
- var x = this.plotX,
- y = this.plotY,
- temp;
- if (this.series.chart.inverted) {
- temp = x;
- x = y;
- y = temp;
- }
- return [x, y, 0, 0];
- },
- /**
- * Returns a label config object -
- * the same as Highcharts.Point.prototype.getLabelConfig
- *
- * @function Highcharts.MockPoint#getLabelConfig
- *
- * @return {Highcharts.MockLabelOptionsObject}
- * Label config object
- */
- getLabelConfig: function () {
- return {
- x: this.x,
- y: this.y,
- point: this
- };
- },
- isInsidePane: function () {
- var plotX = this.plotX,
- plotY = this.plotY,
- xAxis = this.series.xAxis,
- yAxis = this.series.yAxis,
- isInside = true;
- if (xAxis) {
- isInside = defined(plotX) && plotX >= 0 && plotX <= xAxis.len;
- }
- if (yAxis) {
- isInside =
- isInside &&
- defined(plotY) &&
- plotY >= 0 && plotY <= yAxis.len;
- }
- return isInside;
- }
- };
- /* ************************************************************************** *
- *
- * ANNOTATION
- *
- * ************************************************************************** */
- H.defaultOptions.annotations = [];
- /**
- * An annotation class which serves as a container for items like labels or
- * shapes. Created items are positioned on the chart either by linking them to
- * existing points or created mock points
- *
- * @class
- * @name Highcharts.Annotation
- *
- * @param {Highcharts.Chart} chart
- * The chart object
- *
- * @param {Highcharts.AnnotationsOptions} userOptions
- * The options object
- */
- var Annotation = H.Annotation = function (chart, userOptions) {
- /**
- * The chart that the annotation belongs to.
- *
- * @name Highcharts.Annotation#chart
- * @type {Highcharts.Chart}
- */
- this.chart = chart;
- /**
- * The array of labels which belong to the annotation.
- *
- * @name Highcharts.Annotation#labels
- * @type {Array<Highcharts.SVGElement>}
- */
- this.labels = [];
- /**
- * The array of shapes which belong to the annotation.
- *
- * @name Highcharts.Annotation#shapes
- * @type {Array<Highcharts.SVGElement>}
- */
- this.shapes = [];
- /**
- * The user options for the annotations.
- *
- * @name Highcharts.Annotation#userOptions
- * @type {Highcharts.AnnotationsOptions}
- */
- this.userOptions = userOptions;
- /**
- * The options for the annotations. It contains user defined options
- * merged with the default options.
- *
- * @name Highcharts.Annotation#options
- * @type {Highcharts.AnnotationsOptions}
- */
- this.options = merge(this.defaultOptions, userOptions);
- /**
- * The callback that reports to the overlapping-labels module which
- * labels it should account for.
- *
- * @todo Needs more specific function interface
- *
- * @private
- * @name Highcharts.Annotation#labelCollector
- * @type {Function}
- */
- /**
- * The group element of the annotation.
- *
- * @private
- * @name Highcharts.Annotation#group
- * @type {Highcharts.SVGElement}
- */
- /**
- * The group element of the annotation's shapes.
- *
- * @private
- * @name Highcharts.Annotation#shapesGroup
- * @type {Highcharts.SVGElement}
- */
- /**
- * The group element of the annotation's labels.
- *
- * @private
- * @name Highcharts.Annotation#labelsGroup
- * @type {Highcharts.SVGElement}
- */
- this.init(chart, userOptions);
- };
- Annotation.prototype = {
- /**
- * Shapes which do not have background - the object is used for proper
- * setting of the contrast color
- *
- * @private
- * @name Highcharts.Annotations#shapesWithoutBackground
- * @type {Array<string>}
- */
- shapesWithoutBackground: ['connector'],
- /**
- * Returns a map object which allows to map options attributes to element
- * attributes.
- *
- * @private
- * @function Highcharts.Annotations#getAttrsMap
- *
- * @return {object}
- */
- getAttrsMap: function () {
- var attrsMap = {
- zIndex: 'zIndex',
- width: 'width',
- height: 'height',
- borderRadius: 'r',
- r: 'r',
- padding: 'padding'
- };
- if (!this.chart.styledMode) {
- extend(attrsMap, {
- backgroundColor: 'fill',
- borderColor: 'stroke',
- borderWidth: 'stroke-width',
- dashStyle: 'dashstyle',
- strokeWidth: 'stroke-width',
- stroke: 'stroke',
- fill: 'fill'
- });
- }
- return attrsMap;
- },
- /**
- * Options for configuring annotations, for example labels, arrows or
- * shapes. Annotations can be tied to points, axis coordinates or chart
- * pixel coordinates.
- *
- * @sample highcharts/annotations/basic/
- * Basic annotations
- * @sample highcharts/demo/annotations/
- * Advanced annotations
- * @sample highcharts/css/annotations
- * Styled mode
- * @sample {highstock} stock/annotations/fibonacci-retracements
- * Custom annotation, Fibonacci retracement
- *
- * @type {Array<*>}
- * @since 6.0.0
- * @optionparent annotations
- */
- defaultOptions: {
- /**
- * Sets an ID for an annotation. Can be user later when removing an
- * annotation in [Chart#removeAnnotation(id)](
- * /class-reference/Highcharts.Chart#removeAnnotation) method.
- *
- * @type {string}
- * @apioption annotations.id
- */
- /**
- * Whether the annotation is visible.
- *
- * @sample highcharts/annotations/visible/
- * Set annotation visibility
- */
- visible: true,
- /**
- * Options for annotation's labels. Each label inherits options
- * from the labelOptions object. An option from the labelOptions can be
- * overwritten by config for a specific label.
- */
- labelOptions: {
- /**
- * The alignment of the annotation's label. If right,
- * the right side of the label should be touching the point.
- *
- * @sample highcharts/annotations/label-position/
- * Set labels position
- *
- * @type {Highcharts.AlignType}
- */
- align: 'center',
- /**
- * Whether to allow the annotation's labels to overlap.
- * To make the labels less sensitive for overlapping,
- * the can be set to 0.
- *
- * @sample highcharts/annotations/tooltip-like/
- * Hide overlapping labels
- */
- allowOverlap: false,
- /**
- * The background color or gradient for the annotation's label.
- *
- * @sample highcharts/annotations/label-presentation/
- * Set labels graphic options
- *
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
- */
- backgroundColor: 'rgba(0, 0, 0, 0.75)',
- /**
- * The border color for the annotation's label.
- *
- * @sample highcharts/annotations/label-presentation/
- * Set labels graphic options
- *
- * @type {Highcharts.ColorString}
- */
- borderColor: 'black',
- /**
- * The border radius in pixels for the annotaiton's label.
- *
- * @sample highcharts/annotations/label-presentation/
- * Set labels graphic options
- */
- borderRadius: 3,
- /**
- * The border width in pixels for the annotation's label
- *
- * @sample highcharts/annotations/label-presentation/
- * Set labels graphic options
- */
- borderWidth: 1,
- /**
- * A class name for styling by CSS.
- *
- * @sample highcharts/css/annotations
- * Styled mode annotations
- *
- * @since 6.0.5
- */
- className: '',
- /**
- * Whether to hide the annotation's label that is outside the plot
- * area.
- *
- * @sample highcharts/annotations/label-crop-overflow/
- * Crop or justify labels
- */
- crop: false,
- /**
- * The label's pixel distance from the point.
- *
- * @sample highcharts/annotations/label-position/
- * Set labels position
- *
- * @type {number}
- * @apioption annotations.labelOptions.distance
- */
- /**
- * A
- * [format](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting)
- * string for the data label.
- *
- * @see [plotOptions.series.dataLabels.format](plotOptions.series.dataLabels.format.html)
- *
- * @sample highcharts/annotations/label-text/
- * Set labels text
- *
- * @type {string}
- * @apioption annotations.labelOptions.format
- */
- /**
- * Alias for the format option.
- *
- * @see [format](annotations.labelOptions.format.html)
- *
- * @sample highcharts/annotations/label-text/
- * Set labels text
- *
- * @type {string}
- * @apioption annotations.labelOptions.text
- */
- /**
- * Callback JavaScript function to format the annotation's label.
- * Note that if a `format` or `text` are defined, the format or text
- * take precedence and the formatter is ignored. `This` refers to a
- * point object.
- *
- * @sample highcharts/annotations/label-text/
- * Set labels text
- *
- * @type {Highcharts.FormatterCallbackFunction<Highcharts.Point>}
- * @default function () { return defined(this.y) ? this.y : 'Annotation label'; }
- */
- formatter: function () {
- return defined(this.y) ? this.y : 'Annotation label';
- },
- /**
- * How to handle the annotation's label that flow outside the plot
- * area. The justify option aligns the label inside the plot area.
- *
- * @sample highcharts/annotations/label-crop-overflow/
- * Crop or justify labels
- *
- * @validvalue ["allow", "justify"]
- */
- overflow: 'justify',
- /**
- * When either the borderWidth or the backgroundColor is set,
- * this is the padding within the box.
- *
- * @sample highcharts/annotations/label-presentation/
- * Set labels graphic options
- */
- padding: 5,
- /**
- * The shadow of the box. The shadow can be an object configuration
- * containing `color`, `offsetX`, `offsetY`, `opacity` and `width`.
- *
- * @sample highcharts/annotations/label-presentation/
- * Set labels graphic options
- *
- * @type {boolean|Highcharts.ShadowOptionsObject}
- */
- shadow: false,
- /**
- * The name of a symbol to use for the border around the label.
- * Symbols are predefined functions on the Renderer object.
- *
- * @sample highcharts/annotations/shapes/
- * Available shapes for labels
- *
- * @type {string}
- */
- shape: 'callout',
- /**
- * Styles for the annotation's label.
- *
- * @see [plotOptions.series.dataLabels.style](plotOptions.series.dataLabels.style.html)
- *
- * @sample highcharts/annotations/label-presentation/
- * Set labels graphic options
- *
- * @type {Highcharts.CSSObject}
- */
- style: {
- /** @ignore */
- fontSize: '11px',
- /** @ignore */
- fontWeight: 'normal',
- /** @ignore */
- color: 'contrast'
- },
- /**
- * Whether to [use HTML](https://www.highcharts.com/docs/chart-concepts/labels-and-string-formatting#html)
- * to render the annotation's label.
- */
- useHTML: false,
- /**
- * The vertical alignment of the annotation's label.
- *
- * @sample highcharts/annotations/label-position/
- * Set labels position
- *
- * @type {Highcharts.VerticalAlignType}
- */
- verticalAlign: 'bottom',
- /**
- * The x position offset of the label relative to the point.
- * Note that if a `distance` is defined, the distance takes
- * precedence over `x` and `y` options.
- *
- * @sample highcharts/annotations/label-position/
- * Set labels position
- */
- x: 0,
- /**
- * The y position offset of the label relative to the point.
- * Note that if a `distance` is defined, the distance takes
- * precedence over `x` and `y` options.
- *
- * @sample highcharts/annotations/label-position/
- * Set labels position
- */
- y: -16
- },
- /**
- * An array of labels for the annotation. For options that apply to
- * multiple labels, they can be added to the
- * [labelOptions](annotations.labelOptions.html).
- *
- * @type {Array<*>}
- * @extends annotations.labelOptions
- * @apioption annotations.labels
- */
- /**
- * This option defines the point to which the label will be connected.
- * It can be either the point which exists in the series - it is
- * referenced by the point's id - or a new point with defined x, y
- * properies and optionally axes.
- *
- * @sample highcharts/annotations/mock-point/
- * Attach annotation to a mock point
- *
- * @type {string|*}
- * @apioption annotations.labels.point
- */
- /**
- * The x position of the point. Units can be either in axis
- * or chart pixel coordinates.
- *
- * @type {number}
- * @apioption annotations.labels.point.x
- */
- /**
- * The y position of the point. Units can be either in axis
- * or chart pixel coordinates.
- *
- * @type {number}
- * @apioption annotations.labels.point.y
- */
- /**
- * This number defines which xAxis the point is connected to. It refers
- * to either the axis id or the index of the axis in the xAxis array.
- * If the option is not configured or the axis is not found the point's
- * x coordinate refers to the chart pixels.
- *
- * @type {number|string}
- * @apioption annotations.labels.point.xAxis
- */
- /**
- * This number defines which yAxis the point is connected to. It refers
- * to either the axis id or the index of the axis in the yAxis array.
- * If the option is not configured or the axis is not found the point's
- * y coordinate refers to the chart pixels.
- *
- * @type {number|string}
- * @apioption annotations.labels.point.yAxis
- */
- /**
- * An array of shapes for the annotation. For options that apply to
- * multiple shapes, then can be added to the
- * [shapeOptions](annotations.shapeOptions.html).
- *
- * @type {Array<*>}
- * @extends annotations.shapeOptions
- * @apioption annotations.shapes
- */
- /**
- * This option defines the point to which the shape will be connected.
- * It can be either the point which exists in the series - it is
- * referenced by the point's id - or a new point with defined x, y
- * properties and optionally axes.
- *
- * @extends annotations.labels.point
- * @apioption annotations.shapes.point
- */
- /**
- * An array of points for the shape. This option is available for shapes
- * which can use multiple points such as path. A point can be either
- * a point object or a point's id.
- *
- * @see [annotations.shapes.point](annotations.shapes.point.html)
- *
- * @type {Array<*>}
- * @extends annotations.labels.point
- * @apioption annotations.shapes.points
- */
- /**
- * Id of the marker which will be drawn at the final vertex of the path.
- * Custom markers can be defined in defs property.
- *
- * @see [defs.markers](defs.markers.html)
- *
- * @sample highcharts/annotations/custom-markers/
- * Define a custom marker for annotations
- *
- * @type {string}
- * @apioption annotations.shapes.markerEnd
- */
- /**
- * Id of the marker which will be drawn at the first vertex of the path.
- * Custom markers can be defined in defs property.
- *
- * @see [defs.markers](defs.markers.html)
- *
- * @sample {highcharts} highcharts/annotations/custom-markers/
- * Define a custom marker for annotations
- *
- * @type {string}
- * @apioption annotations.shapes.markerStart
- */
- /**
- * Options for annotation's shapes. Each shape inherits options
- * from the shapeOptions object. An option from the shapeOptions can be
- * overwritten by config for a specific shape.
- */
- shapeOptions: {
- /**
- * The width of the shape.
- *
- * @sample highcharts/annotations/shape/
- * Basic shape annotation
- *
- * @type {number}
- * @apioption annotations.shapeOptions.width
- **/
- /**
- * The height of the shape.
- *
- * @sample highcharts/annotations/shape/
- * Basic shape annotation
- *
- * @type {number}
- * @apioption annotations.shapeOptions.height
- */
- /**
- * The color of the shape's stroke.
- *
- * @sample highcharts/annotations/shape/
- * Basic shape annotation
- *
- * @type {Highcharts.ColorString}
- */
- stroke: 'rgba(0, 0, 0, 0.75)',
- /**
- * The pixel stroke width of the shape.
- *
- * @sample highcharts/annotations/shape/
- * Basic shape annotation
- */
- strokeWidth: 1,
- /**
- * The color of the shape's fill.
- *
- * @sample highcharts/annotations/shape/
- * Basic shape annotation
- *
- * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
- */
- fill: 'rgba(0, 0, 0, 0.75)',
- /**
- * The type of the shape, e.g. circle or rectangle.
- *
- * @sample highcharts/annotations/shape/
- * Basic shape annotation
- *
- * @type {string}
- * @default 'rect'
- * @apioption annotations.shapeOptions.type
- */
- /**
- * The radius of the shape.
- *
- * @sample highcharts/annotations/shape/
- * Basic shape annotation
- */
- r: 0
- },
- /**
- * The Z index of the annotation.
- */
- zIndex: 6
- },
- /**
- * Initialize the annotation.
- *
- * @function Highcharts.Annotation#init
- */
- init: function () {
- var anno = this;
- (this.options.labels || []).forEach(this.initLabel, this);
- (this.options.shapes || []).forEach(this.initShape, this);
- this.labelCollector = function () {
- return anno.labels.filter(function (label) {
- return !label.options.allowOverlap;
- });
- };
- this.chart.labelCollectors.push(this.labelCollector);
- },
- /**
- * Main method for drawing an annotation.
- *
- * @function Highcharts.Annotation#redraw
- */
- redraw: function () {
- if (!this.group) {
- this.render();
- }
- this.redrawItems(this.shapes);
- this.redrawItems(this.labels);
- },
- /**
- * @private
- * @function Highcharts.Annotation#redrawItems
- *
- * @param {Array<Highcharts.SVGElement>} items
- */
- redrawItems: function (items) {
- var i = items.length;
- // needs a backward loop
- // labels/shapes array might be modified due to destruction of the item
- while (i--) {
- this.redrawItem(items[i]);
- }
- },
- /**
- * Render the annotation.
- *
- * @function Highcharts.Annotation#render
- */
- render: function () {
- var renderer = this.chart.renderer;
- var group = this.group = renderer.g('annotation')
- .attr({
- zIndex: this.options.zIndex,
- visibility: this.options.visible ? 'visible' : 'hidden'
- })
- .add();
- this.shapesGroup = renderer.g('annotation-shapes').add(group);
- this.labelsGroup = renderer.g('annotation-labels').attr({
- // hideOverlappingLabels requires translation
- translateX: 0,
- translateY: 0
- }).add(group);
- this.shapesGroup.clip(this.chart.plotBoxClip);
- },
- /**
- * Set the annotation's visibility.
- *
- * @function Highcharts.Annotation#setVisible
- *
- * @param {boolean} [visibility]
- * Whether to show or hide an annotation. If the param is omitted,
- * the annotation's visibility is toggled.
- */
- setVisible: function (visibility) {
- var options = this.options,
- visible = pick(visibility, !options.visible);
- this.group.attr({
- visibility: visible ? 'visible' : 'hidden'
- });
- options.visible = visible;
- },
- /**
- * Destroy the annotation. This function does not touch the chart
- * that the annotation belongs to (all annotations are kept in
- * the chart.annotations array) - it is recommended to use
- * {@link Highcharts.Chart#removeAnnotation} instead.
- *
- * @function Highcharts.Annotation#destroy
- */
- destroy: function () {
- var chart = this.chart,
- destroyItem = function (item) {
- item.destroy();
- };
- erase(this.chart.labelCollectors, this.labelCollector);
- this.labels.forEach(destroyItem);
- this.shapes.forEach(destroyItem);
- destroyObjectProperties(this, chart);
- },
- /* ********************************************************************** *
- *
- * ITEM SECTION
- * Contains methods for handling a single item in an annotation
- *
- * ********************************************************************** */
- /**
- * Initialisation of a single shape
- *
- * @private
- * @function Highcharts.Annotation#initShape
- *
- * @param {Highcharts.AnnotationsShapesOptions} shapeOptions
- * A confg object for a single shape
- */
- initShape: function (shapeOptions) {
- var renderer = this.chart.renderer,
- options = merge(this.options.shapeOptions, shapeOptions),
- attr = this.attrsFromOptions(options),
- type = renderer[options.type] ? options.type : 'rect',
- shape = renderer[type](0, -9e9, 0, 0);
- shape.points = [];
- shape.type = type;
- shape.options = options;
- shape.itemType = 'shape';
- if (type === 'path') {
- extend(shape, {
- markerStartSetter: MarkerMixin.markerStartSetter,
- markerEndSetter: MarkerMixin.markerEndSetter,
- markerStart: MarkerMixin.markerStart,
- markerEnd: MarkerMixin.markerEnd
- });
- }
- shape.attr(attr);
- if (options.className) {
- shape.addClass(options.className);
- }
- this.shapes.push(shape);
- },
- /**
- * Initialisation of a single label
- *
- * @private
- * @function Highcharts.Annotation#initLabel
- *
- * @param {Highcharts.AnnotationsLabelsOptions} labelOptions
- */
- initLabel: function (labelOptions) {
- var options = merge(this.options.labelOptions, labelOptions),
- attr = this.attrsFromOptions(options),
- label = this.chart.renderer.label(
- '',
- 0, -9e9,
- options.shape,
- null,
- null,
- options.useHTML,
- null,
- 'annotation-label'
- );
- label.points = [];
- label.options = options;
- label.itemType = 'label';
- // Labelrank required for hideOverlappingLabels()
- label.labelrank = options.labelrank;
- label.annotation = this;
- label.attr(attr);
- if (!this.chart.styledMode) {
- var style = options.style;
- if (style.color === 'contrast') {
- style.color = this.chart.renderer.getContrast(
- this.shapesWithoutBackground.indexOf(options.shape) > -1 ?
- '#FFFFFF' :
- options.backgroundColor
- );
- }
- label.css(style).shadow(options.shadow);
- }
- if (options.className) {
- label.addClass(options.className);
- }
- this.labels.push(label);
- },
- /**
- * Redrawing a single item
- *
- * @private
- * @function Highcharts.Annotation#redrawItem
- *
- * @param {Highcharts.SVGElement} item
- */
- redrawItem: function (item) {
- var points = this.linkPoints(item),
- itemOptions = item.options,
- text,
- time = this.chart.time,
- hasVisiblePoints = false;
- if (!points.length) {
- this.destroyItem(item);
- } else {
- if (!item.parentGroup) {
- this.renderItem(item);
- }
- if (item.itemType === 'label') {
- text = itemOptions.format || itemOptions.text;
- item.attr({
- text: text ?
- format(text, points[0].getLabelConfig(), time) :
- itemOptions.formatter.call(points[0])
- });
- }
- // Hide or show annotaiton attached to points (#9481)
- points.forEach(function (point) {
- if (
- point.series.visible !== false &&
- point.visible !== false
- ) {
- hasVisiblePoints = true;
- }
- });
- if (!hasVisiblePoints) {
- item.hide();
- } else if (item.visibility === 'hidden') {
- item.show();
- }
- if (item.type === 'path') {
- this.redrawPath(item);
- } else {
- this.alignItem(item, !item.placed);
- }
- }
- },
- /**
- * Destroing a single item
- *
- * @private
- * @function Highcharts.Annotation#destroyItem
- *
- * @param {Highcharts.SVGElement} item
- */
- destroyItem: function (item) {
- // erase from shapes or labels array
- erase(this[item.itemType + 's'], item);
- item.destroy();
- },
- /**
- * Returns a point object
- *
- * @private
- * @function Highcharts.Annotation#pointItem
- *
- * @param {object} pointOptions
- *
- * @param {Highcharts.MockPoint|Highcharts.Point} point
- *
- * @return {Highcharts.MockPoint|Highcharts.Point|null}
- * If the point is found/exists returns this point, otherwise null
- */
- pointItem: function (pointOptions, point) {
- if (!point || point.series === null) {
- if (isObject(pointOptions)) {
- point = mockPoint(this.chart, pointOptions);
- } else if (isString(pointOptions)) {
- point = this.chart.get(pointOptions) || null;
- }
- }
- return point;
- },
- /**
- * Linking item with the point or points and returning an array of linked
- * points.
- *
- * @private
- * @function Highcharts.Annotation#linkPoints
- *
- * @param {Highcharts.SVGElement} item
- *
- * @return {Highcharts.MockPoint|Highcharts.Point|Array<Highcharts.MockPoint|Highcharts.Point>}
- */
- linkPoints: function (item) {
- var pointsOptions = (
- item.options.points ||
- (item.options.point && H.splat(item.options.point))
- ),
- points = item.points,
- len = pointsOptions && pointsOptions.length,
- i,
- point;
- for (i = 0; i < len; i++) {
- point = this.pointItem(pointsOptions[i], points[i]);
- if (!point) {
- return (item.points = []);
- }
- points[i] = point;
- }
- return points;
- },
- /**
- * Aligning the item and setting its anchor
- *
- * @private
- * @function Highcharts.Annotation#alignItem
- *
- * @param {Highcharts.SVGElement} item
- *
- * @param {boolean} [isNew=false]
- * If the label is re-positioned (is not new) it is animated
- */
- alignItem: function (item, isNew) {
- var anchor = this.itemAnchor(item, item.points[0]),
- attrs = this.itemPosition(item, anchor);
- if (attrs) {
- item.alignAttr = attrs;
- item.placed = true;
- attrs.anchorX = anchor.absolutePosition.x;
- attrs.anchorY = anchor.absolutePosition.y;
- item[isNew ? 'attr' : 'animate'](attrs);
- } else {
- item.placed = false;
- item.attr({
- x: 0,
- y: -9e9
- });
- }
- },
- redrawPath: function (pathItem, isNew) {
- var points = pathItem.points,
- strokeWidth = pathItem['stroke-width'] || 1,
- d = ['M'],
- pointIndex = 0,
- dIndex = 0,
- len = points && points.length,
- crispSegmentIndex,
- anchor,
- point,
- showPath;
- if (len) {
- do {
- point = points[pointIndex];
- anchor = this.itemAnchor(pathItem, point).absolutePosition;
- d[++dIndex] = anchor.x;
- d[++dIndex] = anchor.y;
- // Crisping line, it might be replaced with
- // Renderer.prototype.crispLine but it requires creating many
- // temporary arrays
- crispSegmentIndex = dIndex % 5;
- if (crispSegmentIndex === 0) {
- if (d[crispSegmentIndex + 1] === d[crispSegmentIndex + 4]) {
- d[crispSegmentIndex + 1] = d[crispSegmentIndex + 4] =
- Math.round(d[crispSegmentIndex + 1]) -
- (strokeWidth % 2 / 2);
- }
- if (d[crispSegmentIndex + 2] === d[crispSegmentIndex + 5]) {
- d[crispSegmentIndex + 2] = d[crispSegmentIndex + 5] =
- Math.round(d[crispSegmentIndex + 2]) +
- (strokeWidth % 2 / 2);
- }
- }
- if (pointIndex < len - 1) {
- d[++dIndex] = 'L';
- }
- showPath = point.series.visible;
- } while (++pointIndex < len && showPath);
- }
- if (showPath) {
- pathItem[isNew ? 'attr' : 'animate']({
- d: d
- });
- } else {
- pathItem.attr({
- d: 'M 0 ' + -9e9
- });
- }
- pathItem.placed = showPath;
- },
- renderItem: function (item) {
- item.add(
- item.itemType === 'label' ?
- this.labelsGroup :
- this.shapesGroup
- );
- this.setItemMarkers(item);
- },
- setItemMarkers: function (item) {
- var itemOptions = item.options,
- chart = this.chart,
- defs = chart.options.defs,
- fill = itemOptions.fill,
- color = defined(fill) && fill !== 'none' ?
- fill :
- itemOptions.stroke,
- setMarker = function (markerType) {
- var markerId = itemOptions[markerType],
- def,
- predefinedMarker,
- key,
- marker;
- if (markerId) {
- for (key in defs) {
- def = defs[key];
- if (markerId === def.id && def.tagName === 'marker') {
- predefinedMarker = def;
- break;
- }
- }
- if (predefinedMarker) {
- marker = item[markerType] = chart.renderer.addMarker(
- (itemOptions.id || uniqueKey()) + '-' +
- predefinedMarker.id,
- merge(predefinedMarker, { color: color })
- );
- item.attr(markerType, marker.attr('id'));
- }
- }
- };
- ['markerStart', 'markerEnd'].forEach(setMarker);
- },
- /**
- * Returns object which denotes anchor position - relative and absolute
- *
- * @private
- * @function Highcharts.Annotation#itemAnchor
- *
- * @param {Highcharts.SVGElement} item
- *
- * @param {Highcharts.MockPoint|Highcharts.Point} point
- *
- * @return {Highcharts.AnnotationAnchorObject}
- */
- itemAnchor: function (item, point) {
- var plotBox = point.series.getPlotBox(),
- box = point.mock ?
- point.alignToBox(true) :
- tooltipPrototype.getAnchor.call({
- chart: this.chart
- }, point),
- anchor = {
- x: box[0],
- y: box[1],
- height: box[2] || 0,
- width: box[3] || 0
- };
- return {
- relativePosition: anchor,
- absolutePosition: merge(anchor, {
- x: anchor.x + plotBox.translateX,
- y: anchor.y + plotBox.translateY
- })
- };
- },
- /**
- * Returns the item position
- *
- * @private
- * @function Highcharts.Annotation#itemPosition
- *
- * @param {Highcharts.SVGElement} item
- *
- * @param {Highcharts.AnnotationAnchorObject} anchor
- *
- * @return {Highcharts.AnnotationAnchorPositionObject}
- */
- itemPosition: function (item, anchor) {
- var chart = this.chart,
- point = item.points[0],
- itemOptions = item.options,
- anchorAbsolutePosition = anchor.absolutePosition,
- anchorRelativePosition = anchor.relativePosition,
- itemPosition,
- alignTo,
- itemPosRelativeX,
- itemPosRelativeY,
- showItem =
- point.series.visible &&
- MockPoint.prototype.isInsidePane.call(point);
- if (showItem) {
- if (defined(itemOptions.distance) || itemOptions.positioner) {
- itemPosition = (
- itemOptions.positioner ||
- tooltipPrototype.getPosition
- ).call(
- {
- chart: chart,
- distance: pick(itemOptions.distance, 16)
- },
- item.width,
- item.height,
- {
- plotX: anchorRelativePosition.x,
- plotY: anchorRelativePosition.y,
- negative: point.negative,
- ttBelow: point.ttBelow,
- h: anchorRelativePosition.height ||
- anchorRelativePosition.width
- }
- );
- } else {
- alignTo = {
- x: anchorAbsolutePosition.x,
- y: anchorAbsolutePosition.y,
- width: 0,
- height: 0
- };
- itemPosition = this.alignedPosition(
- extend(itemOptions, {
- width: item.width,
- height: item.height
- }),
- alignTo
- );
- if (item.options.overflow === 'justify') {
- itemPosition = this.alignedPosition(
- this.justifiedOptions(item, itemOptions, itemPosition),
- alignTo
- );
- }
- }
- if (itemOptions.crop) {
- itemPosRelativeX = itemPosition.x - chart.plotLeft;
- itemPosRelativeY = itemPosition.y - chart.plotTop;
- showItem =
- chart.isInsidePlot(itemPosRelativeX, itemPosRelativeY) &&
- chart.isInsidePlot(
- itemPosRelativeX + item.width,
- itemPosRelativeY + item.height
- );
- }
- }
- return showItem ? itemPosition : null;
- },
- /**
- * Returns new aligned position based alignment options and box to align to.
- * It is almost a one-to-one copy from SVGElement.prototype.align
- * except it does not use and mutate an element
- *
- * @private
- * @function Highcharts.Annotation#alignedPosition
- *
- * @param {Highcharts.AlignObject} alignOptions
- *
- * @param {Highcharts.BBoxObject} box
- *
- * @return {Highcharts.AlignObject}
- */
- alignedPosition: function (alignOptions, box) {
- var align = alignOptions.align,
- vAlign = alignOptions.verticalAlign,
- x = (box.x || 0) + (alignOptions.x || 0),
- y = (box.y || 0) + (alignOptions.y || 0),
- alignFactor,
- vAlignFactor;
- if (align === 'right') {
- alignFactor = 1;
- } else if (align === 'center') {
- alignFactor = 2;
- }
- if (alignFactor) {
- x += (box.width - (alignOptions.width || 0)) / alignFactor;
- }
- if (vAlign === 'bottom') {
- vAlignFactor = 1;
- } else if (vAlign === 'middle') {
- vAlignFactor = 2;
- }
- if (vAlignFactor) {
- y += (box.height - (alignOptions.height || 0)) / vAlignFactor;
- }
- return {
- x: Math.round(x),
- y: Math.round(y)
- };
- },
- /**
- * Returns new alignment options for a label if the label is outside the
- * plot area. It is almost a one-to-one copy from
- * Series.prototype.justifyDataLabel except it does not mutate the label and
- * it works with absolute instead of relative position.
- *
- * @private
- * @function Highcharts.Annotation#justifiedOptions
- *
- * @param {Highcharts.SVGElement} label
- *
- * @param {Highcharts.AlignObject} alignOptions
- *
- * @param {Highcharts.SVGAttributes} alignAttr
- *
- * @return {Highcharts.AlignObject}
- */
- justifiedOptions: function (label, alignOptions, alignAttr) {
- var chart = this.chart,
- align = alignOptions.align,
- verticalAlign = alignOptions.verticalAlign,
- padding = label.box ? 0 : (label.padding || 0),
- bBox = label.getBBox(),
- off,
- options = {
- align: align,
- verticalAlign: verticalAlign,
- x: alignOptions.x,
- y: alignOptions.y,
- width: label.width,
- height: label.height
- },
- x = alignAttr.x - chart.plotLeft,
- y = alignAttr.y - chart.plotTop;
- // Off left
- off = x + padding;
- if (off < 0) {
- if (align === 'right') {
- options.align = 'left';
- } else {
- options.x = -off;
- }
- }
- // Off right
- off = x + bBox.width - padding;
- if (off > chart.plotWidth) {
- if (align === 'left') {
- options.align = 'right';
- } else {
- options.x = chart.plotWidth - off;
- }
- }
- // Off top
- off = y + padding;
- if (off < 0) {
- if (verticalAlign === 'bottom') {
- options.verticalAlign = 'top';
- } else {
- options.y = -off;
- }
- }
- // Off bottom
- off = y + bBox.height - padding;
- if (off > chart.plotHeight) {
- if (verticalAlign === 'top') {
- options.verticalAlign = 'bottom';
- } else {
- options.y = chart.plotHeight - off;
- }
- }
- return options;
- },
- /**
- * Utility function for mapping item's options to element's attribute
- *
- * @private
- * @function Highcharts.Annotation#attrsFromOptions
- *
- * @param {object} options
- *
- * @return {object}
- * Mapped options
- */
- attrsFromOptions: function (options) {
- var map = this.getAttrsMap(),
- attrs = {},
- key,
- mappedKey;
- for (key in options) {
- mappedKey = map[key];
- if (mappedKey) {
- attrs[mappedKey] = options[key];
- }
- }
- return attrs;
- }
- };
- /* ************************************************************************** *
- *
- * EXTENDING CHART PROTOTYPE
- *
- * ************************************************************************** */
- H.extend(chartPrototype, {
- /**
- * Add an annotation to the chart after render time.
- *
- * @function Highcharts.Chart#addAnnotation
- *
- * @param {Highcharts.AnnotationsOptions} options
- * The series options for the new, detailed series.
- *
- * @return {Highcharts.Annotation}
- * The newly generated annotation.
- */
- addAnnotation: function (userOptions, redraw) {
- var annotation = new Annotation(this, userOptions);
- this.annotations.push(annotation);
- this.options.annotations.push(userOptions);
- if (pick(redraw, true)) {
- annotation.redraw();
- }
- return annotation;
- },
- /**
- * Remove an annotation from the chart.
- *
- * @function Highcharts.Chart#removeAnnotation
- *
- * @param {string} id
- * The annotation's id.
- */
- removeAnnotation: function (id) {
- var annotations = this.annotations,
- annotation = find(annotations, function (annotation) {
- return annotation.options.id === id;
- });
- if (annotation) {
- erase(this.options.annotations, annotation.userOptions);
- erase(annotations, annotation);
- annotation.destroy();
- }
- },
- drawAnnotations: function () {
- var clip = this.plotBoxClip,
- plotBox = this.plotBox;
- if (clip) {
- clip.attr(plotBox);
- } else {
- this.plotBoxClip = this.renderer.clipRect(plotBox);
- }
- this.annotations.forEach(function (annotation) {
- annotation.redraw();
- });
- }
- });
- chartPrototype.callbacks.push(function (chart) {
- chart.annotations = [];
- chart.options.annotations.forEach(function (annotationOptions) {
- chart.annotations.push(
- new Annotation(chart, annotationOptions)
- );
- });
- chart.drawAnnotations();
- addEvent(chart, 'redraw', chart.drawAnnotations);
- addEvent(chart, 'destroy', function () {
- var plotBoxClip = chart.plotBoxClip;
- if (plotBoxClip && plotBoxClip.destroy) {
- plotBoxClip.destroy();
- }
- });
- });
- addEvent(H.Chart, 'afterGetContainer', function () {
- this.options.defs = merge(defaultMarkers, this.options.defs || {});
- if (!this.styledMode) {
- objectEach(this.options.defs, function (def) {
- if (def.tagName === 'marker' && def.render !== false) {
- this.renderer.addMarker(def.id, def);
- }
- }, this);
- }
- });
- /* ************************************************************************** */
- // General symbol definition for labels with connector
- H.SVGRenderer.prototype.symbols.connector = function (x, y, w, h, options) {
- var anchorX = options && options.anchorX,
- anchorY = options && options.anchorY,
- path,
- yOffset,
- lateral = w / 2;
- if (isNumber(anchorX) && isNumber(anchorY)) {
- path = ['M', anchorX, anchorY];
- // Prefer 45 deg connectors
- yOffset = y - anchorY;
- if (yOffset < 0) {
- yOffset = -h - yOffset;
- }
- if (yOffset < w) {
- lateral = anchorX < x + (w / 2) ? yOffset : w - yOffset;
- }
- // Anchor below label
- if (anchorY > y + h) {
- path.push('L', x + lateral, y + h);
- // Anchor above label
- } else if (anchorY < y) {
- path.push('L', x + lateral, y);
- // Anchor left of label
- } else if (anchorX < x) {
- path.push('L', x, y + h / 2);
- // Anchor right of label
- } else if (anchorX > x + w) {
- path.push('L', x + w, y + h / 2);
- }
- }
- return path || [];
- };
|