Skip to content

Instantly share code, notes, and snippets.

@john-guerra
Last active July 26, 2018 22:14
Show Gist options
  • Save john-guerra/e80f02e59681ace122626c39407526a0 to your computer and use it in GitHub Desktop.
Save john-guerra/e80f02e59681ace122626c39407526a0 to your computer and use it in GitHub Desktop.
SVG vs Canvas D3
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<style>
body { margin:20px;position:fixed;top:0;right:0;bottom:0;left:0; }
#canvasExample, #svgExample {
position:relative;
width:100%;
}
</style>
</head>
<body>
<p>Here is an example of drawing 20000 lines with svg vs canvas</p>
<h2>SVG</h2>
<button id="btnSVG">Draw with svg</button> <p id="svgTime"></p>
<div id="svgExample"></div>
<h2>Canvas</h2>
<button id="btnCanvas">Draw with canvas</button> <p id="canvasTime"></p>
<div id="canvasExample"></div>
<script>
// ******************** Globals ************************
var x = d3.scaleLinear().domain([-1, 1]).range([20, 500]);
var steps = 5
//Discrete diverging scale
var color_threshold = d3.scaleThreshold()
.domain(d3.range(-1 + 2/steps, 1, 2/steps) ) //[-.6, -.2, .2, .6]
.range(d3.schemePuOr[steps]); //=> 5 colors in an array
//Continuous diverging scale
var color_sequential = d3.scaleSequential(d3.interpolatePuOr)
.domain([-1, 1]);
function drawWithCanvas() {
//Cleanup
d3.select("#canvasExample").select("svg").remove();
d3.select("#canvasExample").select("canvas").remove();
// Background canvas for quick drawing of 2k lines
var canvas = d3.select("#canvasExample").append("canvas")
.attr("width", 960)
.attr("height", 100);
var ctx = canvas.node().getContext("2d");
//Translucent svg on top to show the axis
var svg = d3.select("#canvasExample").append("svg")
.attr("width", 960)
.attr("height", 100)
.style("position", "absolute")
.style("top", 0)
.style("left", 0);
// Let's add an axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0, 50)")
.call(d3.axisTop(x));
// Let's draw 20000 lines on canvas for speed
d3.range(-1, 1, 0.0001)
.forEach(function (d) {
ctx.beginPath();
ctx.strokeStyle = color_threshold(d);
ctx.moveTo(x(d), 50);
ctx.lineTo(x(d), 70);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = color_sequential(d);
ctx.moveTo(x(d), 80);
ctx.lineTo(x(d), 100);
ctx.stroke();
});
} // drawWithCanvas
function drawWithSVG() {
d3.select("#svgExample").select("svg").remove();
var svg = d3.select("#svgExample").append("svg")
.attr("width", 960)
.attr("height", 100);
// Let's add an axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0, 50)")
.call(d3.axisTop(x));
var line = d3.line();
var gStep = svg.append("g");
var gSeq = svg.append("g");
// Let's draw 20000 lines with svg
gStep.selectAll("path")
.data(d3.range(-1, 1, 0.0001))
.enter()
.append("path")
.attr("d", function (d) {
return line([[x(d), 50], [x(d), 70]]);
})
.style("stroke", color_threshold);
gSeq.selectAll("path")
.data(d3.range(-1, 1, 0.0001))
.enter()
.append("path")
.attr("d", function (d) {
return line([[x(d), 80], [x(d), 100]]);
})
.style("stroke", color_sequential);
} // drawWithSVG
// Setup buttons
d3.select("#btnCanvas").on("click", function () {
var t0 = performance.now();
drawWithCanvas();
var t1 = performance.now();
d3.select("#canvasTime").text("Drawing on canvas took " + (t1 - t0) + " milliseconds.")
} );
d3.select("#btnSVG").on("click", function () {
var t0 = performance.now();
drawWithSVG();
var t1 = performance.now();
d3.select("#svgTime").text("Drawing on SVG took " + (t1 - t0) + " milliseconds.");
});
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment