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
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
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
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
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
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
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
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
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
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