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. Sign up for early access 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);
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
  }]
  
})
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);
0123456780123456
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);
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);
0123456780123456
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);
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);
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);
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);
0123456780123456
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');
  });
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});
0510152025300246810
0071421283542495663707784919810511211912613314014715416116817518218919620321021702468