chartjs / chartjs-plugin-annotation

Annotation plugin for Chart.js
MIT License
603 stars 325 forks source link

How can I show image as annotation label? #813

Closed nijatmursali closed 1 year ago

nijatmursali commented 1 year ago

I'm working on one project and I need to show my flag image and I have checked this library and added annotation, but it does not show image. I have checked documentation , but there is Utils.getImage() function used to get image. I'm using plain html(cdns for both chartjs and this library) and Javascript.

I get following result: image

but I want to show flag image.

My annotation object is like this:

const annotation = {
            type: 'line',
            borderColor: 'red',
            borderWidth: 2,
            display: (ctx) => ctx.chart.isDatasetVisible(1),
            label: {
                content: "/assets/flag.png",
                display: true,
                content: '',
                position: 'start'
            },
            scaleID: 'x',
            value: 3.9
        };
stockiNail commented 1 year ago

@nijatmursali having a look to your config, I see you set twice the content option, in label node.

But assuming the empty string is just a issue, if you want to add an image you must have a HTMLImageElement instance and not a path of the application (I think an URL).

See the doc about line label, see the content option possible value types.

And assuming the /assets/flag.png is the path of your application, you could do the following:

const flag = new Image();
flag.onload = function() {
  // sets chart options
  const annotation = {
            type: 'line',
            borderColor: 'red',
            borderWidth: 2,
            display: (ctx) => ctx.chart.isDatasetVisible(1),
            label: {
                content: flag,  // <-- image instance
                display: true,
                position: 'start'
            },
            scaleID: 'x',
            value: 3.9
        };
  // creates here your chart
  // to be sure that image is loaded.
};
flag.src = '/assets/flag.png';
stockiNail commented 1 year ago

@nijatmursali I have seen your question in SO. About the look and feel of the chart, yes it's possible to have it as you put in the picture.

nijatmursali commented 1 year ago

Thank you, I have added it as image source and it worked, partially. I want to have only image without backgroundColor, but when I set the backgroundColor: transparent it removes the image as well.

image

stockiNail commented 1 year ago

The backgroundColor options doesn't affect the image if the image has got the background as transparent itself. It seems the the image doesn't have a transparent background.

I did a test with "backgroundColor: 'transparent'", and the image will always be shown. Try it in the sample: https://www.chartjs.org/chartjs-plugin-annotation/latest/samples/line/image.html

Maybe you can create a codepen so I can test it as well.

nijatmursali commented 1 year ago

I think I have a problem with image itself. I need to double check it. Thank you for your help. Annotation part is solved. I need to figure out issue I shared on SO.

stockiNail commented 1 year ago

I'm having a look as well even if I haven't spent much time to have a look. But I have created a codepen to test it. https://codepen.io/stockinail/pen/ExREWrq

nijatmursali commented 1 year ago

Thank you. Hopefully I can get answer to it. Got some brain explosion by writing that code.

stockiNail commented 1 year ago

I have added a comment to SO to understand well what you need to calculate.

nijatmursali commented 1 year ago

Thank you, I added comment.

stockiNail commented 1 year ago

Thank you, I added comment.

Answered.

nijatmursali commented 1 year ago

Just a question, how can I show my annotation image like this, in the screenshot annotation image is outside the red line. image

My current design looks like this:

image

My annotation const:

        const flag = new Image();
        flag.src = 'assets/images/flag_t.svg';
        const annotation = {
            type: 'line',
            borderColor: 'red',
            borderWidth: 2,
            display: (ctx) => ctx.chart.isDatasetVisible(1),
            label: {
                content: flag,
                display: true,
                backgroundColor: 'black',
                width: '30%',
                height: '30%',
                position: 'start'
            },
            scaleID: 'x',
            value: where
        };

and chart options:

 options: {
                scales: {
                    x: {
                        grid: {
                            display: false
                        }
                    }

                },
                plugins: {
                    legend: {
                        display: true,
                        position: 'bottom'
                    },
                    annotation: {
                        annotations: {
                            annotation
                        }
                    }
                }
            }
stockiNail commented 1 year ago

@nijatmursali you can use yAdjust option, for instance yAdjust: -100 means that the label is moved -100 pixels from original calculation (based on position 'start').

nijatmursali commented 1 year ago

Thank you for your reply. If I do like that, it is going out of canvas and I feel like I need to increase my canvas height (or have some kind of padding)

image

stockiNail commented 1 year ago

@nijatmursali apologize but I forgot to write you that you have to set also clip: false in the annotation.

                    annotation: {
                        clip: false, // <-- must be added
                        annotations: {
                            annotation
                        }
                    }
stockiNail commented 1 year ago

@nijatmursali and I suggest you to add layout.padding to the chart options if you don't have any legend or title on top.

nijatmursali commented 1 year ago

Unfortunately it still gives similar behavior.. image

stockiNail commented 1 year ago

@nijatmursali see my previous post.

Add space to the top of the chart, as following:

options: {
  layout: {
    padding: {
      top: 32 //<- I suggest to set the height of the image and additional pixels
    }
  },
  scales: { .....
nijatmursali commented 1 year ago

Yes, it solved the issue thank you. Is it possible to set the height of annotation line?

stockiNail commented 1 year ago

Yes, you can.

You shoudl change the annotation config in order to indicate the limit you want:

        const annotation = {
            type: 'line',
            borderColor: 'red',
            borderWidth: 2,
            display: (ctx) => ctx.chart.isDatasetVisible(1),
            label: {
                content: flag,
                display: true,
                backgroundColor: 'black',
                width: '30%',
                height: '30%',
                position: 'start'
            },
            // scaleID: 'x', --> must be removed and go to yScaleID
            // value: where --> must be removed and go to xMin and xMax
           xScaleID: 'x',
           yScaleID: 'y',
           xMin: where,
           xMax: where,
           yMin: 0,
           yMax: [what you want as max value and than you can limit the line]
        };
nijatmursali commented 1 year ago

Thank you. It solved the problem.

One last question, in mobile chart looks like this, but I set my width and height to 100% in my css for canvas.

canvas {
    width: 100%;
  }

image

stockiNail commented 1 year ago

Have a look to responsive doc of CHART.JS: https://www.chartjs.org/docs/latest/configuration/responsive.html#responsive-charts

nijatmursali commented 1 year ago

responsive is set to True by default, but graph does not look responsive.