I would like to create a simple map using Canvas. I have a TopoJson file with the geo object that needs to be displayed. I use D3js to work with the geo-coordinates. Behind the object, I would like to put the Mapbox tiles. And I have actually done this. However, I also need to be able to move the map with a mouse to be able to see other objects around. The problem is that the Mapbox tiles do not load dynamically. I know that I need to handle the 'zoom' event but I can't figure out what exactly should I do...
const width = 960;
const height = 500;
d3.json('test.json').then((topojsonData) => {
var feature = topojson.feature(topojsonData, topojsonData.objects.foo);
var projection = d3.geoMercator().fitSize([width, height], feature);
var path = d3.geoPath(projection);
var svgCanvas = d3.create("svg").attr("viewBox", [0, 0, width, height]);
var group = svgCanvas.append("g");
var tile = d3.tile().size([width, height]).scale(projection.scale() * 2 * Math.PI).translate(projection([0, 0])).tileSize(512);
var url = (x, y, z) => `https://api.mapbox.com/styles/v1/mapbox/light-v10/tiles/${z}/${x}/${y}${devicePixelRatio > 1 ? "@2x" : ""}?access_token=MAPBOX_KEY`;
tile().map(([x, y, z], i, {translate: [tx, ty], scale: k}) =>
{
group.append("image")
.attr("href", url(x, y, z))
.attr("x", Math.round((x + tx) * k))
.attr("y", Math.round((y + ty) * k))
.attr("width", k)
.attr("height", k);
});
group.append("path")
.attr("fill", "red")
.attr("stroke", "red")
.attr("fill-opacity", 0.03)
.attr("stroke-opacity", 0.5)
.attr("d", path(feature));
function zoomed(event) {
const {transform} = event;
group.attr("transform", transform);
group.attr("stroke-width", 1 / transform.k);
}
const zoom = d3.zoom().scaleExtent([1, 1]).on("zoom", zoomed);
svgCanvas.call(zoom);
document.getElementById('map').appendChild(svgCanvas.node());
});
The interactive version is available here: https://observablehq.com/d/22ac89fa043e05c3 Are there any specialists around who can help me please?