Skip to content

Instantly share code, notes, and snippets.

@jmacqueen
Last active November 11, 2019 12:11
Show Gist options
  • Save jmacqueen/7366028 to your computer and use it in GitHub Desktop.
Save jmacqueen/7366028 to your computer and use it in GitHub Desktop.
D3.js: Highlighting Data with CSS Animations

CSS animations are typically far more processor efficient than Javascript animations. Far more clever people than I have spent a lot of brainpower optimizing the animations natively in the browser. Whenever possible, I defer to their expertise.

The animation in use is a simple scale transform:

	@keyframes pulsar {
		from {
			fill: red;
		}
		to {
			fill: red;
			transform: scale(1.3,1.3);
			transform-origin: 50% 50%;
		}
	}

Here's an important potential 'gotcha'! Make sure in your normal CSS style for the data points to explicity set the scale to 1. If you don't you will likely end up with data points of various sizes once the warning condition has passed and the pulse class is removed.

If you want to interact with these D3.js gists without downloading them yourself, replace https://gist.github.com with http://bl.ocks.org to go to Mike Bostock's excellent website for running D3.js gists.

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Highlight Pulse SVG Element</title>
<link rel="stylesheet" href="pulse.css">
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<div class="controls">
<label>Highlight Points: <input type="checkbox" id="chkHighlight"></label>
</div>
<script>
var width = 800;
var height = 400;
var numPoints = 100;
var data = []
for (j=0;j<numPoints;j++){
data[j] = {
x: Math.random() * width,
y: Math.random() * height,
class: "normal-circle"
};
}
var drawCircles = function(container) {
console.log("Drawing Circles");
var circles = container.selectAll("circle").data(data);
enterCircles(circles);
updateCircles(circles);
}
var enterCircles = function(selection) {
// console.log("Adding Circles");
selection.enter().append("circle")
.attr("r",0)
.transition()
.attr("cx",function(d){return d.x;})
.attr("cy",function(d){return d.y;})
.attr("r", 5)
.attr("class", function(d){return d.class;});
}
var updateCircles = function(selection) {
// console.log("Updating Circles");
selection
.transition()
.attr("r",5)
.attr("cx",function(d){return d.x;})
.attr("cy",function(d){return d.y;})
.attr("class", function(d){return d.class;});
}
// Attach CSS animation to random data points
d3.select("#chkHighlight").on("change", function(){
// console.log("Check Changed!");
var isChecked = this.checked;
for (j=0;j<numPoints;j++){
if (isChecked && Math.random() > 0.9) {
data[j]["class"] = "pulse";
} else {
data[j].class="normal-circle";
}
}
drawCircles(svg);
})
// Main
var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);
drawCircles(svg);
</script>
</body>
</html>
body {
font-family: Helvetica,sans-serif;
}
.controls {
border-bottom: solid 1px black;
padding: 1em 5%;
}
svg {
border: solid 1px black;
margin: 1em 5%;
}
.normal-circle {
fill: lightblue;
stroke: purple;
-webkit-transform: scale(1);
-webkit-transform-origin: 50% 50%;
transform: scale(1);
transform-origin: 50% 50%;
}
.pulse {
/*fill: red;*/
-webkit-animation-name: pulsar;
-webkit-animation-duration: 0.2s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
animation-name: pulsar;
animation-duration: 0.2s;
animation-iteration-count: infinite;
animation-direction: alternate;
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
}
@-webkit-keyframes pulsar {
from {
fill: red;
}
to {
fill: red;
-webkit-transform: scale(1.3);
-webkit-transform-origin: 50% 50%;
}
}
@keyframes pulsar {
from {
fill: red;
}
to {
fill: red;
transform: scale(1.3);
transform-origin: 50% 50%;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment