To understand why there is an additional factor of 2π applied to the scales when it comes to using the d3.geo.tile plugin, it is important to know the difference between the projection used by d3.geoMercator()
and the one used when plotting the raster tiles.
D3
D3 implements the standard Mercator projection using the formulae:


This projection is using the unit circle's radius of R = 1 centering on the Greenwich meridian. Up to this point there is no scaling nor any translation applied. The projection will produce output values from the following intervals:


In D3 v4 this is implemented as
export function mercatorRaw(lambda, phi) {
return [lambda, log(tan((halfPi + phi) / 2))];
}
D3 v3 used a slightly different notation which more closely resembles the above mentioned formulae while, of course, being equivalent to the newer implementation:
function d3_geo_mercator(λ, φ) {
return [λ, Math.log(Math.tan(π / 4 + φ / 2))];
}
The intervals' values are often obscured by the fact that d3.geo.mercator()
uses default values for translation and scaling. You have to explicitely set those to .translate([0,0]).scale(1)
to get the above mentioned intervals.
Tiles
Tiles on the other hand use a slightly modified version of the Mercator projection known as Web Mercator. The relevant formulae are


This projection, at its core, uses the same calculations as the standard Mercator projection. This can easily be seen from the terms colored in black on the right sides of the above equations, which are exactly the same as those used by the Mercator projection. Just the output intervals are adjusted to better suit the needs of screen display by applying some scaling and translation.
First of all, the projection is cut off for latitudes both north and south exceeding

Thereby projecting the entire map onto a square. Afterwards, there are three adjustments (matched by color in the above equations):
- Move the origin to the upper left corner (0, 0) — adjustment by π in blue.
- Normalize the intervals to [0, 1] — divide by 2π in green
- Scale up to fit an area of 256 × 256 — multiply by 256 in red.
This will yield output values from the intervals

It's this difference in scales of the projections involved, which is the reason why you need to multiply / divide by 2π. If you want to use both d3.geo.mercator()
as well as the tiles in the same map, you need to modify the scales to match each other.
Imposing the same restrictions for latitude on the standard Mercator projection as is the case for the Web Mercator projection you end up with the following intervals:
Standard Mercator Projection
Projects to the intervals

having length = 2π.
Web Mercator Projection
Projects to the intervals

having length = 256.
This is corrected when setting the projection's scale like
var projection = d3.geoMercator()
.scale((1 << 12) / 2 / Math.PI );
Using simple exponentiation math the scaling factor can be rewritten as
(1 << 4) * (1 << 8) / 2 / Math.PI
and further
(1 << 4) * 256 / ( 2 * Math.PI )
The first term (1 << 4)
equals 24 which is the actual zoom factor to use: 16. This will get tiles of zoom level 4. The next term

is the correction factor to adjust the scales which includes the 2π your question was all about.