Trying to insert an image inside a scatter plot.

Hi, I’m trying to include a picture in a scatter plot, which I can hopefully then make it extend from the origin (0,0) to some value (xpoint,ypoint). My picture is located in a local directory on the same level as the .md file. Here is the code I have written:

    <div class="card" id="phaseSpace" style="cursor: crosshair">${
        resize((width) => Plot.plot({
            title: "Phase Space",
            x: { domain: [0, 1] }, // Adjust according to your data scale
            y: { domain: [0, 5] },
            marks: [
                Plot.image({x: 0, y: 0, src: "./best_param.png", preserveAspectRatio: "none"}),
                Plot.ruleY([0]),
                Plot.ruleX([0]),
                //Plot.frame(),
                Plot.dot(currentpoint, {x: "x", y: "y", curve: "step", stroke: "black"}),
                Plot.dot(bestpoints, {x: "x", y: "y", curve: "step", stroke: "red"}),
                Plot.axisX({anchor: "bottom", label: "energy"}),
            ]
        }))
    }</div>

The problem I’m having is that all the points and axes show up correctly, but the image does not show on the plot. I’d appreciate some help from the community.

Thank you!
– Jose

Hey jacolonr!

I see a couple of things that might help:

First, the image mark (like your other dot marks) wants an array of objects to iterate over as a dataset — if you just want one image you can work around this by passing in an array with a single empty object, like this:

Plot.image([{}], {x: 0, y: 0...

Second, the url for your image should be loaded into a variable in a separate JS block (so you get the benefits of code blocks implicitly awaiting on each others’ values), which you can then reference in your mark, like this:

const imageURL = FileAttachment("data/example.jpeg").url()
Plot.image([{}], {x: 0, y: 0, width: 100, height: 100, src: imageURL, preserveAspectRatio: "none"}),

However, it’s important to note that x: 0, y: 0 aren’t coordinates in screen space but in data space! The image will be placed at 0, 0 as defined by the rest of your data. So you might have to noodle around with hard-coded coordinates a bit.

If you want a true background image, Plot supports that through the top-level style options, like this:

const imageURL = FileAttachment("data/example.jpeg").url()
Plot.plot({
  style: {
    padding: "0px",
    color: "black",
    background: `url(${imageURL})`,
    backgroundSize: "cover"
  },
  marks: [
    ...

You can read more about the image mark here: Image mark | Observable Plot

…and more about loading files in Framework here:
https://observablehq.com/framework/files

Edit:

I’ve just been informed by other members of the Observable team that as of Framework 1.5, files have a synchronous href property, which would mean that you don’t need to load the URL into a variable in a separate code block.

So you could do this with the image mark:

Plot.image([{}], {x: 0, y: 0, width: 100, height: 100, src: FileAttachment("data/example.jpeg").href, preserveAspectRatio: "none"}),

And this in the style options to load a background image:

Plot.plot({
  style: {
    padding: "0px",
    color: "black",
    background: `url(${FileAttachment("data/example.jpeg").href})`,
    backgroundSize: "cover"
  },
  marks: [
    ...
1 Like

Hi,

Thank you so much! This fixed my issue! I was able to insert the picture directly into the plot and control its position/size.

Thanks again,

  • Jose
1 Like