Skip to content

Commit

Permalink
Merge branch 'master' into core.scale.defaults
Browse files Browse the repository at this point in the history
  • Loading branch information
kurkle authored Mar 21, 2021
2 parents 9af04a6 + bd9bc69 commit cda32c7
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 163 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"moment": "^2.29.1",
"pixelmatch": "^5.2.1",
"rollup": "^2.41.4",
"rollup-plugin-analyzer": "^4.0.0",
"rollup-plugin-cleanup": "^3.2.1",
"rollup-plugin-dts": "^3.0.1",
"rollup-plugin-istanbul": "^3.0.0",
Expand Down
2 changes: 2 additions & 0 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const analyze = require('rollup-plugin-analyzer');
const cleanup = require('rollup-plugin-cleanup');
const dts = require('rollup-plugin-dts').default;
const json = require('@rollup/plugin-json');
Expand Down Expand Up @@ -34,6 +35,7 @@ module.exports = [
cleanup({
sourcemap: true
}),
analyze({summaryOnly: true})
],
output: {
name: 'Chart',
Expand Down
169 changes: 169 additions & 0 deletions src/core/core.scale.autoskip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import {isNullOrUndef, valueOrDefault} from '../helpers/helpers.core';
import {_factorize} from '../helpers/helpers.math';


/**
* @typedef { import("./core.controller").default } Chart
* @typedef {{value:number | string, label?:string, major?:boolean, $context?:any}} Tick
*/

/**
* Returns a subset of ticks to be plotted to avoid overlapping labels.
* @param {import('./core.scale').default} scale
* @param {Tick[]} ticks
* @return {Tick[]}
* @private
*/
export function autoSkip(scale, ticks) {
const tickOpts = scale.options.ticks;
const ticksLimit = tickOpts.maxTicksLimit || determineMaxTicks(scale);
const majorIndices = tickOpts.major.enabled ? getMajorIndices(ticks) : [];
const numMajorIndices = majorIndices.length;
const first = majorIndices[0];
const last = majorIndices[numMajorIndices - 1];
const newTicks = [];

// If there are too many major ticks to display them all
if (numMajorIndices > ticksLimit) {
skipMajors(ticks, newTicks, majorIndices, numMajorIndices / ticksLimit);
return newTicks;
}

const spacing = calculateSpacing(majorIndices, ticks, ticksLimit);

if (numMajorIndices > 0) {
let i, ilen;
const avgMajorSpacing = numMajorIndices > 1 ? Math.round((last - first) / (numMajorIndices - 1)) : null;
skip(ticks, newTicks, spacing, isNullOrUndef(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first);
for (i = 0, ilen = numMajorIndices - 1; i < ilen; i++) {
skip(ticks, newTicks, spacing, majorIndices[i], majorIndices[i + 1]);
}
skip(ticks, newTicks, spacing, last, isNullOrUndef(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing);
return newTicks;
}
skip(ticks, newTicks, spacing);
return newTicks;
}

function determineMaxTicks(scale) {
const offset = scale.options.offset;
const tickLength = scale._tickSize();
const maxScale = scale._length / tickLength + (offset ? 0 : 1);
const maxChart = scale._maxLength / tickLength;
return Math.floor(Math.min(maxScale, maxChart));
}

/**
* @param {number[]} majorIndices
* @param {Tick[]} ticks
* @param {number} ticksLimit
*/
function calculateSpacing(majorIndices, ticks, ticksLimit) {
const evenMajorSpacing = getEvenSpacing(majorIndices);
const spacing = ticks.length / ticksLimit;

// If the major ticks are evenly spaced apart, place the minor ticks
// so that they divide the major ticks into even chunks
if (!evenMajorSpacing) {
return Math.max(spacing, 1);
}

const factors = _factorize(evenMajorSpacing);
for (let i = 0, ilen = factors.length - 1; i < ilen; i++) {
const factor = factors[i];
if (factor > spacing) {
return factor;
}
}
return Math.max(spacing, 1);
}

/**
* @param {Tick[]} ticks
*/
function getMajorIndices(ticks) {
const result = [];
let i, ilen;
for (i = 0, ilen = ticks.length; i < ilen; i++) {
if (ticks[i].major) {
result.push(i);
}
}
return result;
}

/**
* @param {Tick[]} ticks
* @param {Tick[]} newTicks
* @param {number[]} majorIndices
* @param {number} spacing
*/
function skipMajors(ticks, newTicks, majorIndices, spacing) {
let count = 0;
let next = majorIndices[0];
let i;

spacing = Math.ceil(spacing);
for (i = 0; i < ticks.length; i++) {
if (i === next) {
newTicks.push(ticks[i]);
count++;
next = majorIndices[count * spacing];
}
}
}

/**
* @param {Tick[]} ticks
* @param {Tick[]} newTicks
* @param {number} spacing
* @param {number} [majorStart]
* @param {number} [majorEnd]
*/
function skip(ticks, newTicks, spacing, majorStart, majorEnd) {
const start = valueOrDefault(majorStart, 0);
const end = Math.min(valueOrDefault(majorEnd, ticks.length), ticks.length);
let count = 0;
let length, i, next;

spacing = Math.ceil(spacing);
if (majorEnd) {
length = majorEnd - majorStart;
spacing = length / Math.floor(length / spacing);
}

next = start;

while (next < 0) {
count++;
next = Math.round(start + count * spacing);
}

for (i = Math.max(start, 0); i < end; i++) {
if (i === next) {
newTicks.push(ticks[i]);
count++;
next = Math.round(start + count * spacing);
}
}
}


/**
* @param {number[]} arr
*/
function getEvenSpacing(arr) {
const len = arr.length;
let i, diff;

if (len < 2) {
return false;
}

for (diff = arr[0], i = 1; i < len; ++i) {
if (arr[i] - arr[i - 1] !== diff) {
return false;
}
}
return diff;
}
Loading

0 comments on commit cda32c7

Please sign in to comment.