istencsaszar
Posts: 2
Joined: Wed Jul 06, 2022 7:39 am

Set custom icon/image on bars of BarChart

Hi,
I am new with Highcharts and have this question:

I have to create a barchart and have to add custom icons/images on every bar conditionally.

For example:

I have a barchart with 5 values. The current value of the first bar is 125 (the current month's value). If the value in the previous month (stored in an array called prevData[0].) was higher, than I must show an arrow icon pointing down.

Is there a way to do this? Thanks in advance.

https://jsfiddle.net/4d6oLjng/
hubert.k
Posts: 1164
Joined: Mon Apr 11, 2022 11:48 am

Re: Set custom icon/image on bars of BarChart

Hello istencsaszar!
Welcome to our forum and thanks for contacting us with your question!

You can add some images as data labels to each column by setting dataLabels.useHTML property to true. To calculate the rotation of arrow you can make a loop through your data before chart configuration and add some custom property, which will be used in dataLabels.formatter callback function to calculate rotation of arrow. I have prepared a simple demo for you.

Demo: https://jsfiddle.net/BlackLabel/0c2se9wj/
API Reference: https://api.highcharts.com/highcharts/s ... dataLabels

If you have any further questions, feel free to ask.
Kind regards!
Hubert Kozik
Highcharts Developer
istencsaszar
Posts: 2
Joined: Wed Jul 06, 2022 7:39 am

Re: Set custom icon/image on bars of BarChart

Hello Hubert!

Thanks for the answer, I think this is what I needed. :)
hubert.k
Posts: 1164
Joined: Mon Apr 11, 2022 11:48 am

Re: Set custom icon/image on bars of BarChart

You're welcome! In case of any further questions, feel free to contact us again.
Hubert Kozik
Highcharts Developer
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: Set custom icon/image on bars of BarChart

Hello,
It's possible somehow to add an icon/image when existsa overlapping of tasks?

Check here what I mean: https://ibb.co/Bs2GdbT

Thanks, Paulo Torres
jakub.j
Posts: 1091
Joined: Tue Jan 24, 2023 11:14 am

Re: Set custom icon/image on bars of BarChart

Thanks for contacting us with your question!

I created a custom logic on chart.events.load which checks if any of the tasks overlap and if so it enables the dataLabel with an icon and positions it exactly in the place of the overlap. You can change the icon in the dataLabels.format in line 69.

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

Let me know if that was what you were looking for!
Kind regards
Jakub
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: Set custom icon/image on bars of BarChart

Hi Jakub,
Thanks again for your help :)

I forgot to say that I'm working on TreeGrid, it's possible to have this feature in TreeGrid?

Thanks, Paulo Torres
jakub.j
Posts: 1091
Joined: Tue Jan 24, 2023 11:14 am

Re: Set custom icon/image on bars of BarChart

You're welcome!

Yes, it works correctly with TreeGrid, see demo:

Demo: https://jsfiddle.net/BlackLabel/4mq5egtu/

If any glitches arise please inform as soon as possible.
Kind regards
Jakub
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: Set custom icon/image on bars of BarChart

jakub.j wrote: Fri Dec 22, 2023 9:04 am You're welcome!

Yes, it works correctly with TreeGrid, see demo:

Demo: https://jsfiddle.net/BlackLabel/4mq5egtu/

If any glitches arise please inform as soon as possible.
Kind regards
Jakub
Hi Jakub,
The issue in this JS it's because the Y variable it's something mandatory and in my code I don't use this variable, as I let the Highcharts organize in automatic way. There is a possibility to have this without Y?

Thanks, Paulo Torres
jakub.j
Posts: 1091
Joined: Tue Jan 24, 2023 11:14 am

Re: Set custom icon/image on bars of BarChart

Hey!

You don't need to provide 'y' value to the data and it works fine, see:

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

Feel free to ask any further questions!
Kind regards
Jakub
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: Set custom icon/image on bars of BarChart

Hi Jakub,
For some reason in my App with your code (Copy-Paste) the image doesn't appears, however I can find the image in the html below the bar.
Do you have some idea to solve this?

You can see here: https://personal-ieehgzmp.outsystemsclo ... mo/Screen1

Thanks a lot again
jakub.j
Posts: 1091
Joined: Tue Jan 24, 2023 11:14 am

Re: Set custom icon/image on bars of BarChart

Hey!

I've created the demo in react and everything seem to work fine, could you please reproduce the problem you encounter in the demo below or any other live demo that I can work on?

Demo: https://codesandbox.io/p/sandbox/highch ... 2Fdemo.jsx

Kind regards
Jakub
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: Set custom icon/image on bars of BarChart

Hi Jakub,
Maybe it's a problem of my platform. Do you see any problem on my code?

Code: Select all

var today = new Date(),
    day = 1000 * 60 * 60 * 24,

    // Dynamic Variables for Tooltip
    tooltipStartText = $parameters.TooltipStartText,
    tooltipEndText = $parameters.TooltipEndText,
    tooltipCompletedText = $parameters.TooltipCompletedText,
    tooltipOwnerText = $parameters.TooltipOwnerText,
    tooltipProjectManagerText = $parameters.TooltipProjectManagerText,

    // Utility functions
    dateFormat = Highcharts.dateFormat,
    defined = Highcharts.defined,
    isObject = Highcharts.isObject;

// Set to 00:00:00:000 today
today.setUTCHours(0);
today.setUTCMinutes(0);
today.setUTCSeconds(0);
today.setUTCMilliseconds(0);


// THE CHART
Highcharts.ganttChart($parameters.ChartContainerId, {

 chart: {
      events: {
        load: function () {
          const chart = this;

          chart.series.forEach((series) => {
            series.points.forEach((point) => {
              chart.series.forEach((insideSeries) => {
                series.points.forEach((insidePoint) => {
                  if (
                    insidePoint.y === point.y &&
                    point.x < insidePoint.x2 &&
                    point.x2 > insidePoint.x2 &&
                    insidePoint.index < point.index
                  ) {
                    point.update({
                      dataLabels: {
                        enabled: true,
                        align: "left",
                        x: -20,
                      },
                    });
                  }

                  if (
                    insidePoint.y === point.y &&
                    point.x2 > insidePoint.x &&
                    point.x2 < insidePoint.x2 &&
                    insidePoint.index < point.index
                  ) {
                    point.update({
                      dataLabels: {
                        enabled: true,
                        align: "right",
                        x: -10,
                      },
                    });
                  }
                });
              });
            });
          });
        },
      },
    },

    yAxis: {
      type: "treegrid",
      uniqueNames: true,
    },

    title: {
        text: $parameters.Title
    },
    subtitle: {
        text: $parameters.SubTitle
    },
    navigator: {
        enabled: $parameters.HasNavigator,
        liveRedraw: true,
        series: {
            type: 'gantt',
            pointPlacement: 0.5,
            pointPadding: 0.25,
            accessibility: {
                enabled: true
            }
        },
    },
    scrollbar: {
        enabled: $parameters.HasScrollbar
    },
    rangeSelector: {
        enabled: $parameters.HasRangeSelector
    },

    yAxis: {
        type: 'treegrid',
        uniqueNames: $parameters.IsUniqueNames
    },

    chart: {
        backgroundColor: $parameters.BackgroundColor,
        style: {
            fontFamily: $parameters.Font,
            //stroke: 'black',
        }
    },

    //Customization of tooltip
    tooltip: {
        pointFormatter: function() {
            var point = this,
                format = '%e. %b',
                options = point.options,
                completed = options.completed,
                amount = isObject(completed) ? completed.amount : completed,
                status = ((amount || 0) * 100) + '%',
                lines;

            lines = [{
                value: point.name,
                style: 'font-weight: bold;'
            }, {
                title: tooltipStartText,
                value: dateFormat(format, point.start)
            }, {
                visible: !options.milestone,
                title: tooltipEndText,
                value: dateFormat(format, point.end)
            }, {
                title: tooltipCompletedText,
                value: status
            }, {
                visible: options.isShowOwner,
                title: tooltipOwnerText,
                value: options.owner || 'unassigned'
            }, {
                visible: options.isProjectManager,
                title: tooltipProjectManagerText,
                value: options.projectManager || 'unassigned'
            }];


            return lines.reduce(function(str, line) {
                var s = '',
                    style = (
                        defined(line.style) ? line.style : 'font-size: 0.8em;'
                    );
                if (line.visible !== false) {
                    s = (
                        '<span style="' + style + '">' +
                        (defined(line.title) ? line.title + ': ' : '') +
                        (defined(line.value) ? line.value : '') +
                        '</span><br/>'
                    );
                }
                return str + s;
            }, '');
        }
    },

    xAxis: [{ // first x-axis
        currentDateIndicator: $parameters.IsCurrDateIndicator,
        min: $parameters.StartDate.getTime(),
        max: $parameters.EndDate.getTime() + ($parameters.EndDateMarginDays * day),
        tickInterval: 1000 * 60 * 60 * 24 // 1 month
    }, { // second x-axis
        tickInterval: 1000 * 60 * 60 * 24 * 7 // 1 week
    }, { // third x-axis
        tickInterval: 1000 * 60 * 60 * 24 * 30, // 1 day
    }],


    accessibility: {
        keyboardNavigation: {
            seriesNavigation: {
                mode: 'serialize'
            }
        },

        point: {
            descriptionFormatter: function(point) {
                var completedValue = point.completed ?
                    point.completed.amount || point.completed : null,
                    completed = completedValue ?
                    ' Task ' + Math.round(completedValue * 1000) / 10 + '% completed.' :
                    '',
                    dependency = point.dependency &&
                    point.series.chart.get(point.dependency).name,
                    dependsOn = dependency ? ' Depends on ' + dependency + '.' : '';

                return Highcharts.format(
                    point.milestone ?
                    '{point.yCategory}. Milestone at {point.x:%Y-%m-%d}. Owner: {point.owner}.{dependsOn}' :
                    '{point.yCategory}.{completed} Start {point.x:%Y-%m-%d}, end {point.x2:%Y-%m-%d}. Owner: {point.owner}.{dependsOn}', {
                        point,
                        completed,
                        dependsOn
                    }
                );
            }
        }
    },



    plotOptions: {
        series: {
            cursor: 'pointer',
            allowPointSelect: $parameters.IsAllowPointSelect,
            dragDrop: {
                draggableX: $parameters.IsDraggableX,
                dragPrecisionX: day / 3 // Snap to eight hours
            },
            point: {
                events: {
                    // Function for click on bar, will return the ID of element
                    click: function() {
                        $actions.OnClickElement(this.aux_id, this.aux_type);
                    },

                    drop: function(e) {
                        $actions.OnDragDropElement(this.aux_id, this.aux_type, this.start, this.end);
                    }
                }
            }
        },

        gantt: {
            dataLabels: {
                formatter: function() {
                    const point = this.point,
                        name = point.name;

                    if (name !== '') {
                        return name;
                    } else {
                        return point.options.completed.amount * 100 + '%';
                    }
                }
            }
        },

        lang: {
            accessibility: {
                axis: {
                    xAxisDescriptionPlural: 'The chart has a two-part X axis showing time in both week numbers and days.',
                    yAxisDescriptionPlural: 'The chart has one Y axis showing task categories.'
                }
            }
        },

        //Remove logo/credits Highcharts
        credits: {
            enabled: false
        }
    },

    //Json with elements of Gantt
    series: [{
        name: $parameters.ProjectName,
        data: JSON.parse($parameters.JSONData),

        dataLabels: {
          enabled: false,
          format:
            '<img src="https://www.highcharts.com/samples/graphics/sun.png">',
          useHTML: true,
          outside: true,
          y: -10,
        },
      },
    ],
  });
Thanks
jakub.j
Posts: 1091
Joined: Tue Jan 24, 2023 11:14 am

Re: Set custom icon/image on bars of BarChart

Hey, thanks for the code!

I see where the problem is, you have multiple chart object declarations in your config and the one below is overwriting our chart object with events, that's why the icons aren't displayed.

Code: Select all

 chart: {
        backgroundColor: $parameters.BackgroundColor,
        style: {
            fontFamily: $parameters.Font,
            //stroke: 'black',
        }
    }

If you remove the duplicate declaration, everything works fine, see demo:
Demo: https://jsfiddle.net/BlackLabel/pthvj0of/

Feel free to ask any further questions!
Kind regards
Jakub
[email protected]
Posts: 65
Joined: Fri Aug 26, 2022 9:33 am

Re: Set custom icon/image on bars of BarChart

Hi Jakub,
I noticed that and I removed but still the same behavior. Maybe it's a problem of my platform?
The icon is on HTML but under the bar, that's we can't see it. I'll check if it's possible to solve with CSS.

Another issue I have with the code is in some cases and I don't understand why I have several errors on the console: Error: <rect> attribute y: Expected length, "NaN". When this happens I don't have overlaping of tasks.

You can see here: https://personal-ieehgzmp.outsystemsclo ... /NovoTeste

Thanks a lot again.
Paulo Torres

Return to “Highcharts Usage”