diff --git a/docs/axes/cartesian/time.md b/docs/axes/cartesian/time.md index 389de1d55f9..b36ef28681a 100644 --- a/docs/axes/cartesian/time.md +++ b/docs/axes/cartesian/time.md @@ -30,6 +30,7 @@ Namespace: `options.scales[scaleId]` | `suggestedMax` | `number`\|`string` | | The maximum item to display if there is no datapoint behind it. [more...](../index.md#axis-range-settings) | `adapters.date` | `object` | `{}` | Options for adapter for external date library if that adapter needs or supports options | `bounds` | `string` | `'data'` | Determines the scale bounds. [more...](./index.md#scale-bounds) +| `offsetAfterAutoskip` | `boolean` | `false` | If true, bar chart offsets are computed with auto skipped ticks. | `ticks.source` | `string` | `'auto'` | How ticks are generated. [more...](#ticks-source) | `time.displayFormats` | `object` | | Sets how different time units are displayed. [more...](#display-formats) | `time.isoWeekday` | `boolean`\|`number` | `false` | If `boolean` and true and the unit is set to 'week', then the first day of the week will be Monday. Otherwise, it will be Sunday. If `number`, the index of the first day of the week (0 - Sunday, 6 - Saturday) diff --git a/src/core/core.scale.js b/src/core/core.scale.js index 1e79c1d97ef..e349a51fb8a 100644 --- a/src/core/core.scale.js +++ b/src/core/core.scale.js @@ -453,6 +453,7 @@ export default class Scale extends Element { if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto')) { this.ticks = autoSkip(this, this.ticks); this._labelSizes = null; + this.afterAutoSkip(); } if (samplingEnabled) { @@ -619,6 +620,7 @@ export default class Scale extends Element { afterCalculateLabelRotation() { call(this.options.afterCalculateLabelRotation, [this]); } + afterAutoSkip() {} // diff --git a/src/scales/scale.time.js b/src/scales/scale.time.js index 6397c18efef..6b8078a7514 100644 --- a/src/scales/scale.time.js +++ b/src/scales/scale.time.js @@ -351,6 +351,14 @@ export default class TimeScale extends Scale { return ticksFromTimestamps(this, ticks, this._majorUnit); } + afterAutoSkip() { + // Offsets for bar charts need to be handled with the auto skipped + // ticks. Once ticks have been skipped, we re-compute the offsets. + if (this.options.offsetAfterAutoskip) { + this.initOffsets(this.ticks.map(tick => +tick.value)); + } + } + /** * Returns the start and end offsets from edges in the form of {start, end} * where each value is a relative width to the scale and ranges between 0 and 1. diff --git a/test/fixtures/scale.time/offset-auto-skip-ticks.js b/test/fixtures/scale.time/offset-auto-skip-ticks.js new file mode 100644 index 00000000000..ae28ce0bdcd --- /dev/null +++ b/test/fixtures/scale.time/offset-auto-skip-ticks.js @@ -0,0 +1,52 @@ +const data = { + labels: [], + datasets: [{ + label: 'Dataset', + borderColor: '#2f54eb', + data: [{ + y: 3, + x: 1646345700000 + }, { + y: 7, + x: 1646346600000 + }, { + y: 9, + x: 1646347500000 + }, { + y: 5, + x: 1646348400000 + }, { + y: 5, + x: 1646349300000 + }], + }] +}; + +module.exports = { + description: 'https://github.com/chartjs/Chart.js/issues/10215', + config: { + type: 'bar', + data, + options: { + maintainAspectRatio: false, + scales: { + x: { + type: 'time', + offset: true, + offsetAfterAutoskip: true, + axis: 'x', + grid: { + offset: true + }, + }, + y: { + display: false, + } + } + } + }, + options: { + spriteText: true, + canvas: {width: 600, height: 400} + } +}; diff --git a/test/fixtures/scale.time/offset-auto-skip-ticks.png b/test/fixtures/scale.time/offset-auto-skip-ticks.png new file mode 100644 index 00000000000..48630badf59 Binary files /dev/null and b/test/fixtures/scale.time/offset-auto-skip-ticks.png differ diff --git a/types/index.esm.d.ts b/types/index.esm.d.ts index 2ef93eb17b3..f3472cf032f 100644 --- a/types/index.esm.d.ts +++ b/types/index.esm.d.ts @@ -3202,6 +3202,13 @@ export type TimeScaleOptions = Omit & { */ bounds: 'ticks' | 'data'; + /** + * If true, bar chart offsets are computed with skipped tick sizes + * @since 3.8.0 + * @default false + */ + offsetAfterAutoskip: boolean; + /** * options for creating a new adapter instance */