1

Update: added a working fiddle online added a working code snippet :)

I am moving from dygraphs to chartsjs but am stuck with trying to show minor grid lines in a log scale chart. The chart with chartjs is in the first image below (with no minor grid lines). I would like it to have grid lines like in the second image. Reading the documentation several times has not yielded an answer to me.

with chartjs with dygraphs

const termFreqWithChartjs = (ctx, series, term, termFreq) => {
    
    const config = {
        type: 'line',
        data: {
            labels: termFreq.map(e => e.journalYear),
            datasets: [
                {
                    label: series.y1,
                    data: termFreq.map(e => e.total),
                    borderColor: 'red',
                    borderWidth: 1,
                    backgroundColor: 'rgba(255, 0, 0, 0.1)',
                    pointStyle: 'circle',
                    pointRadius: 3,
                    pointBorderColor: 'rgb(0, 0, 0)'
                },
                {
                    label: series.y2,
                    data: termFreq.map(e => e.withImages),
                    borderColor: 'blue',
                    borderWidth: 1,
                    backgroundColor: 'rgba(0, 0, 255, 0.1)',
                    pointStyle: 'circle',
                    pointRadius: 3,
                    pointBorderColor: 'rgb(0, 0, 0)'
                }
            ]
        },
        options: {
            interaction: {
                intersect: false,
                mode: 'x',
            },
            animation: false,
            responsive: true,
            scales: {
                x: {
                    display: true,

                },
                y: {
                    display: true,
                    type: 'logarithmic',
                    grid: {
                        borderColor: 'grey',
                        tickColor: 'grey'
                    },
                    min: 1,
                    ticks: {
                        callback: function (value, index, values) {
                            if (value === 1000000) return "1M";
                            if (value === 100000) return "100K";
                            if (value === 10000) return "10K";
                            if (value === 1000) return "1K";
                            if (value === 100) return "100";
                            if (value === 10) return "10";
                            if (value === 1) return "1";
                            return null;
                        }
                    }
                }
            },
            plugins: {
                title: {
                    display: true,
                    text: `occurrence of '${term}' in text by year`,
                },
                legend: {
                    display: true,
                    position: 'chartArea',
                    labels: {
                        usePointStyle: true,
                    }
                },
                tooltip: {
                    enabled: true
                }
            }
        }
    };

    let canvas = document.getElementById('termFreq');

    if (canvas) {
        termFreqChart.destroy();
        termFreqChart = new Chart(canvas, config);
    }
    else {
        canvas = document.createElement('canvas');
        canvas.id = "termFreq";
        canvas.width = 500;
        canvas.height = 200;
        ctx.appendChild(canvas);
        termFreqChart = new Chart(canvas, config);
    }
}
const termFreq = [
    {
        "journalYear": 1841,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1846,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1850,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1851,
        "total": 26,
        "withImages": 0
    },
    {
        "journalYear": 1853,
        "total": 5,
        "withImages": 0
    },
    {
        "journalYear": 1855,
        "total": 7,
        "withImages": 0
    },
    {
        "journalYear": 1857,
        "total": 27,
        "withImages": 0
    },
    {
        "journalYear": 1859,
        "total": 30,
        "withImages": 0
    },
    {
        "journalYear": 1860,
        "total": 4,
        "withImages": 0
    },
    {
        "journalYear": 1861,
        "total": 9,
        "withImages": 0
    },
    {
        "journalYear": 1862,
        "total": 18,
        "withImages": 0
    },
    {
        "journalYear": 1863,
        "total": 4,
        "withImages": 0
    },
    {
        "journalYear": 1866,
        "total": 12,
        "withImages": 0
    },
    {
        "journalYear": 1877,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1884,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1886,
        "total": 12,
        "withImages": 0
    },
    {
        "journalYear": 1887,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1890,
        "total": 5,
        "withImages": 0
    },
    {
        "journalYear": 1893,
        "total": 4,
        "withImages": 0
    },
    {
        "journalYear": 1894,
        "total": 9,
        "withImages": 0
    },
    {
        "journalYear": 1895,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1896,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1902,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1904,
        "total": 14,
        "withImages": 0
    },
    {
        "journalYear": 1905,
        "total": 10,
        "withImages": 0
    },
    {
        "journalYear": 1910,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1912,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1913,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1914,
        "total": 7,
        "withImages": 0
    },
    {
        "journalYear": 1915,
        "total": 5,
        "withImages": 0
    },
    {
        "journalYear": 1920,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1922,
        "total": 8,
        "withImages": 0
    },
    {
        "journalYear": 1924,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1926,
        "total": 5,
        "withImages": 0
    },
    {
        "journalYear": 1928,
        "total": 5,
        "withImages": 0
    },
    {
        "journalYear": 1932,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1949,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1950,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1953,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1955,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1956,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1958,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1959,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1960,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1975,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1979,
        "total": 136,
        "withImages": 0
    },
    {
        "journalYear": 1990,
        "total": 27,
        "withImages": 5
    },
    {
        "journalYear": 1992,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1993,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1997,
        "total": 1,
        "withImages": 1
    },
    {
        "journalYear": 2000,
        "total": 251,
        "withImages": 225
    },
    {
        "journalYear": 2001,
        "total": 14,
        "withImages": 0
    },
    {
        "journalYear": 2003,
        "total": 141,
        "withImages": 139
    },
    {
        "journalYear": 2004,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 2005,
        "total": 62,
        "withImages": 0
    },
    {
        "journalYear": 2006,
        "total": 16,
        "withImages": 12
    },
    {
        "journalYear": 2007,
        "total": 79,
        "withImages": 17
    },
    {
        "journalYear": 2008,
        "total": 42,
        "withImages": 16
    },
    {
        "journalYear": 2009,
        "total": 141,
        "withImages": 60
    },
    {
        "journalYear": 2010,
        "total": 111,
        "withImages": 5
    },
    {
        "journalYear": 2011,
        "total": 62,
        "withImages": 14
    },
    {
        "journalYear": 2012,
        "total": 100,
        "withImages": 25
    },
    {
        "journalYear": 2013,
        "total": 137,
        "withImages": 129
    },
    {
        "journalYear": 2014,
        "total": 54,
        "withImages": 23
    },
    {
        "journalYear": 2015,
        "total": 139,
        "withImages": 73
    },
    {
        "journalYear": 2016,
        "total": 166,
        "withImages": 36
    },
    {
        "journalYear": 2017,
        "total": 87,
        "withImages": 74
    },
    {
        "journalYear": 2018,
        "total": 79,
        "withImages": 49
    },
    {
        "journalYear": 2019,
        "total": 142,
        "withImages": 96
    },
    {
        "journalYear": 2020,
        "total": 84,
        "withImages": 27
    },
    {
        "journalYear": 2021,
        "total": 907,
        "withImages": 386
    },
    {
        "journalYear": 2022,
        "total": 79,
        "withImages": 50
    },
    {
        "journalYear": 2023,
        "total": 3,
        "withImages": 0
    }
];

const series = {
    x: "journal year",
    y1: "total",
    y2: "with images"
}

const ctx = document.getElementById('graphdiv');
termFreqWithChartjs(ctx, series, 'formica', termFreq);
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div id="graphdiv"></div>
punkish
  • 13,598
  • 26
  • 66
  • 101
  • 1
    Hello, you need to post your code so we can help you identify your mistakes. – Douglas Cunha Jul 05 '23 at 07:45
  • If [major ticks](https://www.chartjs.org/docs/latest/axes/styling.html#major-tick-configuration) don't work for you, you should use the fact that [`grid.lineWidth`](https://www.chartjs.org/docs/latest/axes/styling.html#grid-line-configuration) is [scriptable](https://www.chartjs.org/docs/latest/general/options.html#scriptable-options) and use [ticks callback](https://www.chartjs.org/docs/latest/axes/labelling.html#creating-custom-tick-formats). Or, do what @DouglasCunha asked, and provide a working example and let us help... – kikon Jul 06 '23 at 15:13
  • I want grid lines between the ticks, hence, what I call "minor grid". In a log chart esp., these minor grid lines (as shown in the dygraphs image I posted) give a visual indication of the scale. Wrt a workable example, I've posted the code of what I have got so far. While I see several references to the scriptability of the ticks for styling the grid, I can't figure out how to draw these lines in the first place. How do I tell `chartjs` to draw, say, 10 grid lines in between each major grid line (the labeled ones)? – punkish Jul 06 '23 at 21:00
  • You already observed and I confirmed, there are no minor ticks per se. I told you that you can do them with code; that's the way of chart.js. – kikon Jul 07 '23 at 08:44
  • 1
    oh, an online fiddle is a great idea! Thanks! I had never made one before. I've added a working example to the original post. – punkish Jul 07 '23 at 09:48

1 Answers1

2

This is a possible approach. I realise now that the main thing is to replace return null with return '' in ticks.callback. The former completely kills non-conforming lines, the latter only kills the tick labels, keeping the line, which becomes a minor grid line.

After that, there are the scriptable options, that are options that can be given either as values (strings, numbers) or as functions - the latter being the scripted version, useful to adapt the result to the computed circumstances - in this case to whether the ticks are minor or major.

I identified in the code below all relevant options that may be used to visually differentiate minor grid lines and ticks from major ones. You may keep only some of them or just none.

I also added a possible filter for the ticks in the function options.scales.y.afterBuildTicks, more a demonstration of that feature. One can also filter grid lines in ticks.callback, by actually returning null for some values.

Options, extracted:

const config = {
    type: 'line',
    data: {
        // ............
    },
    options: {
        // ..... other options 
        scales: {
            x: // .....
            y: {
                display: true,
                type: 'logarithmic',

                grid: {
                    tickColor: function(data){ // color of the tick line
                        return data.tick.major ? 'rgb(196, 196, 196)' :
                            'rgba(196, 196, 196, 0)' // minor ticks not visible
                    },
                    lineWidth: function(data){ // the width of grid line
                        return data.tick.major ? 2 : 1
                    },
                    color:function(data){ // the color of the grid line
                        return data.tick.major ? 'rgb(196, 196, 196)' :
                            'rgba(196, 196, 196, 0.5)'
                    }
                },
                border:{
                    dash:function(data){
                        // dash pattern for grid lines
                        // (unexpected position for this option here)
                        return data.tick.major ? null : [5, 1]
                    }
                },
                min: 1,
                afterBuildTicks: function(ax){
                    ax.ticks = ax.ticks.filter(({value})=>{
                        const r = value/ Math.pow(10, Math.floor(Math.log10(value)+1e-5));
                        return Math.abs(r - Math.round(r)) < 1e-5
                    })
                    // this eliminates tick values like 15 or 150 and only keeps
                    // those of the form n*10^m with n, m one digit integers
                    // this might not be necessary
                },
                ticks: {
                    callback: function (value, index, ticks) {
                        if (value === 1000000) return "1M";
                        if (value === 100000) return "100K";
                        if (value === 10000) return "10K";
                        if (value === 1000) return "1K";
                        if (value === 100) return "100";
                        if (value === 10) return "10";
                        if (value === 1) return "1";
                        return '';
                    }
                }
            }
        },
        // ......
    }
}
   

Full running example, forked yours, height increased to make log minor grid lines visible.

const termFreqWithChartjs = (ctx, series, term, termFreq) => {
    const config = {
        type: 'line',
        data: {
            labels: termFreq.map(e => e.journalYear),
            datasets: [
                {
                    label: series.y1,
                    data: termFreq.map(e => e.total),
                    borderColor: 'red',
                    borderWidth: 1,
                    backgroundColor: 'rgba(255, 0, 0, 0.1)',
                    pointStyle: 'circle',
                    pointRadius: 3,
                    pointBorderColor: 'rgb(0, 0, 0)'
                },
                {
                    label: series.y2,
                    data: termFreq.map(e => e.withImages),
                    borderColor: 'blue',
                    borderWidth: 1,
                    backgroundColor: 'rgba(0, 0, 255, 0.1)',
                    pointStyle: 'circle',
                    pointRadius: 3,
                    pointBorderColor: 'rgb(0, 0, 0)'
                }
            ]
        },
        options: {
            interaction: {
                intersect: false,
                mode: 'x',
            },
            animation: false,
            responsive: true,
            scales: {
                x: {
                    display: true,
                },
                y: {
                    display: true,
                    type: 'logarithmic',

                    grid: {
                        tickColor: function(data){
                            return data.tick.major ? 'rgb(196, 196, 196)' :
                                'rgba(196, 196, 196, 0)' // minor ticks not visible
                        },
                        lineWidth: function(data){
                            return data.tick.major ? 2 : 1
                        },
                        color:function(data){
                            return data.tick.major ? 'rgb(196, 196, 196)' :
                                'rgba(196, 196, 196, 0.5)'
                        }
                    },
                    border:{
                        dash:function(data){
                            // dash line for grid lines
                            // (unexpected position for this option here)
                            return data.tick.major ? null : [5, 1]
                        }
                    },
                    min: 1,
                    afterBuildTicks: function(ax){
                        ax.ticks = ax.ticks.filter(({value})=>{
                            const r = value/ Math.pow(10, Math.floor(Math.log10(value)+1e-5));
                            return Math.abs(r - Math.round(r)) < 1e-5
                        })
                        // this eliminates tick values like 15 or 150 and only keeps
                        // those of the form n*10^m with n, m one digit integers
                        // this might not be necessary
                    },
                    ticks: {
                        autoSkip: false,
                        callback: function (value, index, ticks) {
                            if (value === 1000000) return "1M";
                            if (value === 100000) return "100K";
                            if (value === 10000) return "10K";
                            if (value === 1000) return "1K";
                            if (value === 100) return "100";
                            if (value === 10) return "10";
                            if (value === 1) return "1";
                            return '';
                        }
                    }
                }
            },
            plugins: {
                title: {
                    display: true,
                    text: `occurrence of '${term}' in text by year`,
                },
                legend: {
                    display: true,
                    position: 'chartArea',
                    labels: {
                        usePointStyle: true,
                    }
                },
                tooltip: {
                    enabled: true
                }
            }
        }
    };

    let canvas = document.getElementById('termFreq');

    if (canvas) {
        termFreqChart.destroy();
        termFreqChart = new Chart(canvas, config);
    }
    else {
        canvas = document.createElement('canvas');
        canvas.id = "termFreq";
        canvas.width = 960;
        canvas.height = 600;
        ctx.appendChild(canvas);
        termFreqChart = new Chart(canvas, config);
    }
}
const termFreq = [
    {
        "journalYear": 1841,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1846,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1850,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1851,
        "total": 26,
        "withImages": 0
    },
    {
        "journalYear": 1853,
        "total": 5,
        "withImages": 0
    },
    {
        "journalYear": 1855,
        "total": 7,
        "withImages": 0
    },
    {
        "journalYear": 1857,
        "total": 27,
        "withImages": 0
    },
    {
        "journalYear": 1859,
        "total": 30,
        "withImages": 0
    },
    {
        "journalYear": 1860,
        "total": 4,
        "withImages": 0
    },
    {
        "journalYear": 1861,
        "total": 9,
        "withImages": 0
    },
    {
        "journalYear": 1862,
        "total": 18,
        "withImages": 0
    },
    {
        "journalYear": 1863,
        "total": 4,
        "withImages": 0
    },
    {
        "journalYear": 1866,
        "total": 12,
        "withImages": 0
    },
    {
        "journalYear": 1877,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1884,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1886,
        "total": 12,
        "withImages": 0
    },
    {
        "journalYear": 1887,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1890,
        "total": 5,
        "withImages": 0
    },
    {
        "journalYear": 1893,
        "total": 4,
        "withImages": 0
    },
    {
        "journalYear": 1894,
        "total": 9,
        "withImages": 0
    },
    {
        "journalYear": 1895,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1896,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1902,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1904,
        "total": 14,
        "withImages": 0
    },
    {
        "journalYear": 1905,
        "total": 10,
        "withImages": 0
    },
    {
        "journalYear": 1910,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1912,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1913,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1914,
        "total": 7,
        "withImages": 0
    },
    {
        "journalYear": 1915,
        "total": 5,
        "withImages": 0
    },
    {
        "journalYear": 1920,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1922,
        "total": 8,
        "withImages": 0
    },
    {
        "journalYear": 1924,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1926,
        "total": 5,
        "withImages": 0
    },
    {
        "journalYear": 1928,
        "total": 5,
        "withImages": 0
    },
    {
        "journalYear": 1932,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1949,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1950,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1953,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1955,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1956,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1958,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1959,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1960,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1975,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 1979,
        "total": 136,
        "withImages": 0
    },
    {
        "journalYear": 1990,
        "total": 27,
        "withImages": 5
    },
    {
        "journalYear": 1992,
        "total": 3,
        "withImages": 0
    },
    {
        "journalYear": 1993,
        "total": 1,
        "withImages": 0
    },
    {
        "journalYear": 1997,
        "total": 1,
        "withImages": 1
    },
    {
        "journalYear": 2000,
        "total": 251,
        "withImages": 225
    },
    {
        "journalYear": 2001,
        "total": 14,
        "withImages": 0
    },
    {
        "journalYear": 2003,
        "total": 141,
        "withImages": 139
    },
    {
        "journalYear": 2004,
        "total": 2,
        "withImages": 0
    },
    {
        "journalYear": 2005,
        "total": 62,
        "withImages": 0
    },
    {
        "journalYear": 2006,
        "total": 16,
        "withImages": 12
    },
    {
        "journalYear": 2007,
        "total": 79,
        "withImages": 17
    },
    {
        "journalYear": 2008,
        "total": 42,
        "withImages": 16
    },
    {
        "journalYear": 2009,
        "total": 141,
        "withImages": 60
    },
    {
        "journalYear": 2010,
        "total": 111,
        "withImages": 5
    },
    {
        "journalYear": 2011,
        "total": 62,
        "withImages": 14
    },
    {
        "journalYear": 2012,
        "total": 100,
        "withImages": 25
    },
    {
        "journalYear": 2013,
        "total": 137,
        "withImages": 129
    },
    {
        "journalYear": 2014,
        "total": 54,
        "withImages": 23
    },
    {
        "journalYear": 2015,
        "total": 139,
        "withImages": 73
    },
    {
        "journalYear": 2016,
        "total": 166,
        "withImages": 36
    },
    {
        "journalYear": 2017,
        "total": 87,
        "withImages": 74
    },
    {
        "journalYear": 2018,
        "total": 79,
        "withImages": 49
    },
    {
        "journalYear": 2019,
        "total": 142,
        "withImages": 96
    },
    {
        "journalYear": 2020,
        "total": 84,
        "withImages": 27
    },
    {
        "journalYear": 2021,
        "total": 907,
        "withImages": 386
    },
    {
        "journalYear": 2022,
        "total": 79,
        "withImages": 50
    },
    {
        "journalYear": 2023,
        "total": 3,
        "withImages": 0
    }
];

const series = {
    x: "journal year",
    y1: "total",
    y2: "with images"
}

const ctx = document.getElementById('graphdiv');
termFreqWithChartjs(ctx, series, 'formica', termFreq);
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div id="graphdiv"></div>

Please let me know what's missing from what you would expect from a system of minor grid lines, so I can try to cover that.

kikon
  • 3,670
  • 3
  • 5
  • 20
  • thanks for this… its awesome. The flexibility and adjustability of `chartjs` is remarkable. That said, it is (in my view), unbelievably complicated and verbose to render something as fundamental as grid lines. This should be made easier for the end-user and abstracted away into something much simpler. Given enough time, maybe I would have been able to figure this out without your help, though I doubt it. In any case, immensely grateful for this. Thanks – punkish Jul 07 '23 at 18:01
  • where are you controlling the number of visible minor grid lines, that is, the lines between the labeled grid lines. Can I control that? Can I force the chart to make 10 of them between each major grid line, for example? Look at my example image of the dygraphs chart… the grid lines, bunched together toward the top of each interval, give a visual affordance that the scale is not linear. The values are not impt here, but the visual indication is invaluable for a casual viewer. Dygraphs does this out of the box… I would like to be able to tell chartjs to print more lines – punkish Jul 07 '23 at 18:17
  • there is another interesting glitch… see how the legend keys are drawn so the grid line is visible through them (see the circles to the left of "total" and "with images"? It would be better if the legend were on top of the grid, but I don't see any z-index value to control where (which layer) the legend is drawn with respect to the other elements of the chart. – punkish Jul 07 '23 at 18:55
  • 1
    The legend *is* in fact on top, but you see the grid lines under it because of the transparency of the legend symbols. You can change that from `data.datasets[].backgroundColor`, for instance if you change to `backgroundColor: 'rgba(0, 0, 255, 1)'` you'll no longer see the lines. Nevertheless, it still doesn't look great, so you may want to put a background for the whole legend, which is also not available out of the box, but I'll try to do it with a plugin. [This solution](https://stackoverflow.com/a/71158038/16466946) only works for default positioning of the legend on the top of the chart. – kikon Jul 08 '23 at 10:18
  • You actually have 8 minor grid lines between two major ones. However, I see now that not all are shown, because the algorithm that attempts to avoid overlapping of tick labels. Set `options.scale.y.ticks.autoSkip: false` [see autoSkip](https://www.chartjs.org/docs/latest/axes/cartesian/#common-tick-options-to-all-cartesian-axes) to show all. You may see all tick/grid line positions with a `console.log(value)` at the beginning of `options.scales.y.ticks.callback`. Still, about *controlling* it, you can do it from `options.scales.y.afterBuildTicks`, I'll make an example. – kikon Jul 08 '23 at 11:03
  • 1
    Here's a [jsFiddle](https://jsfiddle.net/djgscnrt/) with an example where there is a "double" number of minor grid lines (actually 18 instead of 8). I control it from `options.scales.y.afterBuildTicks`, using the constant `minorTickStepFraction`. The minor tick step size is computed, for each interval between two major ticks, as `minorTickStepFraction` times the value of the previous major tick. Set `minorTickStepFraction = 1` for the standard view with 8 minor ticks (e.g., 2,3,4,5,6,7,8,9 between 1 and 10) – kikon Jul 08 '23 at 11:19
  • 1
    I wish I could upvote your comment and answer few times more, but for now, a single upvote will have to do. Thanks much. The strange secrets of `chartjs` are slowly revealed to me – punkish Jul 08 '23 at 14:30
  • there is one last thing you could help me with… could you please point me to the place in the documentation where I could have figured this out myself? I am trying to look at all the docs for `afterBuildTicks` and I can't for the life of me figure out how I could have figured this out myself (so to say). For example, where does it say that standard view has 8 ticks? are their other examples of `afterBuildTicks` (other than what you provided here)? – punkish Jul 08 '23 at 17:06
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/254404/discussion-between-punkish-and-kikon). – punkish Jul 08 '23 at 17:26
  • unfortunately this plugin doesn't seem to work… it doesn't change the background color of the legend :( – punkish Jul 08 '23 at 18:27
  • 1
    The plugin I was talking about, for setting a background color for the legend - here's a [fiddle](https://jsfiddle.net/xm9wcftr/) with that. – kikon Jul 08 '23 at 19:21
  • 1
    thanks! I have modified it ever so slightly so the legend is in a `roundRect`. You can see the [end result of all your invaluable help](https://ocellus.info/index.html?page=1&size=30&resource=images&q=phylogeny). Many thanks again – punkish Jul 09 '23 at 18:10