Text and Annotations in JavaScript

How to add text labels and annotations to D3.js-based plots in javascript.


Plotly Studio: Transform any dataset into an interactive data application in minutes with AI. Try Plotly Studio now.

var trace1 = {
  x: [0, 1, 2],
  y: [1, 1, 1],
  mode: 'lines+markers+text',
  name: 'Lines, Markers and Text',
  text: ['Text A', 'Text B', 'Text C'],
  textposition: 'top',
  type: 'scatter'
};
var trace2 = {
  x: [0, 1, 2],
  y: [2, 2, 2],
  mode: 'markers+text',
  name: 'Markers and Text',
  text: ['Text D', 'Text E', 'Text F'],
  textposition: 'bottom',
  type: 'scatter'
};
var trace3 = {
  x: [0, 1, 2],
  y: [3, 3, 3],
  mode: 'lines+text',
  name: 'Lines and Text',
  text: ['Text G', 'Text H', 'Text I'],
  textposition: 'bottom',
  type: 'scatter'
};
var data = [trace1, trace2, trace3];
var layout = {showlegend: false};
Plotly.newPlot('myDiv', data, layout);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var trace1 = {\n x: [0, 1, 2],\n y: [1, 1, 1],\n mode: 'lines+markers+text',\n name: 'Lines, Markers and Text',\n text: ['Text A', 'Text B', 'Text C'],\n textposition: 'top',\n type: 'scatter'\n};\nvar trace2 = {\n x: [0, 1, 2],\n y: [2, 2, 2],\n mode: 'markers+text',\n name: 'Markers and Text',\n text: ['Text D', 'Text E', 'Text F'],\n textposition: 'bottom',\n type: 'scatter'\n};\nvar trace3 = {\n x: [0, 1, 2],\n y: [3, 3, 3],\n mode: 'lines+text',\n name: 'Lines and Text',\n text: ['Text G', 'Text H', 'Text I'],\n textposition: 'bottom',\n type: 'scatter'\n};\nvar data = [trace1, trace2, trace3];\nvar layout = {showlegend: false};\nPlotly.newPlot('myDiv', data, layout);\n"}">
Plotly.newPlot('myDiv', [{
  x: [1,2,3],
  y: [2,1,2]
}], {
  annotations: [{
    xref: 'paper',
    yref: 'paper',
    x: 0,
    xanchor: 'right',
    y: 1,
    yanchor: 'bottom',
    text: 'X axis label',
    showarrow: false
  }, {
    xref: 'paper',
    yref: 'paper',
    x: 1,
    xanchor: 'left',
    y: 0,
    yanchor: 'top',
    text: 'Y axis label',
    showarrow: false
  }]
  
})
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"Plotly.newPlot('myDiv', [{\n x: [1,2,3],\n y: [2,1,2]\n}], {\n annotations: [{\n xref: 'paper',\n yref: 'paper',\n x: 0,\n xanchor: 'right',\n y: 1,\n yanchor: 'bottom',\n text: 'X axis label',\n showarrow: false\n }, {\n xref: 'paper',\n yref: 'paper',\n x: 1,\n xanchor: 'left',\n y: 0,\n yanchor: 'top',\n text: 'Y axis label',\n showarrow: false\n }]\n \n})"}">
var trace1 = {
  x: [0, 1, 2, 3, 4, 5, 6, 7, 8],
  y: [0, 1, 3, 2, 4, 3, 4, 6, 5],
  type: 'scatter'
};
var trace2 = {
  x: [0, 1, 2, 3, 4, 5, 6, 7, 8],
  y: [0, 4, 5, 1, 2, 2, 3, 4, 2],
  type: 'scatter'
};
var data = [trace1, trace2];
var layout = {
  showlegend: false,
  annotations: [
    {
      x: 2,
      y: 5,
      xref: 'x',
      yref: 'y',
      text: 'Annotation Text',
      showarrow: true,
      arrowhead: 7,
      ax: 0,
      ay: -40
    }
  ]
};
Plotly.newPlot('myDiv', data, layout);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var trace1 = {\n x: [0, 1, 2, 3, 4, 5, 6, 7, 8],\n y: [0, 1, 3, 2, 4, 3, 4, 6, 5],\n type: 'scatter'\n};\nvar trace2 = {\n x: [0, 1, 2, 3, 4, 5, 6, 7, 8],\n y: [0, 4, 5, 1, 2, 2, 3, 4, 2],\n type: 'scatter'\n};\nvar data = [trace1, trace2];\nvar layout = {\n showlegend: false,\n annotations: [\n {\n x: 2,\n y: 5,\n xref: 'x',\n yref: 'y',\n text: 'Annotation Text',\n showarrow: true,\n arrowhead: 7,\n ax: 0,\n ay: -40\n }\n ]\n};\nPlotly.newPlot('myDiv', data, layout);\n"}">

If the x or y positions of an annotation reference a log axis, you need to provide that position as a log10 value when adding the annotation. In this example, the yaxis is a log axis so we pass the log10 value of 1000 to the annotation's y position.

var dates = [
    "2024-01-01",
    "2024-01-02",
    "2024-01-03",
    "2024-01-04",
    "2024-01-05",
    "2024-01-06",
];

var y_values = [1, 30, 70, 100, 1000, 10000000];

var trace1 = {
    x: dates,
    y: y_values,
    mode: 'lines+markers',
    type: 'scatter'
};

var layout = {
    yaxis: {
        type: 'log',
    },
    annotations: [
        {
            x: '2024-01-05',
            y: Math.log10(1000),
            text: 'Log axis annotation',
            showarrow: true,
            xanchor: 'right',
        }
    ]
};

var data = [trace1];

Plotly.newPlot('myDiv', data, layout);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var dates = [\n \"2024-01-01\",\n \"2024-01-02\",\n \"2024-01-03\",\n \"2024-01-04\",\n \"2024-01-05\",\n \"2024-01-06\",\n];\n\nvar y_values = [1, 30, 70, 100, 1000, 10000000];\n\nvar trace1 = {\n x: dates,\n y: y_values,\n mode: 'lines+markers',\n type: 'scatter'\n};\n\nvar layout = {\n yaxis: {\n type: 'log',\n },\n annotations: [\n {\n x: '2024-01-05',\n y: Math.log10(1000),\n text: 'Log axis annotation',\n showarrow: true,\n xanchor: 'right',\n }\n ]\n};\n\nvar data = [trace1];\n\nPlotly.newPlot('myDiv', data, layout);"}">
var trace1 = {
  x: [0, 1, 2, 3, 4, 5, 6, 7, 8],
  y: [0, 1, 3, 2, 4, 3, 4, 6, 5],
  type: 'scatter'
};
var trace2 = {
  x: [0, 1, 2, 3, 4, 5, 6, 7, 8],
  y: [0, 4, 5, 1, 2, 2, 3, 4, 2],
  type: 'scatter'
};
var data = [trace1, trace2];
var layout = {
  showlegend: false,
  annotations: [
    {
      x: 2,
      y: 5,
      xref: 'x',
      yref: 'y',
      text: 'Annotation Text',
      showarrow: true,
      arrowhead: 7,
      ax: 0,
      ay: -40
    },
    {
      x: 4,
      y: 4,
      xref: 'x',
      yref: 'y',
      text: 'Annotation Text 2',
      showarrow: true,
      arrowhead: 7,
      ax: 0,
      ay: -40
    }
  ]
};
Plotly.newPlot('myDiv', data, layout);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var trace1 = {\n x: [0, 1, 2, 3, 4, 5, 6, 7, 8],\n y: [0, 1, 3, 2, 4, 3, 4, 6, 5],\n type: 'scatter'\n};\nvar trace2 = {\n x: [0, 1, 2, 3, 4, 5, 6, 7, 8],\n y: [0, 4, 5, 1, 2, 2, 3, 4, 2],\n type: 'scatter'\n};\nvar data = [trace1, trace2];\nvar layout = {\n showlegend: false,\n annotations: [\n {\n x: 2,\n y: 5,\n xref: 'x',\n yref: 'y',\n text: 'Annotation Text',\n showarrow: true,\n arrowhead: 7,\n ax: 0,\n ay: -40\n },\n {\n x: 4,\n y: 4,\n xref: 'x',\n yref: 'y',\n text: 'Annotation Text 2',\n showarrow: true,\n arrowhead: 7,\n ax: 0,\n ay: -40\n }\n ]\n};\nPlotly.newPlot('myDiv', data, layout);\n"}">
var trace0 = {
  x: [1, 2, 3],
  y: [4, 5, 6],
  type: 'scatter'
};

var trace1 = {
  x: [20, 30, 40],
  y: [50, 60, 70],
  xaxis: 'x2',
  yaxis: 'y2',
  type: 'scatter'
};

var data = [trace0, trace1];

var layout = {
  title: {
    text: 'Subplot Annotations'
  },
  xaxis: {domain: [0, 0.45]},
  yaxis2: {anchor: 'x2'},
  xaxis2: {domain: [0.55, 1]},
  annotations: [
    {
      x: 2,
      y: 5,
      xref: 'x',
      yref: 'y',
      text: 'Annotation A',
      showarrow: true,
      arrowhead: 3,
      ax: -30,
      ay: -40
    },
    {
      x: 30,
      y: 60,
      xref: 'x2',
      yref: 'y2',
      text: 'Annotation B',
      showarrow: true,
      arrowhead: 2,
      ax: -25,
      ay: -40
    }
  ]
};

Plotly.newPlot('myDiv', data, layout);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var trace0 = {\n x: [1, 2, 3],\n y: [4, 5, 6],\n type: 'scatter'\n};\n\nvar trace1 = {\n x: [20, 30, 40],\n y: [50, 60, 70],\n xaxis: 'x2',\n yaxis: 'y2',\n type: 'scatter'\n};\n\nvar data = [trace0, trace1];\n\nvar layout = {\n title: {\n text: 'Subplot Annotations'\n },\n xaxis: {domain: [0, 0.45]},\n yaxis2: {anchor: 'x2'},\n xaxis2: {domain: [0.55, 1]},\n annotations: [\n {\n x: 2,\n y: 5,\n xref: 'x',\n yref: 'y',\n text: 'Annotation A',\n showarrow: true,\n arrowhead: 3,\n ax: -30,\n ay: -40\n },\n {\n x: 30,\n y: 60,\n xref: 'x2',\n yref: 'y2',\n text: 'Annotation B',\n showarrow: true,\n arrowhead: 2,\n ax: -25,\n ay: -40\n }\n ]\n};\n\nPlotly.newPlot('myDiv', data, layout);\n"}">
var data = [{
    type: "scatter3d",
    x: ["2017-01-01", "2017-02-10", "2017-03-20"],
    y: ["A", "B", "C"],
    z: [1, 1e3, 1e5]
 }]

var layout = {
    scene: {
      camera: {
        eye: {x: 2.1, y: 0.1, z: 0.9}
      },
      xaxis: {
        title: {
            text: ""
        }
      },
      yaxis: {
          title: {
              text: ""
          }
      },
      zaxis: {
          type: "log",
          title: {
              text: ""
          }
      },
      annotations: [{
        showarrow: false,
        x: "2017-01-01",
        y: "A",
        z: 0,
        text: "Point 1",
        font: {
          color: "black",
          size: 12
        },
        xanchor: "left",
        xshift: 10,
        opacity: 0.7
      }, {
        x: "2017-02-10",
        y: "B",
        z: 4,
        text: "Point 2",
        textangle: 0,
        ax: 0,
        ay: -75,
        font: {
          color: "black",
          size: 12
        },
        arrowcolor: "black",
        arrowsize: 3,
        arrowwidth: 1,
        arrowhead: 1
      }, {
        x: "2017-03-20",
        y: "C",
        z: 5,
        ax: 50,
        ay: 0,
        text: "Point 3",
        arrowhead: 1,
        xanchor: "left",
        yanchor: "bottom"
      }]
}
}

Plotly.newPlot('myDiv', data, layout);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var data = [{\n type: \"scatter3d\",\n x: [\"2017-01-01\", \"2017-02-10\", \"2017-03-20\"],\n y: [\"A\", \"B\", \"C\"],\n z: [1, 1e3, 1e5]\n }]\n\nvar layout = {\n scene: {\n camera: {\n eye: {x: 2.1, y: 0.1, z: 0.9}\n },\n xaxis: {\n title: {\n text: \"\"\n }\n },\n yaxis: {\n title: {\n text: \"\"\n }\n },\n zaxis: {\n type: \"log\",\n title: {\n text: \"\"\n }\n },\n annotations: [{\n showarrow: false,\n x: \"2017-01-01\",\n y: \"A\",\n z: 0,\n text: \"Point 1\",\n font: {\n color: \"black\",\n size: 12\n },\n xanchor: \"left\",\n xshift: 10,\n opacity: 0.7\n }, {\n x: \"2017-02-10\",\n y: \"B\",\n z: 4,\n text: \"Point 2\",\n textangle: 0,\n ax: 0,\n ay: -75,\n font: {\n color: \"black\",\n size: 12\n },\n arrowcolor: \"black\",\n arrowsize: 3,\n arrowwidth: 1,\n arrowhead: 1\n }, {\n x: \"2017-03-20\",\n y: \"C\",\n z: 5,\n ax: 50,\n ay: 0,\n text: \"Point 3\",\n arrowhead: 1,\n xanchor: \"left\",\n yanchor: \"bottom\"\n }]\n}\n}\n\nPlotly.newPlot('myDiv', data, layout);\n"}">
var trace1 = {
  x: [0, 1, 2],
  y: [1, 1, 1],
  mode: 'lines+markers+text',
  name: 'Lines, Markers and Text',
  text: ['Text A', 'Text B', 'Text C'],
  textposition: 'top right',
  textfont: {
    family: 'sans serif',
    size: 18,
    color: '#1f77b4'
  },
  type: 'scatter'
};
var trace2 = {
  x: [0, 1, 2],
  y: [2, 2, 2],
  mode: 'lines+markers+text',
  name: 'Lines and Text',
  text: ['Text G', 'Text H', 'Text I'],
  textposition: 'bottom',
  textfont: {
    family: 'sans serif',
    size: 18,
    color: '#ff7f0e'
  },
  type: 'scatter'
};
var data = [trace1, trace2];
var layout = {showlegend: false};
Plotly.newPlot('myDiv', data, layout);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var trace1 = {\n x: [0, 1, 2],\n y: [1, 1, 1],\n mode: 'lines+markers+text',\n name: 'Lines, Markers and Text',\n text: ['Text A', 'Text B', 'Text C'],\n textposition: 'top right',\n textfont: {\n family: 'sans serif',\n size: 18,\n color: '#1f77b4'\n },\n type: 'scatter'\n};\nvar trace2 = {\n x: [0, 1, 2],\n y: [2, 2, 2],\n mode: 'lines+markers+text',\n name: 'Lines and Text',\n text: ['Text G', 'Text H', 'Text I'],\n textposition: 'bottom',\n textfont: {\n family: 'sans serif',\n size: 18,\n color: '#ff7f0e'\n },\n type: 'scatter'\n};\nvar data = [trace1, trace2];\nvar layout = {showlegend: false};\nPlotly.newPlot('myDiv', data, layout);\n"}">
var trace1 = {
  x: [0, 1, 2, 3, 4, 5, 6, 7, 8],
  y: [0, 1, 3, 2, 4, 3, 4, 6, 5],
  type: 'scatter'
};
var trace2 = {
  x: [0, 1, 2, 3, 4, 5, 6, 7, 8],
  y: [0, 4, 5, 1, 2, 2, 3, 4, 2],
  type: 'scatter'
};
var data = [trace1, trace2];
var layout = {
  showlegend: false,
  annotations: [
    {
      x: 2,
      y: 5,
      xref: 'x',
      yref: 'y',
      text: 'max=5',
      showarrow: true,
      font: {
        family: 'Courier New, monospace',
        size: 16,
        color: '#ffffff'
      },
      align: 'center',
      arrowhead: 2,
      arrowsize: 1,
      arrowwidth: 2,
      arrowcolor: '#636363',
      ax: 20,
      ay: -30,
      bordercolor: '#c7c7c7',
      borderwidth: 2,
      borderpad: 4,
      bgcolor: '#ff7f0e',
      opacity: 0.8
    }
  ]
};
Plotly.newPlot('myDiv', data, layout);
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var trace1 = {\n x: [0, 1, 2, 3, 4, 5, 6, 7, 8],\n y: [0, 1, 3, 2, 4, 3, 4, 6, 5],\n type: 'scatter'\n};\nvar trace2 = {\n x: [0, 1, 2, 3, 4, 5, 6, 7, 8],\n y: [0, 4, 5, 1, 2, 2, 3, 4, 2],\n type: 'scatter'\n};\nvar data = [trace1, trace2];\nvar layout = {\n showlegend: false,\n annotations: [\n {\n x: 2,\n y: 5,\n xref: 'x',\n yref: 'y',\n text: 'max=5',\n showarrow: true,\n font: {\n family: 'Courier New, monospace',\n size: 16,\n color: '#ffffff'\n },\n align: 'center',\n arrowhead: 2,\n arrowsize: 1,\n arrowwidth: 2,\n arrowcolor: '#636363',\n ax: 20,\n ay: -30,\n bordercolor: '#c7c7c7',\n borderwidth: 2,\n borderpad: 4,\n bgcolor: '#ff7f0e',\n opacity: 0.8\n }\n ]\n};\nPlotly.newPlot('myDiv', data, layout);\n"}">
var myPlot = document.getElementById('myDiv'),
   N = 12,
    x = d3.range(N).map( d3.random.normal(3) ),
    y1 = d3.range(N).map( d3.random.normal(4) ),
    y2 = d3.range(N).map( d3.random.normal(4) ),
    y3 = d3.range(N).map( d3.random.normal(4) ),
    months = ['Jan', 'Feb', 'Mar',
          'Apr', 'May', 'June',
          'July', 'Aug', 'Sept',
          'Oct', 'Nov', 'Dec'],
    data = [{ x:x, y:y1,
             type:'scatter', mode:'markers',
         name:'2014', text: months,
             marker:{color:'rgba(200, 50, 100, .7)',
                      size:16}
             },
            { x:x, y:y2,
             type:'scatter', mode:'markers',
         name:'2015', text:months,
             marker:{color:'rgba(120, 20, 130, .7)',
                     size:16}
             },
            { x:x, y:y3,
             type:'scatter', mode:'markers',
         name: '2016', text:months,
             marker:{color:'rgba(10, 180, 180, .8)',
                     size:16}}];
    layout = {
        hovermode:'closest',
        title: {text: '<b>Formatting Annotations</b> <br> click on a point to plot an annotation'},
        xaxis: {
          zeroline: false,
          title: {
              text: 'Value A'
          }
        },
        yaxis: {
            zeroline: false,
            title: {
                text: 'Value B'
            }
        }
     };

Plotly.newPlot('myDiv', data, layout);

myPlot.on('plotly_click',
    function(data){
      var point = data.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>Series Identification</i>' + <br>
                  '<b>Year</b>       '+(point.data.name) + '<br>' +
                  '<i>Point Identification</i><br>' +
                  '<b>Month</b>      '+ (months[point.pointNumber]) +
                  '<br><i>Point Values</i><br>' +
                  '<b>A</b>     '+(point.x).toPrecision(4) +
                  '<br><b>B</b>     '+(point.y).toPrecision(4)

        },
        divid = document.getElementById('myDiv'),
        newIndex = (divid.layout.annotations || []).length;
    console.log(point.pointNumber)
     // delete instead if clicked twice
    if(newIndex) {
       var foundCopy = false;
       divid.layout.annotations.forEach(function(ann, sameIndex) {
         if(ann.text === newAnnotation.text ) {
           Plotly.relayout('myDiv', 'annotations[' + sameIndex + ']', 'remove');
           foundCopy = true;
         }
       });
       if(foundCopy) return;
     }
     Plotly.relayout('myDiv', 'annotations[' + newIndex + ']', newAnnotation);
  })
  .on('plotly_clickannotation', function(event, data) {
    Plotly.relayout('myDiv', 'annotations[' + data.index + ']', 'remove');
  });
var n = 250;
var t = 12;
var x = [];
var y = [];
var z = [];
var text = [];
var arr = ["A","T","G", "C"];

for (var j = 0; j < t; j++){
  ztemp = [];
  for (var i = 0; i < n; i++) {
    x.push(i);
    y.push(j);
    ztemp.push(Math.floor(Math.random() * 10));
    text.push(arr[Math.floor(Math.random() * 4)])
  }
  z.push(ztemp)
}

var steps = [];
for (var e = 0; e < n-30; e++){
  steps.push({
      label: e,
      value: e,
      method: 'relayout',
      args: ['xaxis', {range: [-0.5 + e, 30.5 + e]}]
    })
}

data1 = {
  x: x,
  y: y,
  mode: "text",
  text: text,
  type: "scattergl",
  textfont: {
    size: 20
    }
  }
       
data2 = {
  z: z,
  type: "heatmap"
  }

sliders = [{
      active: 0,
      steps: steps
    }]

layout = {
  sliders: sliders,
  xaxis: {
    range: [-0.5, 30.5],
    showline: false,
    zeroline: false,
     showgrid: false
  },
  yaxis: {
    showline: false,
    zeroline: false,
     showgrid: false
  }  
  }

data = [data1, data2]
Plotly.newPlot('myDiv', {data:data,
                     layout:layout});
</script>\n</head>\n\n<body>\n\t<div id='myDiv'><!-- Plotly chart will be drawn inside this DIV --></div>\n</body>","js":"var n = 250;\nvar t = 12;\nvar x = [];\nvar y = [];\nvar z = [];\nvar text = [];\nvar arr = [\"A\",\"T\",\"G\", \"C\"];\n\nfor (var j = 0; j < t; j++){\n ztemp = [];\n for (var i = 0; i < n; i++) {\n x.push(i);\n y.push(j);\n ztemp.push(Math.floor(Math.random() * 10));\n text.push(arr[Math.floor(Math.random() * 4)])\n }\n z.push(ztemp)\n}\n\nvar steps = [];\nfor (var e = 0; e < n-30; e++){\n steps.push({\n label: e,\n value: e,\n method: 'relayout',\n args: ['xaxis', {range: [-0.5 + e, 30.5 + e]}]\n })\n}\n\ndata1 = {\n x: x,\n y: y,\n mode: \"text\",\n text: text,\n type: \"scattergl\",\n textfont: {\n size: 20\n }\n }\n \ndata2 = {\n z: z,\n type: \"heatmap\"\n }\n\nsliders = [{\n active: 0,\n steps: steps\n }]\n\nlayout = {\n sliders: sliders,\n xaxis: {\n range: [-0.5, 30.5],\n showline: false,\n zeroline: false,\n showgrid: false\n },\n yaxis: {\n showline: false,\n zeroline: false,\n showgrid: false\n } \n }\n\ndata = [data1, data2]\nPlotly.newPlot('myDiv', {data:data,\n layout:layout});"}">