Search code examples
javascriptjquerycanvasgraph

How to draw a custom inclined line on Chartjs


I'm trying out some open source JavaScript graphing libraries (point and lines) that launch in a browser page to check and see which one is best.

After watching some example on codepen.io I stumbled upon Chart.js that uses canavas to draw points and many other forms (like bars, pie etc).

Is it possible to draw a custom sloped line on the canvas graph?

Something like custom chartjs line

I tryied putting

    // Start a new Path
    ctx.beginPath();
    ctx.moveTo(300, 0);
    ctx.lineTo(0, 300);

    // Draw the Path
    ctx.stroke();

after the graph initialization, so should be drawn after the graph is initialized.

Watch the snippet.

        var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
        var config = {
            type: 'line',
            data: {
                labels: ["January", "February", "March", "April", "May", "June", "July"],
                datasets: [{
                    label: "My First dataset",
                    data: [
                        10, 5, 2, 10, 4, 1, 10
                    ],
                    fill: false,
                }, {
                    label: "My Second dataset",
                    fill: false,
                    data: [
                        8, 3, 8, 6, 8, 8, 8
                    ],
                }]
            },
            options: {
                responsive: true,
                title:{
                    display:true,
                    text:'Chart.js Line Chart'
                },
                tooltips: {
                    mode: 'index',
                    intersect: false,
                },
                hover: {
                    mode: 'nearest',
                    intersect: true
                },
            }
        };

        window.onload = function() {
            var ctx = document.getElementById("canvas").getContext("2d");
            window.myLine = new Chart(ctx, config);
            
            
            
            // Start a new Path
            ctx.beginPath();
            ctx.moveTo(0, 0);
            ctx.lineTo(600, 150);

            // Draw the Path
            ctx.stroke();
        };
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>


<div id="container" style="width: 75%;">
  <canvas id="canvas"></canvas>
</div>

Look the result and...

Nothing happened. :(


Solution

  • Using a browser debugger one can see your line drawn but then immediately overwritten by the chart. For example set a breakpoint at ctx.stroke(); and step over it. (I embedded your code into an existing chart I had and therefore was able to use the chrome debugger - not sure if one can debug snippets.)

    This can be overcome by moving your drawing code into a completion event as defined here:

    animation: {
        onComplete: function() {
            var ctx = document.getElementById("canvas").getContext("2d");
            
            // Start a new Path
            ctx.beginPath();
            ctx.moveTo(0, 0);
            ctx.lineTo(600, 150);
    
            // Draw the Path
            ctx.stroke();     
          }
       }
    

    Use of that particular completion event was suggested here.

    With that said you can also draw lines using the scale(s) of the chart for coordinates using the plugin "Line Annotations" chartjs-plugin-annotation.min.js documented here. Again that uses chart coordinates and not absolute canvas coordinates.

    Btw, 0,0 is upper left based on my test. And naturally, the coordinate system of the canvas is oblivious to the chart contents so it seems to have limited value. Again the plugin for line annotations seems like a better path provided you can draw using the coordinates of the graph.

    Here is your snippet with the callback used for your canvas drawing calls.

            var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
            var config = {
                type: 'line',
                data: {
                    labels: ["January", "February", "March", "April", "May", "June", "July"],
                    datasets: [{
                        label: "My First dataset",
                        data: [
                            10, 5, 2, 10, 4, 1, 10
                        ],
                        fill: false,
                    }, {
                        label: "My Second dataset",
                        fill: false,
                        data: [
                            8, 3, 8, 6, 8, 8, 8
                        ],
                    }]
                },
                options: {
                    responsive: true,
                    title:{
                        display:true,
                        text:'Chart.js Line Chart'
                    },
                    tooltips: {
                        mode: 'index',
                        intersect: false,
                    },
                    hover: {
                        mode: 'nearest',
                        intersect: true
                    },
    
                    animation: {
        onProgress: function() {
            var ctx = document.getElementById("canvas").getContext("2d");
            
            // Start a new Path
            ctx.beginPath();
            ctx.moveTo(0, 0);
            ctx.lineTo(600, 150);
    
            // Draw the Path
            ctx.stroke();     
        },
                       onComplete: function() {
                          var ctx = document.getElementById("canvas").getContext("2d");
            
                          ctx.beginPath();
                          ctx.moveTo(0, 0);
                          ctx.lineTo(600, 150);
                          ctx.stroke();   
                       }
                    }
               }
            };
    
            window.onload = function() {
                var ctx = document.getElementById("canvas").getContext("2d");
                window.myLine = new Chart(ctx, config);
                
                
                
            };
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    
    
    <div id="container" style="width: 75%;">
      <canvas id="canvas"></canvas>
    </div>