Accepted answer

If you can position them to start, you can update them the same way on zoom, just with the new width/height of each item. You initially append each item with these attributes:

.attr("x", (d) => projection([,d.lon])[0] - icon/2)
.attr("y", (d) => projection([d.lon,])[1] - icon/2)
.attr("width", `${icon}px`)
.attr("height", `${icon}px`)

Which offsets the icon from the x,y values returned by the projection by half the icon's width and height - centering it on the projected point. Note: Your x value is set with, d.lon rather than d.lon,, also, your csv has lng, rather than lon as a header, so d.lng should be used).

To keep the icon centered on the point, just update the icon using the new icon width/height (which in your case is located in iconMove) and the new projected point:

.attr("x", (d) => projection([d.lng,])[0] - iconMove/2)
.attr("y", (d) => projection([d.lng,])[1] - iconMove/2)
.attr("width", iconMove)
.attr("height", iconMove);

Here's an updated block (I wasn't able to figure out how to save a new block builder block).

Related Query

More Query from same tag