Wrapping and text size in responsive design
Mavromatika opened this issue · 5 comments
Hi, I'd like to thank you first of all for this wonderful plugin. I'm using it a lot now and I think it was very well designed.
I'm currently struggling however with dynamic text wrapping and size in notes. I'm trying to make a chart responsive to the size of it parent. For this I resize and re-position a lot of elements on the window resize event. For my annotations to remain visible I need to change both the wrap length and the font size of the notes.
But the interaction between the wrapping function and the font-size is obscure to me. It seems like it's computing the line height based on the font-size it can find before displaying the annotations (which makes sense). But given that d3.js only allows us to change inline style properties of existing elements, one needs to draw the annotations once to be able to set their font size, before redrawing them with the new wrap length and position.
At least this what I understand at the moment (after several hours trying to figure out a solution, so bear with me if what I wrote doesn't make sense).
Would it be possible to define the font-size in the annotation data instead (in the note, in addition to wrap length) ? This way all dynamic changes are to be made in the annotations' data, and when the annotations are re-draw the note is properly displayed.
Thanks for the feedback. It is computing the line height based on the font-size. I hadn't thought of putting the font-size in the annotation data.
I'll try to put together a small example to test out this case, let me know if you have anything like this put together already that I could use for testing. I'll let you know what conclusions I come to.
Thanks!
I believe this is fixed in the latest version 1.13.0 please let me know if you have any issues with the rendering positioning after upgrading.
Here's a code snippet example:
d3.select("svg")
.attr('width', window.innerWidth - 16)
const annotations = [
{
note: {
label: "A different annotation type wtih long wrap",
title: "Another title with a long wrap for testing"
},
subject: { radius: 50 },
x: 120,
y: 200,
dy: 50,
dx: 0
}
]
const fontSize = d3.scaleLinear().range([10, 20]).clamp(true)
const wrap = d3.scaleLinear().range([40, 160]).clamp(true)
let ratio = window.innerWidth/1200
const makeAnnotations = d3.annotation()
.textWrap(wrap(ratio))
.type(d3.annotationCalloutCircle)
.notePadding(10)
.annotations(annotations)
//helper function to only create annotations after fonts are loaded
//if you have external fonts, this will help with the placement
document.fonts.ready.then(function(){
d3.select("svg")
.append("g")
.attr("class", "annotation-group")
.style('font-size', fontSize(ratio))
.call(makeAnnotations)
})
window.onresize = function(d) {
ratio = window.innerWidth/1200
d3.select("svg")
.attr('width', window.innerWidth - 16)
makeAnnotations.textWrap(wrap(ratio))
d3.select('g.annotation-group')
.style('font-size', fontSize(ratio))
.call(makeAnnotations)
}
Thanks,
Susie
Thanks Susie, I'll give it a try will provide feedback here.
@susielu thank you very much for your example. It helped me a lot
Hi Susie, I'm stuck too and just adjusted my code to work like you suggest, but to no avail. I can't get my test label to wrap, using wrapSplitter, textWrap, etc.
https://observablehq.com/@pablo-mayrgundter/map-regional-with-click-callback
I'd appreciate any help! Loving the annotation library :)