Black Lives Matter. Please consider donating to Black Girls Code today.
Learn how to use COVID-19 data in open source Dash apps. Register for the Sept 23rd webinar with IQT!

Adding images to annotations

Hi all,

I have been working with plotly in a project for quite some time now, and I have been struggling to do something that a client is looking for in a dashboard that is being developed.

Please take a look at this Styling and Formatting Annotations.

I would really like to use and extend this functionality to something where the user will be able to see an image associated with that point when clicked. The image will be fetched from a database server.

Is it possible to add images to the annotations, and not only text?

Here is an example of what I have at the moment:

As the user hovers over the line, an associated image is fetched and displayed just above the point that is being hovered over. However, what I am now trying to achieve, is trying to “freeze” the image when the user clicks on this point, this way allowing the user to click multiple times and view multiple images at once.

We might want to look at out new layout.image components.

See example here: http://codepen.io/etpinard/pen/VjjoWJ

Thank you for your response Etienne. I didn’t know about this component in the layout options.

I have tried to use plotly relayout to add images on a click event. However, I am experiencing some troubles. Please see the following code as an example of what I have so far (Note that this is very similar to what was done in this example):

             `graphDiv.on('plotly_click', function (eventData) {`
                   var point = eventData.points[0],
                       newAnnotation = {
                         x: point.xaxis.d2l(point.x),
                         y: point.yaxis.d2l(point.y),
                         arrowhead: 6,
                         ax: 0,
                         ay: -80,
                         bgcolor: 'rgba(255, 255, 255, 0.9)',
                         arrowcolor: point.fullData.marker.color,
                         font: {size:12},
                         bordercolor: point.fullData.marker.color,
                         borderwidth: 3,
                         borderpad: 4,
                         text: '<i>Some text will be added here...</i><br>',
                         pointNum: point.pointNumber
                       },
                       newImage = {
                         source: "<Path to some valid image>",
                         xref: "x",
                         yref: "y",
                         x: point.xaxis.d2l(point.x),
                         y: point.yaxis.d2l(point.y),
                         sizex: point.xaxis.d2l(point.x)/36000,
                         sizey: 10,
                         xanchor: "left",
                         yanchor: "bottom",
                         pointNum: point.pointNumber
                       },
                       divid = document.getElementById('plantTimeseries'),
                       newIndex = (divid.layout.annotations || []).length;
                       console.log(newIndex);
                   // delete instead if clicked twice
                   if(newIndex) {
                     var foundCopy = false;
                     divid.layout.annotations.forEach(function(ann, sameIndex) {
                       if(ann.pointNum === newAnnotation.pointNum ) {
                         Plotly.relayout('plantTimeseries', 'annotations[' + sameIndex + ']', 'remove');
                         Plotly.relayout('plantTimeseries', 'images[' + sameIndex + ']', 'remove');
                         foundCopy = true;
                         console.log(divid.layout.annotations.length);
                       }
                     });
                     if(foundCopy){
                       return;
                     }
                   }
                  Plotly.relayout('plantTimeseries', 'annotations[' + newIndex + ']', newAnnotation);
                  Plotly.relayout('plantTimeseries', 'images[' + newIndex + ']', newImage);
                  console.log(divid.layout.annotations.length);
                 }
               }
             });

`

The annotations are added nicely, with multiple annotations added if the same point is not clicked twice (which will delete/remove the annotation instead). The same idea was tackled for the images, but it seems that only one image is added at a time, and only if the showing image is removed (by clicking on the same point twice), does the next image show up. Here is two figures to illustrate my problem:

@Evert Looks like you discovered a bug. Layout image should behave the same via relayout as shapes.

Please subscribe to https://github.com/plotly/plotly.js/issues/670 for the latest development info.

Thanks for reporting.

Hi all,

Can you suggest a way to do this in Python? From what I understand, I would be appending a unique image to each marker’s “text” element.

Thank you! :slight_smile:

See https://plot.ly/python/images/ for some examples in Python

Thanks chriddyp. Specifically, I am looking to append an image into the text box of each marker, which the python/images page doesn’t include an example of. From a bit of research into the plotly api, it seems that plotly collates all of its graph data into json format before making it’s graph (Please correct me if I am wrong). I haven’t yet looked into this, but if there is a way to prepare an image for json so that the image would show up in the graph, that would potentially be the answer. Thanks again for the response.