Skip to content

Instantly share code, notes, and snippets.

@vectorsize
Forked from mbostock/.block
Last active December 31, 2015 18:22
Show Gist options
  • Save vectorsize/8026287 to your computer and use it in GitHub Desktop.
Save vectorsize/8026287 to your computer and use it in GitHub Desktop.
DOM-to-Canvas using D3

Mouseover to draw circles!

This is a quick proof-of-concept example demonstrating how to create a canvas scenegraph in the DOM using document fragments. The scenegraph in this example consists of a simple container svg element and a number of child circle elements.

The content positions and sizes are calculated offline and the actual DOM tree doesn't even need to be aware of out svg. To render them, we use a timer that iterates over the child elements and draws them to a canvas element.

This is a modification of the original DOM-to-Canvas using D3 proof of conncept.

<!DOCTYPE html>
<html>
<head>
<title>Custom Elements</title>
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js?2.3.2"></script>
<style type="text/css">
body {
margin: 0;
}
</style>
</head>
<body>
<canvas id="container" width="960" height="500"></canvas>
<script type="text/javascript">
var w = 960,
h = 500;
// creare a document fragment to draw "offline"
var sketchFrag = document.createDocumentFragment();
var canvas = document.getElementById('container');
var context = canvas.getContext("2d");
var sketch = d3.select(sketchFrag).append("svg")
.attr("width", w)
.attr("height", h)
.call(custom);
// On each mouse move, create a circle that increases in size and fades away.
d3.select(canvas).on("mousemove", function() {
var circ = sketch.append("circle")
.attr("x", d3.event.offsetX)
.attr("y", d3.event.offsetY)
.attr("radius", 1)
.attr("strokeStyle", "red")
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("radius", 200)
.attr("strokeStyle", "white")
.remove();
});
function custom(selection) {
selection.each(function() {
var root = this;
// canvas.style.position = "absolute";
// canvas.style.top = root.offsetTop + "px";
// canvas.style.left = root.offsetLeft + "px";
// It'd be nice to use DOM Mutation Events here instead.
// However, they appear to arrive irregularly, causing choppy animation.
d3.timer(redraw);
// Clear the canvas and then iterate over child elements.
function redraw() {
canvas.width = root.getAttribute("width");
canvas.height = root.getAttribute("height");
sketch.selectAll('circle')
.each(function(){
var d = d3.select(this);
context.strokeStyle = d.attr("strokeStyle");
context.beginPath();
context.arc(d.attr("x"), d.attr("y"), d.attr("radius"), 0, 2 * Math.PI);
context.stroke();
});
}
});
};
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment