chart.js

Give box annotation only left and right border but not on top and bottom


I am using ChartJS annotation plugin in order to display some annotations.

I am using the box annotation, but I am not sure how I can display a border for that annotation only on the left and right edge, but not top and bottom?


Solution

  • You can use the afterDraw hook of the annotation to draw custom stuff over your annotation.

    To have only the left and right borders, the simplest way seems to set the borderColor property to 'transparent' and draw the two borders using the intended color in the afterDraw:

    afterDraw(context){
       const element = context.element,
          options = element.options,
          ctx = context.chart.ctx;
       ctx.save();
       ctx.strokeStyle = 'rgb(165, 214, 167)';
       ctx.lineWidth = options.borderWidth;
       ctx.beginPath();
       ctx.moveTo(element.x, element.y);
       ctx.lineTo(element.x, element.y2);
       ctx.stroke();
       ctx.beginPath();
       ctx.moveTo(element.x2, element.y);
       ctx.lineTo(element.x2, element.y2);
       ctx.stroke();
       ctx.restore();
    }
    

    This is the basic version that draw just the simple vertical lines. The following snippet implements a complete version, that takes into consideration all available annotation options like shadow, rotation, line dash; the code is based on the actual plugin source code.

    const data = {
       labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
       datasets: [{
          type: 'line',
          label: 'Dataset 1',
          borderColor: 'rgb(54, 162, 235)',
          borderWidth: 2,
          fill: false,
          data: Array.from({length: 100}, () => Math.round(Math.random() * 100))
       }]
    };
    
    const annotation1 = {
       type: 'box',
       backgroundColor: 'rgba(165, 214, 167, 0.2)',
       borderColor: 'transparent',//'rgb(165, 214, 167)',
       borderShadowColor: 'gray',
       shadowOffsetX: 4,
       shadowOffsetY: 4,
       borderWidth: 5,
       label: {
          display: true,
          content: ['Box', 'annotation'],
          textAlign: 'center'
       },
       rotation: 45,
       xMax: 'May',
       xMin: 'April',
       xScaleID: 'x',
       yMax: 75,
       yMin: 25,
       yScaleID: 'y',
       afterDraw(context){
          const element = context.element,
             options = element.options,
             ctx = context.chart.ctx;
          ctx.save();
          ctx.strokeStyle = 'rgb(165, 214, 167)';
          ctx.lineWidth = options.borderWidth;
          ctx.lineCap = options.borderCapStyle || 'butt';
          ctx.lineJoin = options.borderJoinStyle || 'miter';
          if(options.rotation){
             const {x, y} = element.getCenterPoint();
             ctx.translate(x, y);
             ctx.rotate(options.rotation * Math.PI / 180);
             ctx.translate(-x, -y);
          }
          if(options.borderDash){
             ctx.setLineDash(options.borderDash);
             ctx.lineDashOffset = options.borderDashOffset;
    
          }
          if(options.shadowColor !== 'transparent'){
             ctx.shadowColor = options.borderShadowColor;
             ctx.shadowBlur = options.shadowBlur;
             ctx.shadowOffsetX = options.shadowOffsetX;
             ctx.shadowOffsetY = options.shadowOffsetY;
          }
          ctx.beginPath();
          ctx.moveTo(element.x, element.y);
          ctx.lineTo(element.x, element.y2);
          ctx.stroke();
          ctx.beginPath();
          ctx.moveTo(element.x2, element.y);
          ctx.lineTo(element.x2, element.y2);
          ctx.stroke();
          ctx.restore();
       }
    };
    
    const config = {
       type: 'line',
       data,
       options: {
          scales: {
             y: {
                beginAtZero: true,
                min: 0,
                max: 100
             }
          },
          plugins: {
             annotation: {
                annotations: {
                   annotation1,
                }
             }
          }
       }
    };
    
    new Chart('myChart', config);
    <div style="height: 300px">
       <canvas id="myChart">
       </canvas>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-annotation/3.1.0/chartjs-plugin-annotation.min.js"></script>