This is the code for Chapter 11, Figure 5 from D3.js in Action showing mixed mode rendering where the country polygons are rendered in canvas and the triangles are rendered in SVG.
<html>
<head>
<title>D3 in Action Chapter 11 - Example 3</title>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
</head>
<style>
body, html {
margin: 0;
}
canvas {
position: absolute;
width: 500px;
height: 500px;
}
svg {
position: absolute;
width:500px;
height:500px;
}
path.country {
fill: gray;
stroke-width: 1;
stroke: black;
opacity: .5;
}
path.sample {
stroke: black;
stroke-width: 1px;
fill: red;
fill-opacity: .5;
}
line.link {
stroke-width: 1px;
stroke: black;
stroke-opacity: .5;
}
circle.node {
fill: red;
stroke: white;
stroke-width: 1px;
}
circle.xy {
fill: pink;
stroke: black;
stroke-width: 1px;
}
</style>
<body>
<canvas height="500" width="500"></canvas>
<div id="viz">
<svg></svg>
</div>
</body>
<footer>
<script>
sampleData = d3.range(2000).map(function(d) {
var datapoint = {};
datapoint.id = "Sample Feature " + d;
datapoint.type = "Feature";
datapoint.properties = {};
datapoint.geometry = {};
datapoint.geometry.type = "Polygon";
datapoint.geometry.coordinates = randomCoords();
return datapoint;
})
d3.json("world.geojson", function(data) {createMap(data)});
function createMap(countries) {
projection = d3.geo.mercator().scale(100).translate([250,250]);
geoPath = d3.geo.path().projection(projection);
canvasPath = d3.geo.path().projection(projection);
mapZoom = d3.behavior.zoom().translate(projection.translate()).scale(projection.scale()).on("zoom", zoomed);
d3.select("svg").call(mapZoom);
var g = d3.select("svg")
g.selectAll("path.sample").data(sampleData)
.enter()
.append("path")
.attr("class", "sample")
.style("stroke", "black")
.style("stroke-width", "1px")
.style("fill", "red")
.style("fill-opacity", .5)
.on("mouseover", function() {d3.select(this).style("fill", "pink")});
zoomed();
function zoomed() {
projection.translate(mapZoom.translate()).scale(mapZoom.scale());
var context = d3.select("canvas").node().getContext("2d");
context.clearRect(0,0,500,500);
context.strokeStyle = "black";
context.fillStyle = "gray";
context.lineWidth = "1px";
for (var x in countries.features) {
context.beginPath();
canvasPath.context(context)(countries.features[x]);
context.stroke()
context.fill();
}
d3.selectAll("path.sample").attr("d", geoPath);
}
}
function randomCoords() {
var randX = (Math.random() * 350) - 175;
var randY = (Math.random() * 170) - 85;
return [[[randX - 5,randY],[randX,randY - 5],[randX - 10,randY - 5],[randX - 5,randY]]];
}
</script>
</footer>
</html>