I am trying to add zoom to UK map with d3fc-label-layout. But when I zoom in the labels are shifted. As I understand I have to recalculate the positions with d3fc-label-layout every time the zoom is called, but not sure how to do this Here is a fiddle https://jsfiddle.net/benderlio/cyvqase5/11/
var zoom = d3.zoom()
.scaleExtent([1, 28])
.on('zoom', function () {
svg.selectAll('path')
.attr('transform', d3.event.transform);
svg.selectAll("circle")
.attr('transform', d3.event.transform);
svg.selectAll("text")
.attr('transform', d3.event.transform);
});
svg.call(zoom);
I was able to sync the zoom of the points and text by applying a transform on the labels themselves instead of the circles and text items.
I recalculate the position from the projection and adjust according to the zoom transformation:
const t=d3.event.transform;
svg.selectAll('path')
.attr('transform', t);
svg.selectAll(".label")
.attr('transform', d => {
const p=projection(d.geometry.coordinates)
return `translate(${ p[0] * t.k + t.x }, ${ p[1] * t.k + t.y }) scale(${ t.k })`
})
you can see it working here: https://jsfiddle.net/p94xhorv/8/
I changed the code to recalculate the layout as the user zooms to keep cities from becoming "hidden" as per the OP's comment to my original answer.
.on('zoom', function () {
const t=d3.event.transform;
svg.selectAll('path')
.attr('transform', t);
labels.position(function (d) {
const p=projection(d.geometry.coordinates)
return [p[0]*t.k+t.x, p[1]*t.k+t.y]
});
svg.datum(places.features)
.call(labels);
});
and here's the updated jsfiddle https://jsfiddle.net/rpv9743n/