function canvasFunction(extent, resolution, pixelRatio, size, projection) {
var canvasWidth = size[0];
var canvasHeight = size[1];
var canvas = d3.select(document.createElement('canvas'));
canvas.attr('width', canvasWidth).attr('height', canvasHeight);
var context = canvas.node().getContext('2d');
var d3Projection = d3.geoMercator().scale(1).translate([0, 0]);
var d3Path = d3.geoPath().projection(d3Projection);
var pixelBounds = d3Path.bounds(features);
var pixelBoundsWidth = pixelBounds[1][0] - pixelBounds[0][0];
var pixelBoundsHeight = pixelBounds[1][1] - pixelBounds[0][1];
var geoBounds = d3.geoBounds(features);
var geoBoundsLeftBottom = ol.proj.fromLonLat(geoBounds[0], projection);
var geoBoundsRightTop = ol.proj.fromLonLat(geoBounds[1], projection);
var geoBoundsWidth = geoBoundsRightTop[0] - geoBoundsLeftBottom[0];
if (geoBoundsWidth < 0) {
geoBoundsWidth += ol.extent.getWidth(projection.getExtent());
}
var geoBoundsHeight = geoBoundsRightTop[1] - geoBoundsLeftBottom[1];
var widthResolution = geoBoundsWidth / pixelBoundsWidth;
var heightResolution = geoBoundsHeight / pixelBoundsHeight;
var r = Math.max(widthResolution, heightResolution);
var scale = r / (resolution / pixelRatio);
let f = d3.format("\ ,d");
info.innerHTML = "Left bottom: " + geoBoundsLeftBottom.map(f) +
"<br>Right top: " + geoBoundsRightTop.map(f) +
"<br>widthResolution, heightResolution: " + widthResolution + ", " + heightResolution;
var center = ol.proj.toLonLat(ol.extent.getCenter(extent), projection);
d3Projection.scale(scale).center(center)
.translate([canvasWidth / 2, canvasHeight / 2]);
d3Path = d3Path.projection(d3Projection).context(context);
context.beginPath();
d3Path(topojson.mesh(topo, topo.objects.counties, (a, b) => a !== b && (a.id / 1000 | 0) === (b.id / 1000 | 0)));
context.lineWidth = 1;
context.strokeStyle = "#aaa";
context.stroke();
context.beginPath();
d3Path(topojson.mesh(topo, topo.objects.states, (a, b) => a !== b));
context.strokeStyle = "#555";
context.stroke();
context.beginPath();
d3Path(topojson.feature(topo, topo.objects.nation));
context.strokeStyle = "#000";
context.stroke();
return canvas.node();
}