I am using plotly.js to create charts. Some charts have long text inside legend, so these text make legend unnecessary bigger. I want to give legend fixed width and if a length of text is long, I want it to be wrapped.
I have been trying to do this by manipulating svg element on DOM, but since legend is svg:g
tag, I can not really do much. I also try give textLength
to <text>
, but it does wrap text but it does not make a new line.
Is there a way to give legend fixed width?
I am using plotly.js to create charts. Some charts have long text inside legend, so these text make legend unnecessary bigger. I want to give legend fixed width and if a length of text is long, I want it to be wrapped.
I have been trying to do this by manipulating svg element on DOM, but since legend is svg:g
tag, I can not really do much. I also try give textLength
to <text>
, but it does wrap text but it does not make a new line.
Is there a way to give legend fixed width?
Share Improve this question asked Feb 2, 2017 at 11:56 kaykay 1,4294 gold badges16 silver badges27 bronze badges 1- did you figure out any better solutions now. – Punita Ojha Commented Apr 22, 2021 at 20:19
3 Answers
Reset to default 2Perhaps just adding </br>
to the legend text would be an easy solution to get a fixed width?
You could use any text wrapping trick in Javascript to do so, e.g.
for (i = 0; i < data.length; i += 1) {
data[i].name = data[i].name.replace(/([\w\s,]{13,}?)\s?\b/g, "$1</br>");
}
var numbers = [];
var total = 10000;
var i = 0;
var data = [];
for (i = 0; i < total; i++) {
numbers[i] = ((Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random()) - 3) / 3;
}
data.push({
x: numbers,
name: "that's a histogram with lots of points, it therefore needs lots of text as well",
type: 'histogram',
marker: {color: 'blue'}
});
numbers = [];
for (var i = 0; i < total; i++) {
numbers[i] = 0.25 + ((Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random()) - 3) / 3;
}
data.push({
x: numbers,
name: "that's yet another histogram with lots of points, it therefore needs lots of text as well, like for example that it was shifted by 0.25",
type: 'histogram',
marker: {color: 'red'}
});
for (i = 0; i < data.length; i += 1) {
data[i].name = data[i].name.replace(/([\w\s,]{13,}?)\s?\b/g, "$1<br>");
}
Plotly.newPlot('myDiv', data, {showlegend: true});
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="myDiv"></div>
Maximilian's answer almost works with the current version of Plotly.js. There doesn't seem to be a property for setting the width of the legend, but you can rig it by inserting breaks (</br>
) into the legend text manually. For some reason Plotly seems to mishandle the first break in the text, however; to get around this, you can add a "ghost" break at the beginning of the text. For instance:
// Rudimentary function to break a string on spaces
// attempting to get no more than `maxChars` characters in a line
const breakString = (str, maxChars) => {
if (str.length > maxChars && str.includes(' ')) {
let index = str.lastIndexOf(' ', maxChars);
if (index === -1) index = str.indexOf(' ', maxChars + 1);
return str.substr(0, index) + '</br>' + breakString(str.substr(index + 1), maxChars);
} else {
return str;
}
}
const original_text = "Respondents who think Tenet is Christopher Nolan's most interesting movie";
const final_text = '</br>' + breakString(original_text, 20);
The color symbols next to each legend entry by default are aligned to the center of the corresponding text; with multiline legend text, you'll probably want to change the symbols to be aligned to the top of the text. To do that, add this to your layout
:
legend: {
valign: 'top',
}
This works for me using Plotly with javascript.
title: 'first part' + '<br>' + 'Second part'
eg
yaxis2: {
domain: [0.7, 1],
title: 'Sea Surface' + '<br>' + 'Temperature',
showgrid: true,
showline: true,
titlefont: {color: 'blue'},
tickfont: {color: 'blue'},
side: 'right',
anchor: 'free',
position: 0.91
},