diff --git a/docs/guide/types/box.md b/docs/guide/types/box.md index 17ec716a3..da753f0f9 100644 --- a/docs/guide/types/box.md +++ b/docs/guide/types/box.md @@ -75,6 +75,7 @@ The following options are available for box annotations. | [`yMin`](#general) | `number` \| `string` | Yes | `undefined` | [`yMax`](#general) | `number` \| `string` | Yes | `undefined` | [`yScaleID`](#general) | `string` | Yes | `undefined` +| [`z`](#general) | `number` | Yes | `0` ### General @@ -92,6 +93,7 @@ If one of the axes does not match an axis in the chart, the box will take the en | `yMax` | Bottom edge of the box in units along the y axis. | `yMin` | Top edge of the box in units along the y axis. | `yScaleID` | ID of the Y scale to bind onto. If missing, the plugin will try to use the scale of the chart, configured as `'y'` axis. If more than one scale has been defined in the chart as `'y'` axis, the option is mandatory to select the right scale. +| `z` | The `z` property determines the drawing stack level of the box annotation element. All visible elements will be drawn in ascending order of `z` option, with the same `drawTime` option. ### Styling @@ -138,6 +140,7 @@ All of these options can be [Scriptable](../options#scriptable-options) | `width` | `number`\|`string` | `undefined` | Overrides the width of the image or canvas element. Could be set in pixel by a number, or in percentage of current width of image or canvas element by a string. If undefined, uses the width of the image or canvas element. It is used only when the content is an image or canvas element. | `xAdjust` | `number` | `0` | Adjustment along x-axis (left-right) of label relative to computed position. Negative values move the label left, positive right. | `yAdjust` | `number` | `0` | Adjustment along y-axis (top-bottom) of label relative to computed position. Negative values move the label up, positive down. +| `z` | `number` | `0` | It determines the drawing stack level of the label element, with same `drawTime`. ### Position diff --git a/docs/guide/types/ellipse.md b/docs/guide/types/ellipse.md index 71aa686ca..b6e328539 100644 --- a/docs/guide/types/ellipse.md +++ b/docs/guide/types/ellipse.md @@ -71,6 +71,7 @@ The following options are available for ellipse annotations. | [`yMax`](#general) | `number` \| `string` | Yes | `undefined` | [`yMin`](#general) | `number` \| `string` | Yes | `undefined` | [`yScaleID`](#general) | `string` | Yes | `undefined` +| [`z`](#general) | `number` | Yes | `0` ### General @@ -88,6 +89,7 @@ If one of the axes does not match an axis in the chart, the ellipse will take th | `yMax` | Bottom edge of the ellipse in units along the y axis. | `yMin` | Top edge of the ellipse in units along the y axis. | `yScaleID` | ID of the Y scale to bind onto. If missing, the plugin will try to use the scale of the chart, configured as `'y'` axis. If more than one scale has been defined in the chart as `'y'` axis, the option is mandatory to select the right scale. +| `z` | The `z` property determines the drawing stack level of the ellipse annotation element. All visible elements will be drawn in ascending order of `z` option, with the same `drawTime` option. ### Styling diff --git a/docs/guide/types/label.md b/docs/guide/types/label.md index 19febdeb2..9ffb50890 100644 --- a/docs/guide/types/label.md +++ b/docs/guide/types/label.md @@ -91,6 +91,7 @@ The following options are available for label annotations. | [`yMin`](#general) | `number` \| `string` | Yes | `undefined` | [`yScaleID`](#general) | `string` | Yes | `undefined` | [`yValue`](#general) | `number` \| `string` | Yes | `undefined` +| [`z`](#general) | `number` | Yes | `0` ### General @@ -119,6 +120,7 @@ The 4 coordinates, xMin, xMax, yMin, yMax are optional. If not specified, the bo | `yMin` | Top edge of the box in units along the y axis. | `yScaleID` | ID of the Y scale to bind onto. If missing, the plugin will try to use the scale of the chart, configured as `'y'` axis. If more than one scale has been defined in the chart as `'y'` axis, the option is mandatory to select the right scale. | `yValue` | Y coordinate of the point in units along the y axis. +| `z` | The `z` property determines the drawing stack level of the label annotation element. All visible elements will be drawn in ascending order of `z` option, with the same `drawTime` option. ### Styling diff --git a/docs/guide/types/line.md b/docs/guide/types/line.md index 07037feeb..3af178c6f 100644 --- a/docs/guide/types/line.md +++ b/docs/guide/types/line.md @@ -72,6 +72,7 @@ The following options are available for line annotations. All of these options c | [`yMax`](#general) | `number` \| `string` | Yes | `undefined` | [`yMin`](#general) | `number` \| `string` | Yes | `undefined` | [`yScaleID`](#positioning) | `string` | Yes | `undefined` +| [`z`](#general) | `number` | Yes | `0` ### General @@ -89,6 +90,7 @@ The 4 coordinates, xMin, xMax, yMin, yMax are optional. If not specified, the li | `adjustScaleRange` | Should the scale range be adjusted if this annotation is out of range. | `display` | Whether or not this annotation is visible. | `drawTime` | See [drawTime](../options#draw-time). +| `z` | The `z` property determines the drawing stack level of the line annotation element. All visible elements will be drawn in ascending order of `z` option, with the same `drawTime` option. ### Positioning @@ -157,6 +159,7 @@ All of these options can be [Scriptable](../options#scriptable-options) | `width` | `number`\|`string` | `undefined` | Overrides the width of the image or canvas element. Could be set in pixel by a number, or in percentage of current width of image or canvas element by a string. If undefined, uses the width of the image or canvas element. It is used only when the content is an image or canvas element. | `xAdjust` | `number` | `0` | Adjustment along x-axis (left-right) of label relative to computed position. Negative values move the label left, positive right. | `yAdjust` | `number` | `0` | Adjustment along y-axis (top-bottom) of label relative to computed position. Negative values move the label up, positive down. +| `z` | `number` | `0` | It determines the drawing stack level of the label element, with same `drawTime`. ### borderRadius diff --git a/docs/guide/types/point.md b/docs/guide/types/point.md index faa852869..3519d1c35 100644 --- a/docs/guide/types/point.md +++ b/docs/guide/types/point.md @@ -75,6 +75,7 @@ The following options are available for point annotations. | [`yMin`](#general) | `number` \| `string` | Yes | `undefined` | [`yScaleID`](#general) | `string` | Yes | `undefined` | [`yValue`](#general) | `number` \| `string` | Yes | `undefined` +| [`z`](#general) | `number` | Yes | `0` ### General @@ -99,6 +100,7 @@ The 4 coordinates, xMin, xMax, yMin, yMax are optional. If not specified, the bo | `yMin` | Top edge of the box in units along the y axis. | `yScaleID` | ID of the Y scale to bind onto. If missing, the plugin will try to use the scale of the chart, configured as `'y'` axis. If more than one scale has been defined in the chart as `'y'` axis, the option is mandatory to select the right scale. | `yValue` | Y coordinate of the point in units along the y axis. +| `z` | The `z` property determines the drawing stack level of the point annotation element. All visible elements will be drawn in ascending order of `z` option, with the same `drawTime` option. ### Styling diff --git a/docs/guide/types/polygon.md b/docs/guide/types/polygon.md index 435124478..027f7e477 100644 --- a/docs/guide/types/polygon.md +++ b/docs/guide/types/polygon.md @@ -80,6 +80,7 @@ The following options are available for polygon annotations. | [`yMax`](#general) | `number` \| `string` | Yes | `undefined` | [`yMin`](#general) | `number` \| `string` | Yes | `undefined` | [`yValue`](#general) | `number` \| `string` | Yes | `undefined` +| [`z`](#general) | `number` | Yes | `0` ### General @@ -105,6 +106,7 @@ The 4 coordinates, xMin, xMax, yMin, yMax are optional. If not specified, the bo | `yMin` | Top edge of the box in units along the y axis. | `yScaleID` | ID of the Y scale to bind onto. If missing, the plugin will try to use the scale of the chart, configured as `'y'` axis. If more than one scale has been defined in the chart as `'y'` axis, the option is mandatory to select the right scale. | `yValue` | Y coordinate of the polygon in units along the y axis. +| `z` | The `z` property determines the drawing stack level of the polygon annotation element. All visible elements will be drawn in ascending order of `z` option, with the same `drawTime` option. ### Styling diff --git a/src/annotation.js b/src/annotation.js index db8e1eb60..183fd6b96 100644 --- a/src/annotation.js +++ b/src/annotation.js @@ -150,25 +150,31 @@ function draw(chart, caller, clip) { area = chartArea; } - drawElements(chart, visibleElements, caller, area); + const drawableElements = getDrawableElements(visibleElements, caller, area).sort((a, b) => a.element.options.z - b.element.options.z); + + for (const item of drawableElements) { + item.element.draw(chart.ctx, item.area); + } if (clip) { unclipArea(ctx); } } -function drawElements(chart, elements, caller, area) { +function getDrawableElements(elements, caller, area) { + const drawableElements = []; for (const el of elements) { if (el.options.drawTime === caller) { - el.draw(chart.ctx, area); + drawableElements.push({element: el, area}); } if (el.elements && el.elements.length) { const box = 'getBoundingBox' in el ? el.getBoundingBox() : area; for (const sub of el.elements) { if (sub.options.display && sub.options.drawTime === caller) { - sub.draw(chart.ctx, box); + drawableElements.push({element: sub, area: box}); } } } } + return drawableElements; } diff --git a/src/types/box.js b/src/types/box.js index 6f3cbf104..32a726e74 100644 --- a/src/types/box.js +++ b/src/types/box.js @@ -88,9 +88,10 @@ BoxAnnotation.defaults = { textAlign: 'start', textStrokeColor: undefined, textStrokeWidth: 0, + width: undefined, xAdjust: 0, yAdjust: 0, - width: undefined + z: undefined }, rotation: 0, shadowBlur: 0, @@ -101,7 +102,8 @@ BoxAnnotation.defaults = { xScaleID: undefined, yMax: undefined, yMin: undefined, - yScaleID: undefined + yScaleID: undefined, + z: 0 }; BoxAnnotation.defaultRoutes = { diff --git a/src/types/ellipse.js b/src/types/ellipse.js index de6b01f40..e6a4783fb 100644 --- a/src/types/ellipse.js +++ b/src/types/ellipse.js @@ -64,7 +64,8 @@ EllipseAnnotation.defaults = { xScaleID: undefined, yMax: undefined, yMin: undefined, - yScaleID: undefined + yScaleID: undefined, + z: 0 }; EllipseAnnotation.defaultRoutes = { diff --git a/src/types/label.js b/src/types/label.js index e6074309f..1f45446a5 100644 --- a/src/types/label.js +++ b/src/types/label.js @@ -110,7 +110,8 @@ LabelAnnotation.defaults = { yMax: undefined, yMin: undefined, yScaleID: undefined, - yValue: undefined + yValue: undefined, + z: 0 }; LabelAnnotation.defaultRoutes = { diff --git a/src/types/line.js b/src/types/line.js index 78b871dca..78504d45f 100644 --- a/src/types/line.js +++ b/src/types/line.js @@ -173,7 +173,8 @@ LineAnnotation.defaults = { textStrokeWidth: 0, width: undefined, xAdjust: 0, - yAdjust: 0 + yAdjust: 0, + z: undefined }, scaleID: undefined, shadowBlur: 0, @@ -185,7 +186,8 @@ LineAnnotation.defaults = { xScaleID: undefined, yMax: undefined, yMin: undefined, - yScaleID: undefined + yScaleID: undefined, + z: 0 }; LineAnnotation.descriptors = { diff --git a/src/types/point.js b/src/types/point.js index 967df85b1..97c0dd039 100644 --- a/src/types/point.js +++ b/src/types/point.js @@ -69,7 +69,8 @@ PointAnnotation.defaults = { yMax: undefined, yMin: undefined, yScaleID: undefined, - yValue: undefined + yValue: undefined, + z: 0 }; PointAnnotation.defaultRoutes = { diff --git a/src/types/polygon.js b/src/types/polygon.js index e8f6ecd48..bcf08e92f 100644 --- a/src/types/polygon.js +++ b/src/types/polygon.js @@ -91,7 +91,8 @@ PolygonAnnotation.defaults = { yMax: undefined, yMin: undefined, yScaleID: undefined, - yValue: undefined + yValue: undefined, + z: 0 }; PolygonAnnotation.defaultRoutes = { diff --git a/test/fixtures/box/zIndex.js b/test/fixtures/box/zIndex.js new file mode 100644 index 000000000..9259c5e2d --- /dev/null +++ b/test/fixtures/box/zIndex.js @@ -0,0 +1,120 @@ +module.exports = { + config: { + type: 'scatter', + options: { + scales: { + x: { + display: false, + min: 0, + max: 10 + }, + y: { + display: false, + min: 0, + max: 25 + } + }, + plugins: { + annotation: { + annotations: { + box1: { + type: 'box', + xMin: 3, + xMax: 7, + yMin: 1, + yMax: 4, + backgroundColor: 'rgba(255, 99, 132, 0.5)', + borderColor: 'rgb(255, 99, 132)', + borderWidth: 1, + label: { + display: true, + content: 'box1 z:+10/z: 0', + z: 0 + }, + z: 10 + }, + box2: { + type: 'box', + xMin: 1.5, + xMax: 5.5, + yMin: 15, + yMax: 23.5, + backgroundColor: 'rgba(255, 99, 132, 0.5)', + borderColor: 'rgba(255, 99, 132)', + borderWidth: 1, + label: { + display: true, + content: 'box2 fallback/z: +100', + z: 100 + } + }, + box3: { + type: 'box', + xMin: 2.5, + xMax: 7, + yMin: 16, + yMax: 21, + backgroundColor: 'rgba(255, 99, 132, 0.5)', + borderColor: 'rgba(255, 99, 132)', + borderWidth: 1, + label: { + display: true, + content: 'box3 fallback/z: -1', + z: -1 + } + }, + box4: { + type: 'box', + xMin: 3, + xMax: 7, + yMin: 5, + yMax: 9, + backgroundColor: 'rgba(255, 99, 132, 0.5)', + borderColor: 'rgba(255, 99, 132)', + borderWidth: 1, + label: { + display: true, + content: 'box4 fallback/fallback', + }, + }, + box5: { + type: 'box', + xMin: 1.5, + xMax: 5.5, + yMin: 10, + yMax: 14.5, + backgroundColor: 'rgba(255, 99, 132, 0.5)', + borderColor: 'rgba(255, 99, 132)', + borderWidth: 1, + label: { + display: true, + content: 'box5 z: +100/z: 0', + position: 'start', + z: 0 + }, + z: 100 + }, + box6: { + type: 'box', + xMin: 2.5, + xMax: 4.5, + yMin: 11, + yMax: 13.5, + backgroundColor: 'rgba(255, 99, 132, 0.5)', + borderColor: 'rgba(255, 99, 132)', + borderWidth: 1, + label: { + display: true, + content: 'box6 z: 0/fallback', + }, + z: 0 + } + } + } + } + } + }, + options: { + spriteText: true + } +}; diff --git a/test/fixtures/box/zIndex.png b/test/fixtures/box/zIndex.png new file mode 100644 index 000000000..0c0932984 Binary files /dev/null and b/test/fixtures/box/zIndex.png differ diff --git a/test/fixtures/line/labelZindex.js b/test/fixtures/line/labelZindex.js new file mode 100644 index 000000000..abd47028f --- /dev/null +++ b/test/fixtures/line/labelZindex.js @@ -0,0 +1,96 @@ +module.exports = { + config: { + type: 'scatter', + data: { + datasets: [{ + backgroundColor: 'rgba(255,165,0,0.9)', + radius: 20, + data: [{x: 15, y: 25}, {x: 35, y: 50}, {x: 50, y: 95}, {x: 82, y: 75}, {x: 82, y: 5}] + }] + }, + options: { + scales: { + x: { + display: false, + min: 0, + max: 100 + }, + y: { + display: false, + min: 0, + max: 100 + } + }, + plugins: { + legend: false, + annotation: { + common: { + z: -10 + }, + annotations: { + left: { + type: 'line', + scaleID: 'y', + value: 25, + borderColor: 'black', + borderWidth: 5, + label: { + position: 'start', + backgroundColor: 'red', + content: 'left z: +10/undefined', + display: true + }, + z: 10 + }, + hCenter: { + type: 'line', + scaleID: 'y', + value: 50, + borderColor: 'black', + borderWidth: 5, + label: { + position: 'center', + backgroundColor: 'red', + content: 'hCenter z: -10/z: +10', + display: true, + z: 10 + }, + z: -10 + }, + right: { + type: 'line', + scaleID: 'y', + value: 75, + borderColor: 'black', + borderWidth: 5, + label: { + position: 'end', + backgroundColor: 'green', + content: 'right z: +10/z: -10', + display: true, + z: -10 + }, + z: 10 + }, + top: { + type: 'line', + scaleID: 'x', + value: 50, + borderColor: 'blue', + borderWidth: 5, + label: { + position: 'start', + backgroundColor: 'red', + content: 'top fallback/fallback', + display: true + } + }, + } + } + } + } + }, + options: { + spriteText: true + } +}; diff --git a/test/fixtures/line/labelZindex.png b/test/fixtures/line/labelZindex.png new file mode 100644 index 000000000..738563f4f Binary files /dev/null and b/test/fixtures/line/labelZindex.png differ diff --git a/types/label.d.ts b/types/label.d.ts index ce6e34cfc..0766bcbf5 100644 --- a/types/label.d.ts +++ b/types/label.d.ts @@ -46,6 +46,7 @@ export interface CoreLabelOptions { * or in percentage of current height of image by a string */ height?: Scriptable, + z?: Scriptable } export interface ContainedLabelOptions extends CoreLabelOptions { @@ -76,7 +77,7 @@ export interface ContainedLabelOptions extends CoreLabelOptions { * Border radius of the label rectangle * @default 6 */ - borderRadius?: Scriptable, + borderRadius?: Scriptable } export interface LabelOptions extends ContainedLabelOptions, ShadowOptions { diff --git a/types/options.d.ts b/types/options.d.ts index fe0b7b4a9..03cce72d1 100644 --- a/types/options.d.ts +++ b/types/options.d.ts @@ -39,7 +39,8 @@ export interface CoreAnnotationOptions extends AnnotationEvents, ShadowOptions { scaleID?: Scriptable, value?: Scriptable, xScaleID?: Scriptable, - yScaleID?: Scriptable + yScaleID?: Scriptable, + z?: Scriptable } export type Scriptable = T | ((ctx: TContext, options: AnnotationOptions) => T);