I have a world map in svg format, and am using a viewbox to focus on Africa. I have two buttons for zooming in and zooming out:
<rect class="button" x="75" y="170" onclick="zoom(0.8)" style="width:25px; height:20px; fill:khaki"/>
<rect class="button" x="100" y="170" onclick="zoom(1.25)" style="width:25px; height:20px; fill:khaki"/>
In an external .js file, I have code that pans and zooms, which I found in Peter Collingridge's online tutorial:
var transformMatrix = [1, 0, 0, 1, 0, 0];
var svg = document.getElementById('map-svg');
var viewbox = svg.getAttributeNS(null, "viewBox").split(" ");
var centerX = parseFloat(viewbox[2]) / 2;
var centerY = parseFloat(viewbox[3]) / 2;
var matrixGroup = svg.getElementById("matrix-group");
function pan(dx, dy) {
transformMatrix[4] += dx;
transformMatrix[5] += dy;
var newMatrix = "matrix(" + transformMatrix.join(' ') + ")";
matrixGroup.setAttributeNS(null, "transform", newMatrix);
}
function zoom(scale) {
for (var i = 0; i < transformMatrix.length; i++) {
transformMatrix[i] *= scale;
}
transformMatrix[4] += (1 - scale) * centerX;
transformMatrix[5] += (1 - scale) * centerY;
var newMatrix = "matrix(" + transformMatrix.join(' ') + ")";
matrixGroup.setAttributeNS(null, "transform", newMatrix);
}
Everything works just as I want it to, except for one thing. When I zoom in, Africa "jumps" to the right, and when I zoom out, it "jumps" to the left. How can I zoom in and out, with Africa staying in the center of the viewbox?
I think I answered my own question. In lines 4 and 5, centerX and centerY are defined:
var centerX = parseFloat(viewbox[2]) / 2;
var centerY = parseFloat(viewbox[3]) / 2;
Then in lines 20 and 21, centerX and centerY are used:
transformMatrix[4] += (1 - scale) * centerX;
transformMatrix[5] += (1 - scale) * centerY;
I thought, "What if I multiply centerX and centerY by 2, to offset the division by 2 in lines 4 and 5?" That centered it on the Y axis, but not the X axis. So, I kept changing numbers until I got:
transformMatrix[4] += (1 - scale) * (centerX * 4);
transformMatrix[5] += (1 - scale) * (centerY * 2);
Now it zooms just as I'd hoped, keeping the continent of Africa centered in the viewbox.