Search code examples
highcharts

How to add one or more PNG images on top of HighCharts with plotBackgroundColor?


My goal is to have one or more PNG images displayed on top of a line chart HighCharts with a color gradient as shown below:

enter image description here

I have tried the following code, but the image seems to be buried behind the chart.

Also I am not understanding how to correctly position the image (e.g. I had to use the value 400 to get the image to be positioned at the 200 marker - chart.plotTop + chart.yAxis[0].toPixels(400))

document.addEventListener('DOMContentLoaded', function () {
    var temperatures = [
        [Date.UTC(2024, 8, 1), 20],  // September 1st
        [Date.UTC(2024, 8, 2), 39], 
        [Date.UTC(2024, 8, 3), 58], 
        [Date.UTC(2024, 8, 4), 78], 
        [Date.UTC(2024, 8, 5), 95], 
        [Date.UTC(2024, 8, 6), 110], 
        [Date.UTC(2024, 8, 7), 125], 
        [Date.UTC(2024, 8, 8), 142], 
        [Date.UTC(2024, 8, 9), 160], 
        [Date.UTC(2024, 8, 10), 180], 
        [Date.UTC(2024, 8, 11), 200],  
        [Date.UTC(2024, 8, 12), 219], 
        [Date.UTC(2024, 8, 13), 238], 
        [Date.UTC(2024, 8, 14), 258], 
        [Date.UTC(2024, 8, 15), 275], 
        [Date.UTC(2024, 8, 16), 290], 
        [Date.UTC(2024, 8, 17), 315], 
        [Date.UTC(2024, 8, 18), 332], 
        [Date.UTC(2024, 8, 19), 350], 
        [Date.UTC(2024, 8, 20), 370]         
    ];

    // Options for the chart
    var options = {
        chart: {
            type: 'line',
            plotBackgroundColor: {
                linearGradient: [0, 0, 0, 400],
                stops: [
                    [0, 'green'],  
                    [1, 'yellow']   
                ]
            },
            plotBackgroundImage: null
        },
        title: {
            text: 'Temperature Line Chart'
        },
        xAxis: {
            type: 'datetime',
            dateTimeLabelFormats: {
                month: '%b %e'  
            },
            min: Date.UTC(2024, 8, 1),  // Start from September 1st
            max: Date.UTC(2024, 8, 20), 
        },
        yAxis: {
            title: {
                text: 'Temperature'
            }
        },
        plotOptions: {
            series: {
                marker: {
                    enabled: false  // Disable markers on data points
                }
            }
        },
        series: [{
            name: 'Temperature',
            data: temperatures
        }]
    };

    var chart = Highcharts.chart('container', options);

    Highcharts.addEvent(Highcharts.Chart, 'render', function() {
        chart.renderer.image('https://cdn-icons-png.flaticon.com/64/8445/8445275.png',  // URL of the PNG image
            chart.plotLeft + chart.xAxis[0].toPixels(Date.UTC(2024, 8, 8)),
            chart.plotTop + chart.yAxis[0].toPixels(400), 
            64, 64  
        ).add().toFront(); 
    });

Solution

  • When in comes to the picture behind the chart, using toFront() is one choice, and zIndex also works well.

    In case of the positioning, the toPixels() method uses the axis position as its argument, and you don't have to add plotTop or plotLeft. However, to position image correctly, you should also consider it's height and width.

    Here's an improved version of the code where the image is added in the render() method, which helps make it responsive:

    let temperatures = [
      [Date.UTC(2024, 8, 1), 20],
      [Date.UTC(2024, 8, 2), 39],
      [Date.UTC(2024, 8, 3), 58],
      [Date.UTC(2024, 8, 4), 78],
      [Date.UTC(2024, 8, 5), 95],
      [Date.UTC(2024, 8, 6), 110],
      [Date.UTC(2024, 8, 7), 125],
      [Date.UTC(2024, 8, 8), 142],
      [Date.UTC(2024, 8, 9), 160],
      [Date.UTC(2024, 8, 10), 180],
      [Date.UTC(2024, 8, 11), 200],
      [Date.UTC(2024, 8, 12), 219],
      [Date.UTC(2024, 8, 13), 238],
      [Date.UTC(2024, 8, 14), 258],
      [Date.UTC(2024, 8, 15), 275],
      [Date.UTC(2024, 8, 16), 290],
      [Date.UTC(2024, 8, 17), 315],
      [Date.UTC(2024, 8, 18), 332],
      [Date.UTC(2024, 8, 19), 350],
      [Date.UTC(2024, 8, 20), 370]
    ];
    
    Highcharts.chart('container', {
      chart: {
        events: {
          render() {
            let chart = this,
              imageSize = 64
            if (!chart.myImage) {
              chart.myImage = chart.renderer.image('https://cdn-icons-png.flaticon.com/64/8445/8445275.png', chart.xAxis[0].toPixels(Date.UTC(2024, 8, 11)) - imageSize / 2,
                chart.yAxis[0].toPixels(200) - imageSize / 2,
                imageSize, imageSize
              ).add();
            }
            chart.myImage.attr({
              x: chart.xAxis[0].toPixels(Date.UTC(2024, 8, 11)) - imageSize / 2,
              y: chart.yAxis[0].toPixels(200) - imageSize / 2,
              zIndex: 100
            })
          }
        },
        type: 'line',
        plotBackgroundColor: {
          linearGradient: [0, 0, 0, 400],
          stops: [
            [0, 'green'],
            [1, 'yellow']
          ]
        },
        plotBackgroundImage: null
      },
      title: {
        text: 'Temperature Line Chart'
      },
      xAxis: {
        type: 'datetime',
        dateTimeLabelFormats: {
          month: '%b %e'
        },
        min: Date.UTC(2024, 8, 1),
        max: Date.UTC(2024, 8, 20),
      },
      yAxis: {
        title: {
          text: 'Temperature'
        }
      },
      plotOptions: {
        series: {
          marker: {
            enabled: false
          }
        }
      },
      series: [{
        name: 'Temperature',
        data: temperatures
      }]
    });
    

    Demo: https://jsfiddle.net/BlackLabel/z5gkr68e/