Drag

Exclusive offer: get 50% off this eBook here
Data Visualization with d3.js

Data Visualization with d3.js — Save 50%

Mold your data into beautiful visualizations with d3.js with this book and ebook

$17.99    $9.00
by Swizec Teller | October 2013 | Java Open Source Web Development

In this article by Swizec Teller, the author of the book Data Visualization with d3.js, we will have a look at the dragging behavior module of d3.

(For more resources related to this topic, see here.)

I can't think of a better dragging demonstration than animating with the parallax illusion. The illusion works by having several keyframes rendered in vertical slices and dragging a screen over them to create an animated thingamabob.

Drawing the lines by hand would be tedious, so we're using an image Marco Kuiper created in Photoshop. I asked on Twitter and he said we can use the image, if we check out his other work at marcofolio.net.

You can also get the image in the examples repository at https://raw.github.com/Swizec/d3.js-book-examples/master/ch4/parallax_base.png.

We need somewhere to put the parallax:

var width = 1200, height = 450, svg = d3.select('#graph') .append('svg') .attr({width: width, height: height});

We'll use SVG's native support for embedding bitmaps to insert parallax_base.png into the page:

svg.append('image') .attr({'xlink:href': 'parallax_base.png', width: width, height: height});

The image element's magic stems from its xlink:href attribute. It understands links and even lets us embed images to create self-contained SVGs. To use that, you would prepend an image MIME type to a base64 encoded representation of the image.

For instance, the following line is the smallest embedded version of a spacer GIF. Don't worry if you don't know what a spacer GIF is; they were useful up to about 2005.

data:image/gif;base64,R0lGODlhAQABAID/ AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==

Anyway, now that we have the animation base, we need a screen that can be dragged. It's going to be a bunch of carefully calibrated vertical lines:

var screen_width = 900, lines = d3.range(screen_width/6), x = d3.scale.ordinal().domain(lines).rangeBands([0, screen_width]);

We'll base the screen off an array of numbers (lines). Since line thickness and density are very important, we divide screen_width by 6—five pixels for a line and one for spacing. Make sure the value of screen_width is a multiple of 6; otherwise anti-aliasing ruins the effect.

The x scale will help us place the lines evenly:

svg.append('g') .selectAll('line') .data(lines) .enter() .append('line') .style('shape-rendering', 'crispEdges') .attr({stroke: 'black', 'stroke-width': x.rangeBand()-1, x1: function (d) { return x(d); }, y1: 0, x2: function (d) { return x(d); }, y2: height});

There's nothing particularly interesting here, just stuff you already know. The code goes through the array and draws a new vertical line for each entry. We made absolutely certain there won't be any anti-aliasing by setting shape-rendering to crispEdges.

Time to define and activate a dragging behavior for our group of lines:

var drag = d3.behavior.drag()
.origin(Object)
.on('drag', function () {
d3.select(this)
.attr('transform', 'translate('+d3.event.x+', 0)')
.datum({x: d3.event.x, y: 0});
});

We created the behavior with d3.behavior.drag(), defined a .origin() accessor, and specified what happens on drag. The behavior automatically translates touch and mouse events to the higher-level drag event. How cool is that!

We need to give the behavior an origin so it knows how to calculate positions relatively; otherwise, the current position is always set to the mouse cursor and objects jump around. It's terrible. Object is the identity function for elements and assumes a datum with x and y coordinates.

The heavy lifting happens inside the drag listener. We get the screen's new position from d3.event.x, move the screen there, and update the attached .datum() method.

All that's left to do is to call drag and make sure to set the attached datum to the current position:

svg.select('g') .datum({x: 0, y: 0}) .call(drag);

The item looks solid now! Try dragging the screen at different speeds.

The parallax effect doesn't work very well on a retina display because the base image gets resized and our screen loses calibration.

Summary

In this article, we looked into the drag behavioud of d3. All this can be done by with just click events, but I heartily recommend d3's behaviors module. It makes complex behaviors is that they automatically create relevant event listeners and let you work at a higher level of abstraction.

Resources for Article:


Further resources on this subject:


Data Visualization with d3.js Mold your data into beautiful visualizations with d3.js with this book and ebook
Published: October 2013
eBook Price: $17.99
Book Price: $29.99
See more
Select your format and quantity:

About the Author :


Swizec Teller

Swizec Teller is a geek with a hat. Founding his first startup at 21, he is now looking for the next big idea as a full-stack web generalist focusing on freelancing for early-stage startup companies.

When he isn't coding, he's usually blogging, writing books, or giving talks at various non-conference events in Slovenia and nearby countries. He is still looking for a chance to speak at a big international conference.

In November 2012, he started writing Why Programmers Work at Night, and set out on a quest to improve the lives of developers everywhere.

Books From Packt


Data Visualization with D3.js Cookbook
Data Visualization with D3.js Cookbook

Python Data Visualization Cookbook
Python Data Visualization Cookbook

Data Visualization: a successful design process
Data Visualization: a successful design process

MATLAB Graphics and Data Visualization Cookbook
MATLAB Graphics and Data Visualization Cookbook

Google Visualization API Essentials
Google Visualization API Essentials

SketchUp 7.1 for Architectural Visualization: Beginner's Guide
SketchUp 7.1 for Architectural Visualization: Beginner's Guide

Tableau Data Visualization Cookbook
Tableau Data Visualization Cookbook

 Instant Heat Maps in R How-to [Instant]
Instant Heat Maps in R How-to [Instant]


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
t
P
z
A
L
4
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software