Text and Annotations in JavaScript

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


New to Plotly?

Plotly is a free and open-source graphing library for JavaScript. We recommend you read our Getting Started guide for the latest installation or upgrade instructions, then move on to our Plotly Fundamentals tutorials or dive straight in to some Basic Charts tutorials.

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);
Click to copy
Text AText BText CText DText EText FText GText HText I00.511.5211.522.53
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
  }]
  
})
Click to copy
11.522.5311.21.41.61.82
X axis labelY axis label
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);
Click to copy
024680123456
Annotation Text

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);
Click to copy
Jan 12024Jan 2Jan 3Jan 4Jan 5Jan 6110010k1M
Log axis annotation
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);
Click to copy
024680123456
Annotation TextAnnotation Text 2
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);
Click to copy
11.522.5344.555.5620253035405055606570
trace 0trace 1Subplot AnnotationsAnnotation AAnnotation B
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);
Click to copy
Point 1Point 2Point 3
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);
Click to copy
Text AText BText CText GText HText I00.511.5211.21.41.61.82
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);
Click to copy
024680123456
max=5
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');
  });
Click to copy
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});
Click to copy
0510152025300246810
001428425670849811212614015416818219621002468