Skip to main content

D3 Visualization with Vue.js : a powerful alliance (when done right!)

[UPDATED MAY 2022]  D3.js is a very powerful visualization tool, especially for specialized/custom needs...  On the flip side, it's rather hard to use - with a steep learning curve.

Even worse if one also wants interactivity!

But why is D3 so hard/clunky to use?  And what can be done about it?

Spoiler alert: Vue.js (or other modern front-end framework) to the rescue - if done right...

All code in the examples is available in this GitHub repository.

The Root of the Problem

In a nutshell, what makes D3 awkward to use is that, for historical reasons, it tries to do too much: most painfully, it uses an old way to do direct DOM manipulation (i.e. restructuring the page layout) - an operation that nowadays is superbly handled in a far more friendly way by modern front-end frameworks, such as Vue.js

Document Object Model (DOM) is a programming interface for web documents.  In simple terms, it's the structure of the elements on a web page (text, images, etc.)
Let the front-end framework (such as Vue) handle it!

D3 is more than just about data visualization.  As a consequence of D3 emerging before modern front-end frameworks, it had to "do it all" itself.  As a result, it consists of several parts:

  • DOM utilities: this part resembles the archaic jQuery, and absolutely does not belong in modern web pages!
  • Data utilities/analysis: fine, but also available through other libraries, such as Lodash
  • Data visualization: this is the key "good part" that we must tap into!
  • Animation

For more detail, an excellent in-depth article:  D3 is not a Data Visualization Library.

From "D3 is not a Data Visualization Library",
by Elijah Meeks
The author, Elijah Meeks, who also wrote a D3 book, introduces diagrams such as this:

and then goes into a good amount of detail about each of the parts.

The take-home messages is the appealing prospect to "choose which parts of the [D3] library to learn and which parts to avoid".

But how exactly does one do that, in actual practice?

The Broad Picture

Anyone who's looking into creating custom D3 visualizations - as opposed to just picking a boiler-plate one from the vast D3 offerings (such as these) - is clearly someone with very specific/specialized needs.  Someone who also probably needs interactivity, reactivity to changes in the data, and generally fine control over the front end.  In short, a front-end programmer... or someone in a team that involves front-end programmers who are already using Vue.js or React, or another modern front-end framework.  If your visualization needs are common and straightforward, you're in the wrong place!

Below, I will discuss in detail how to graft the "good parts" of D3 into the "scaffold" provided by Vue.  A similar approach will probably work for other front-end frameworks.

A Warm-Up Example

The awkward "retro" quality of D3, when it's used to do it all, becomes painfully aware to anyone accustomed to a modern front-end framework.  When - in addition to the graphing part - D3 tries to also manage user interactivity or some type of UI, it feels like a journey to the painful ol' days of jQuery (an early JavaScript library to manage the front end.)

Bar graph and a checkbox UI,
all handled by D3

For example, an excellent in-depth first intro to D3 is a 3-part video series from 2020: all is good in the 1st and 2nd videos, which introduce making a bar graph with D3...  

but in the final part, where the checkbox interactivity is added, ouch!  It's painfully to revisit the old ways of doing such things prior to modern front-end frameworks.  With minor tweaks I added, here's the code for this "test3" : HMTL (largely a placeholder, plus CSS) and the D3 JavaScript file, where most of the action takes place.

In the first part of the JS file, you can see D3 reaching into the DOM (a task that really belongs to the framework) in lines such as   d3.select('svg')   , which is reminiscent of the old jQuery world.  The pain further increases in the 2nd half of the file, with the clunky pre-frameworks way of managing the UI!

In my test2 (files) I have a simpler example, with a bar graph but no checkboxes; much less awkward, when we're not trying to use D3 for the UI...

The even simpler test1 (files) has no "real" graphics (SVG code) at all: it emphasizes how D3 can be used - in a "retro" programming fashion - for any sort of general DOM manipulation.

SVG stands for Scalable Vector Graphics.  In simple terms, it's the counterpart of HML tags for graphics elements, such as rectangles, lines and points.  A good, detailed tutorial.
What D3 does is to generate the SVG code, and stick it in the right places on the page (this last function is best left to the front-end framework!)

How to keep the "good" D3 and ditch the "archaic" D3

I researched using Vue with D3...  and found that many authors utilize a very weak integration of the two: a simple insertion of the D3 elements into a Vue page - which completely fails to return the control of the DOM to Vue... and generally leads to unreactive pages (i.e. not automatically changing with changes of the underlying Vue data), unless special remedies are taken, such as the implementation of "watch" functions in Vue.

I also came across a good but long-winded workshop, plus some articles that I found helpful but confusing (such as this one), and rare truly helpful articles like this one (which I'll revisit at the very end)... but mostly I found rehashes of the half-baked minimal integrations of D3 into Vue pages.

I ended up creating a series of code snapshots of a step-by-step process I took, to start with pure D3 ("I do it all, even what I don't do well"), and gradually wrestle away from D3 the parts that best belong to Vue - with the final result of a clean, easy-to-read (if you know Vue!) and reactive modern front end, with a sensible division of labor between D3 and Vue; in principle it could also be any other modern front-end framework.

A STEP-BY-STEP example: a D3 heatmap gradually turned into a clean D3 + Vue

FILES: in the repository, check out the files "heatmap1.htm" thru "heatmap8.htm", plus their .js counterparts when present, in the heatmap directory.

Not a Vue expert?  No problem - you can simply clone the repository to your local machine, and open the HTML files in your browser: NOTHING TO INSTALL :)

1) heatmap1.htm is a pure D3 heatmap, taken straight out from this D3 graph gallery.

2) In heatmap2.htm, I add the Vue scaffold (a "root" element that I'm not yet using), and I replace the heatmap dataset with just a handful of values hardwired into the file.
Please note that I use the final release (2.6) of Vue version 2, stored in my repository.

3) In heatmap3.htm, I introduce a Vue component, <vue-heatmap-3> , in the file heatmap3_comp.js.  All the data for the heatmap is now managed by Vue, and passed to the component, but the heatmap is still entirely produced, and inserted into the DOM, by D3.

The Vue component receives data from its parent, but is NOT reactive:  the mounted() function gets called once, and that's the end of it!

(Note: I use the "template literals" format for Vue components, which I think is very readable, and requires no file compilation.  Various alternatives are discussed in this excellent article: 7 Ways to Define a Component Template in Vue.js)

Many authors stop here in their weak integration of D3 and Vue...  but this surely isn't the end of the story!

4) In heatmap4 (.htm and .js files), a different Vue component takes control of computed values and of most functions used by the original D3 code, except for the axes generation.  

Vue takes control, but does not re-invent the wheel: it invokes the amazing functions provided by D3 libraries, for example for scaling or color mapping.

The DOM manipulation is still being done by D3, for now.
Why are we leaving the axes for last?  Because, alas, the creation of the axes in D3 is hopelessly entangled with the DOM modification, rather than being a truly modular element that just produces the SVG code for the axes without messing around with the DOM...

5) In heatmap5, the creation of the actual heatmap is separated from the creation of the overall graph and axes.  Also, a Vue watch is instituted for the prop 'my_data', which now becomes reactive: it changes the heatmap as needed, when the data is modified.

The screenshot below was taken using the (highly, highly recommended!) Vue Devtools extension, seen here in Firefox.  If you change the "my_data" array in the Vue root component, you'll see the heatmap instantly change.  (Note: make sure to edit the whole array, as show near the bottom of the picture; if you expand the arrow next to my_data, and just change one array element, Vue doesn't detect that.)

By contrast, if you make a similar change in the previous heatmap4, nothing happens, because it's not reactive.  Note that we have to do extra work to attain reactivity; that's because D3 is still meddling with the DOM.  

Reactivity will happen organically once we banish D3 from getting its dirty little paws directly into the DOM.

6) In heatmap6, Vue takes control of the SVG element (in the template of the Vue component), while D3 handles the CONTENTS of the SVG element.

7) In heatmap7, most of the plot is now handled directly by Vue, in an SVG code template (very easy to read and modify), using Vue iteration over the heatmap rectangles, and Vue computations of plot parameters with D3 libraries.

Many D3 libraries are awesome, and we're continuing to utilize them, while at the same time banishing the archaic part of D3


The axes still remain a DOM manipulation directly done by D3, and require special handling to be reactive to changes in the data (while the Vue-controlled part is automatically reactive.)

8) In heatmap8, the last direct DOM manipulation has been wrestled out of D3, hallelujah!

As mentioned earlier, the D3 axes generator is hopelessly entangled with the DOM manipulation, and therefore has to be ditched.  

It's pretty easy, however, to create an SVG axes generator; I ported to JavaScript an old SVG axes generator I had created in PHP many years ago, and tweaked it to give almost identical visuals to the built-in one in D3 (I changed the axes to grey, but you can tweak that and more in the CSS, which I have in the html file.)  The code can be found in the SVG_helper library; with just a light knowledge of SVG, one can easily tweak it, to get the axes any way one wants them, or to factor out to convenient JavaScript calls any other custom SVG code that one needs.

The heatmap also includes a few extra lines (middle, top and right), to demonstrate various ways of adding SVG elements in the template of the Vue component.

All the extra code to create reactivity is now taken out: the page is organically reactive because it utilizes Vue correctly - rather than the earlier "backseat driving" by D3!

Here's an example of reactivity to the enlargement of "outer_width":

All Said and Done...

The final result (files heatmap8.htm and heatmap8_comp.js) utilizes standard D3 libraries for scaling and color mapping, plus a simple SVG helper library (just for the axes) that could be easily customized to one's very specific needs.

[May 2022 update: an improved SVG helper library is now being expanded and maintained by the open-source project Life123; details at the very end of this article!]

Is it simpler than the starting point (heatmap1.htm)?  Well, if one was aiming to do nothing more than the heatmap per se, then the original D3 implementation, or the light Vue integration from step3, might be just fine.

But here I've been addressing the needs of people who have to go beyond existing boiler-plate solutions, and require a high level of control of the graphics as well as the UI surrounding it.  

The original pure-D3 heatmap is OK as a standalone element, but the final heatmap8 in our example above is fully reactive to changes in the data, and is completely in Vue's control, with the SVG very accessible in template form - and so, it's very ready to be easily expanded with UI controls, interactivity and customization, with just a normal Vue skillset, plus a light knowledge of SVG and of the needed D3 libraries.  Anything not provided by a standard D3 library, could be custom-designed and added to the SVG helper library.

D3 at the service of the front-end framework!
Reaping the Benefits

Now that we have a full integration of the heatmap graphics with Vue, we can easily add all sorts of UI controls and interactivity: we're in "Vue territory" and we can draw upon its power and convenience.  

For example, it's a breeze to add a slider that lets the user select a start bin to display in the heatmap.  I'm calling the file heatmap8_slider.htm, rather than heatmap9, for clarity - because we're still using the same Vue component (heatmap8_comp.js) to draw the actual heatmap.  I also added more data to better see the effect, and I'm showing the raw data - being sent to the graphing component - under the image.

Two More Examples

Having discussed the step-by-step process to wrestle out of D3 what is best done by the front-end framework, here are two more complete examples of D3 fully and sensibly integrated into Vue:

1) Dots and lines.  A button toggles between styles.  It looks best on Chrome.  Code.

Based on this video.

 

2) An "interactive star".  A slider determines the number of rays.  Code.

Adapted from this very helpful detailed article.


See More

[May 2022 update]  The open-source project Life123 is exactly an example of something that needs interactive, very customized ad-hoc visualization. You'll find a growing list of Vue components using D3 libraries in the repository for that project: GitHub directory with Vue components, their CSS files and HTML test files. 

Maybe get involved in contributing Vue/D3 components for that open source project?

Comments

Popular posts from this blog

Discussing Neuroscience with ChatGPT

UPDATED Apr. 2023 - I'm excited by ChatGPT 's possibilities in terms of facilitating advanced learning .  For example, I got enlightening answers to questions that I had confronted when I first studied neuroscience.  The examples below are taken from a very recent session I had with ChatGPT (mid Jan. 2023.) Source: https://neurosciencestuff.tumblr.com In case you're not familiar with ChatGPT, it's a very sophisticated "chatbot" - though, if you call it that way, it'll correct you!  'I am not a "chatbot", I am a language model, a sophisticated type of AI algorithm trained on vast amounts of text data to generate human-like text'. For a high-level explanation of how ChatGPT actually works - which also gives immense insight into its weaknesses, there's an excellent late Jan. 2023 talk by Stephen Wolfram, the brilliant author of the Mathematica software and of Wolfram Alpha , a product that could be combined with ChatGPT to imp

Neo4j & Cypher Tutorial : Getting Started with a Graph Database and its Query Language

You have a general idea of what Graph Databases - and Neo4j in particular - are...  But how to get started?  Read on! This is part 3 of a 7-part series on Graph Databases and Neo4j.   part 1 : Graph Databases (Neo4j) - a revolution in modeling the real world! part 2 : Neo4j Sandbox Tutorial : try Neo4j and learn Cypher the free and easy way part 3 : Neo4j & Cypher Tutorial : Getting Started with a Graph Database and its Query Language  part 4 : Using Neo4j with Python : the Open-Source Library NeoAccess part 5 : Using Schema in Graph Databases such as Neo4j part 6  : Putting it All Together - a Technology Stack on Top of a Graph Database part 7  : (SPECIAL TOPIC) Full-Text Search with the Neo4j Graph Database If you're new to graph databases, please check out part 1 for an intro and motivation about them.  There, we discussed an example about an extremely simple database involving actors, movies and directors...  and saw how easy the Cypher query lan

Graph Databases (Neo4j) - a revolution in modeling the real world!

UPDATED July 2023 - I was "married" to Relational Databases for many years... and it was a good "relationship" full of love and productivity - but SOMETHING WAS MISSING! Let me backtrack.   In college, I got a hint of the "pre-relational database" days...  Mercifully, that was largely before my time, but  - primarily through a class - I got a taste of what the world was like before relational databases.  It's an understatement to say: YUCK! Gratitude for the power and convenience of Relational Databases and SQL - and relief at having narrowly averted life before it! - made me an instant mega-fan of that technology.  And for many years I held various jobs that, directly or indirectly, made use of MySQL and other relational databases - whether as a Database Administrator, Full-Stack Developer, Data Scientist, CTO or various other roles. UPDATE: This article is now part of a series... This is part 1 of a 7-part series on Graph Databases and Neo4j.  

Using Neo4j with Python : the Open-Source Library "NeoAccess"

So, you want to build a python app or Jupyter notebook to utilize Neo4j, but aren't too keen on coding a lot of string manipulation to programmatic create ad-hoc Cypher queries?   You're in the right place: the NeoAccess library can do take care of all that, sparing you from lengthy, error-prone development that requires substantial graph-database and software-development expertise! This is part 4 of a 7-part series on Graph Databases and Neo4j.   part 1 : Graph Databases (Neo4j) - a revolution in modeling the real world! part 2 : Neo4j Sandbox Tutorial : try Neo4j and learn Cypher – free and easy part 3 : Neo4j & Cypher Tutorial : Getting Started with a Graph Database and its Query Language   part 4 : Using Neo4j with Python : the Open-Source Library "NeoAccess" part 5 : Using Schema in Graph Databases such as Neo4j part 6  : Putting it All Together - a Technology Stack on Top of a Graph Database part 7  : (SPECIAL TOPIC) Ful

To Build or Not to Build One’s Own Desktop Computer?

“ VALENTINA ” [UPDATED JUNE 2021] - Whether you're a hobbyist, or someone who just needs a good desktop computer, or an IT professional who wants a wider breath of knowledge, or a gamer who needs a performant machine, you might have contemplated at some point whether to build your own desktop computer. If you're a hobbyist, I think it's a great project.  If you're an IT professional - especially a "coder" - I urge you to do it: in my opinion, a full-fledged Computer Scientist absolutely needs breath, ranging from the likes of Shannon's Information Theory and the Halting Problem - all the way down to how transistors work. And what about someone who just needs a good desktop computer?  A big maybe on that - but perhaps this blog entry will either help you, or scare you off for your own good! To build, or not to build, that is the question: Whether 'tis nobler in the mind to suffer The slings and arrows of OEM's cutting corners and limit

Using Schema in Graph Databases such as Neo4j

UPDATED Aug. 2023 - Graph databases have an easygoing laissez-faire attitude: "express yourself (almost) however you want"... By contrast, relational databases come across with an attitude along the lines of a micro-manager:  "my way or the highway"... Is there a way to take the best of both worlds and distance oneself from their respective excesses, as best suited for one's needs? This is part 5 of a 7-part series on Graph Databases and Neo4j.   part 1 : Graph Databases (Neo4j) - a revolution in modeling the real world! part 2 : Neo4j Sandbox Tutorial : try Neo4j and learn Cypher the free and easy way part 3 : Neo4j & Cypher Tutorial : Getting Started with a Graph Database and its Query Language part 4 : Using Neo4j with Python : the Open-Source Library NeoAccess part 5 : Using Schema in Graph Databases such as Neo4j part 6  : Putting it All Together - a Technology Stack on Top of a Graph Database part 7  : (SPECIAL TOPIC) F

Full-Text Search with the Neo4j Graph Database

(UPDATED Sep. 2023)   In part 5 ( Using Schema in Graph Databases ) we discussed the concept of a Schema Layer, and a design and implementation available from the open-source project BrainAnnex.org Now that we have such a layer, what shall be build on top of it?   Well, how about  Full-Text Search ?  This is  part 7  of a ongoing series on Graph Databases and Neo4j.   part 1  : Graph Databases (Neo4j) - a revolution in modeling the real world! part 2  : Neo4j Sandbox Tutorial : try Neo4j and learn Cypher the free and easy way part 3  : Neo4j & Cypher Tutorial : Getting Started with a Graph Database and its Query Language part 4  : Using Neo4j with Python : the Open-Source Library NeoAccess part 5  : Using Schema in Graph Databases such as Neo4j part 6 :   Putting it All Together - a Technology Stack on Top of a (Neo4j) Graph Database part 7 : (SPECIAL TOPIC) Full-Text Search with the Neo4j Graph Database part 8 (upcoming!) : (SPECIAL TOPIC) Document Management Full-Text Searching/

PET/CT Combined Scanners - a 2018 Breakthrough of the Year... and a Personal Story

Image source Recently, a co-worker in her 20's was diagnosed with a brain tumor!  At times like these, the importance of medical imaging jumps to the fore! Most people have heard of CT ("CAT") scanners – at least enough to know that they don't actually involve cats – but less well-known are PET scanners (which likewise don't involve pets!), and the synergistic combination of the two. A Marriage Made in Heaven What do those scanners do?  And why are they being combined in single devices? Voted 2018 Breakthrough of the Year by a science magazine , the improved PET/CT combined scanner has been a game changer. The EXPLORER PET/CT scanner – the world’s first medical imaging system that can capture a 3D image of the entire human body simultaneously – has produced its first human images. Developed by UC Davis scientists and a multi-institutional consortium, EXPLORER can scan up to 40 times faster, or use up to 40 times less radiation dose, than

RDF Triple Stores vs. Property Graphs : How to Attach Properties to Relationships

Time for the opening shot of a series about Semantic Technology , and in particular contrasting-and-comparing the opposing (but perhaps ultimately complementary) camps of:   RDF Triple Stores , aka Triples-Based Graphs.   For example, Blazegraph or Apache Jena   (Labeled) Property Graphs .  For example, Neo4j or Blazegraph (For this article, I'll assume that you have at least a passing acquaintance with both.  Here is background info on Triplestores and Property Graphs ) It’s my opinion that modeling in terms of Subject/Predicate/Object triples (aka RDF ) might be appealing to mathematicians or philosophers for its minimalist foundation (though a lot of baroque add-on’s quickly come out of the closet!) Modeling in terms of (Labeled) Property Graphs might be appealing to computer scientists, because such graphs appear more usable and less clunky once you start actually doing something with them. Perhaps because I straddle both the Math and CS camps, I’m currently on t

Brain Microarchitecture : Feedback from Higher-order areas to Lower-order areas

Some questions that arise in Machine Learning involve the prospect of using feedback from Higher-order areas (downstream) to Lower-order areas (upstream), and using Global Knowledge for Local Processing.  A desire to gain insight into those issues from Neuroscience ("how does the brain do it?") led me to some fascinating investigations into the Microcircuits of the Cerebral Cortex.  This blog entry is a broad review of the field, in the context of the original motivating questions from Machine Learning.   Starting out with a quote from the “bible of Neuroscience”: From Principles of Neural Science, 5th edn  (Online book location 1435.3 / 5867).  Emphasis and note added by me: Sensory pathways are not exclusively serial; in each functional pathway higher-order areas project back to the lower-order areas from which they receive input. In this way neurons in higher-order areas, sensitive to the global pattern of sensory input, can modulate the activity of neurons in lowe