This example demonstrates how to implement an animated tour of a scatterplot using zoom transitions. The tour zooms in on each of the clusters in succession before zooming back out to the overview. To compute the appropriate zoom transform for each cluster, first the bounding box of each cluster is computed in non-transformed coordinates:

```
x0 = x(d3.min(pointset, function(d) { return d[0]; }));
x1 = x(d3.max(pointset, function(d) { return d[0]; }));
y0 = y(d3.max(pointset, function(d) { return d[1]; }));
y1 = y(d3.min(pointset, function(d) { return d[1]; }));
```

Note that the *y₀* and *y₁* are inverted: the browser’s origin is the top-left corner, not the bottom-left. This bounding box is converted into a suitable scale *k* and translate *t _{x}*,

```
k = 0.9 / Math.max((x1 - x0) / width, (y1 - y0) / height);
tx = (width - k * (x0 + x1)) / 2;
ty = (height - k * (y0 + y1)) / 2;
```

This technique is also used in the zoom to bounding box example, which computes a transform using the bounding box of a geographic feature. Here, the values are used to create a zoom transform which is passed to *zoom*.transform to initiate a transition:

```
svg.transition()
.duration(1500)
.call(zoom.transform, d3.zoomIdentity
.translate(tx, ty)
.scale(k));
```

This example uses Canvas for faster rendering of the points, and SVG for convenient rendering of the axes. I expect you could further accelerate Canvas rendering by using image sprites instead of drawing separate arcs for each point, and by culling offscreen points.