diff --git a/docs/guide/options.md b/docs/guide/options.md index 2eedf5c6..a1a095ae 100644 --- a/docs/guide/options.md +++ b/docs/guide/options.md @@ -77,9 +77,22 @@ const chart = new Chart('id', { | `backgroundColor` | `Color` | `'rgba(225,225,225,0.3)'` | Fill color | `borderColor` | `Color` | `'rgba(225,225,225)'` | Stroke color | `borderWidth` | `number` | `0` | Stroke width +| [`drawTime`](#draw-time) | `string` | `beforeDatasetsDraw` | When the dragging box is dran on the chart | `threshold` | `number` | `0` | Minimal zoom distance required before actually applying zoom | `modifierKey` | `'ctrl'`\|`'alt'`\|`'shift'`\|`'meta'` | `null` | Modifier key required for drag-to-zoom + +## Draw Time + +The `drawTime` option for zooming determines where in the chart lifecycle the drag box drawing occurs. Four potential options are available: + +| Option | Notes +| ---- | ---- +| `'beforeDraw'` | Occurs before any drawing takes place +| `'beforeDatasetsDraw'` | Occurs after drawing of axes, but before datasets +| `'afterDatasetsDraw'` | Occurs after drawing of datasets but before items such as the tooltip +| `'afterDraw'` | After other drawing is completed + #### Pinch options | Name | Type | Default | Description diff --git a/package.json b/package.json index 3262a864..2da03b14 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "scripts": { "build": "rollup -c", "dev": "karma start --auto-watch --no-single-run --browsers chrome", + "dev:ff": "karma start --auto-watch --no-single-run --browsers firefox", "docs": "npm run build && vuepress build docs --no-cache", "docs:dev": "npm run build && vuepress dev docs --no-cache", "lint-js": "eslint \"samples/**/*.html\" \"test/**/*.js\" \"src/**/*.js\"", diff --git a/src/plugin.js b/src/plugin.js index 786a13d6..0774f207 100644 --- a/src/plugin.js +++ b/src/plugin.js @@ -6,6 +6,29 @@ import {panFunctions, zoomFunctions, zoomRectFunctions} from './scale.types'; import {getState, removeState} from './state'; import {version} from '../package.json'; +function draw(chart, caller, options) { + const dragOptions = options.zoom.drag; + const {dragStart, dragEnd} = getState(chart); + + if (dragOptions.drawTime !== caller || !dragEnd) { + return; + } + const {left, top, width, height} = computeDragRect(chart, options.zoom.mode, dragStart, dragEnd); + const ctx = chart.ctx; + + ctx.save(); + ctx.beginPath(); + ctx.fillStyle = dragOptions.backgroundColor || 'rgba(225,225,225,0.3)'; + ctx.fillRect(left, top, width, height); + + if (dragOptions.borderWidth > 0) { + ctx.lineWidth = dragOptions.borderWidth; + ctx.strokeStyle = dragOptions.borderColor || 'rgba(225,225,225)'; + ctx.strokeRect(left, top, width, height); + } + ctx.restore(); +} + export default { id: 'zoom', @@ -26,6 +49,7 @@ export default { }, drag: { enabled: false, + drawTime: 'beforeDatasetsDraw', modifierKey: null }, pinch: { @@ -75,27 +99,20 @@ export default { addListeners(chart, options); }, - beforeDatasetsDraw: function(chart, args, options) { - const {dragStart, dragEnd} = getState(chart); - - if (dragEnd) { - const {left, top, width, height} = computeDragRect(chart, options.zoom.mode, dragStart, dragEnd); + beforeDatasetsDraw(chart, _args, options) { + draw(chart, 'beforeDatasetsDraw', options); + }, - const dragOptions = options.zoom.drag; - const ctx = chart.ctx; + afterDatasetsDraw(chart, _args, options) { + draw(chart, 'afterDatasetsDraw', options); + }, - ctx.save(); - ctx.beginPath(); - ctx.fillStyle = dragOptions.backgroundColor || 'rgba(225,225,225,0.3)'; - ctx.fillRect(left, top, width, height); + beforeDraw(chart, _args, options) { + draw(chart, 'beforeDraw', options); + }, - if (dragOptions.borderWidth > 0) { - ctx.lineWidth = dragOptions.borderWidth; - ctx.strokeStyle = dragOptions.borderColor || 'rgba(225,225,225)'; - ctx.strokeRect(left, top, width, height); - } - ctx.restore(); - } + afterDraw(chart, _args, options) { + draw(chart, 'afterDraw', options); }, stop: function(chart) { diff --git a/test/fixtures/zoom/dragDrawTime.js b/test/fixtures/zoom/dragDrawTime.js new file mode 100644 index 00000000..56d011e9 --- /dev/null +++ b/test/fixtures/zoom/dragDrawTime.js @@ -0,0 +1,55 @@ +const data = []; +for (let i = 0; i < 100; i++) { + data.push({x: i, y: Math.sin(i / 25 * Math.PI) * 10}); +} + +module.exports = { + tolerance: 0.004, + config: { + type: 'line', + data: { + datasets: [{ + data, + borderColor: 'red' + }] + }, + options: { + scales: { + x: {type: 'linear', display: false}, + y: {display: false} + }, + plugins: { + legend: false, + zoom: { + zoom: { + drag: { + enabled: true, + backgroundColor: 'yellow', + borderColor: 'black', + borderWidth: 1, + drawTime: 'afterDraw' + }, + } + } + }, + layout: { + padding: 2 + } + } + }, + options: { + run(chart) { + const scaleX = chart.scales.x; + const scaleY = chart.scales.y; + jasmine.triggerMouseEvent(chart, 'mousedown', { + x: scaleX.getPixelForValue(5), + y: scaleY.getPixelForValue(10) + }); + jasmine.triggerMouseEvent(chart, 'mousemove', { + x: scaleX.getPixelForValue(60), + y: scaleY.getPixelForValue(0) + }); + chart.render = function() { }; + } + } +}; diff --git a/test/fixtures/zoom/dragDrawTime.png b/test/fixtures/zoom/dragDrawTime.png new file mode 100644 index 00000000..508c32e7 Binary files /dev/null and b/test/fixtures/zoom/dragDrawTime.png differ diff --git a/test/specs/defaults.spec.js b/test/specs/defaults.spec.js index 5e016a32..b82009fe 100644 --- a/test/specs/defaults.spec.js +++ b/test/specs/defaults.spec.js @@ -14,6 +14,7 @@ describe('defaults', function() { }, drag: { enabled: false, + drawTime: 'beforeDatasetsDraw', modifierKey: null }, pinch: { diff --git a/types/options.d.ts b/types/options.d.ts index 6b1f2eb7..6f6ad051 100644 --- a/types/options.d.ts +++ b/types/options.d.ts @@ -3,6 +3,7 @@ import { Chart, Color, Point } from 'chart.js'; type Mode = 'x' | 'y' | 'xy'; type Key = 'ctrl' | 'alt' | 'shift' | 'meta'; +type DrawTime = 'afterDraw' | 'afterDatasetsDraw' | 'beforeDraw' | 'beforeDatasetsDraw'; export interface WheelOptions { /** @@ -52,6 +53,11 @@ export interface DragOptions { * Modifier key required for drag-to-zoom */ modifierKey?: Key; + + /** + * Draw time required for drag-to-zoom + */ + drawTime?: DrawTime; } export interface PinchOptions {