SlideShare uma empresa Scribd logo
1 de 27
Baixar para ler offline
I M P R O V I N G D 3 P E R F O R M A N C E W I T H
C A N VA S A N D O T H E R H A C K S
WebTechCon 2015
2015-10-27
Philip Tellis
@bluesmoon
https://github.com/lognormal/boomerang
http://www.soasta.com/mpulse/
D 3 I S …
• A JavaScript library that maps Data to DOM Nodes
• Extended via layouts & plugins for rich data
visualisations
• You still need to write code to draw things
• Fast on its own, but you can easily make it sluggish
• BSD Licensed — http://d3js.org/
H T T P S : / / G I T H U B . C O M / M B O S T O C K / D 3 /
W I K I / G A L L E RY
G E T S TA R T E D W I T H D 3
B A S I C D 3 T U T O R I A L
• Adding nodes
• Mapping data to nodes
• Data Driven Documents
• Examples 01-06 at http://soasta.github.io/improving-
d3-performance/d3/
A N I M AT E D D 3 C H A R T S
• Force Directed Layout
• Reacting to user interaction
• Reacting to changing data
F O R C E D I R E C T E D L AY O U T
U S I N G P H Y S I C S
F O R C E D I R E C T E D L AY O U T
• http://bl.ocks.org/mbostock/4062045
• Took basic Force Directed Layout and added
enhancements:
• Convex hulls
• Labels
• Mouseovers
• Variable sized points
F O R C E D I R E C T E D L AY O U T —
P R O B L E M S
• Rendering is O(n) based on number of SVG nodes
• Calculations are O(n2
) based on number of links
• Drawing the hull is expensive as nodes move around a
lot
F O R C E D I R E C T E D L AY O U T —
S O L U T I O N S
• Reduce number of links by using a Minimum Spanning
Tree
• Identify clusters and only link one node from each
cluster
• Visually reduce nodes within the cluster using
approximation
• Add decorators later as the animation stabilizes
F O R C E D I R E C T E D L AY O U T —
A D D I T I O N A L O P T I O N S
• We could use CANVAS to get rid of SVG nodes
• Create subgroups within each group to further reduce
links
• Get rid of some of our visual enhancements
E D G E B U N D L E D L AY O U T
U S E R I N T E R A C T I O N
E D G E B U N D L E D L AY O U T
• http://bl.ocks.org/mbostock/7607999
• We added many more links
• Links colored based on performance
• Links sized based on volume of data flow
• Mouseover should highlight connected links
• Nodes sized based on volume within that node
E D G E B U N D L E D L AY O U T — P R O B L E M S
• Default behaviour is to iterate through every link on
mouseover and change colour — this is slooooow!
• Using CSS class to change colour causes major re-
render
• Quickly cycling through nodes has noticeable lag
E D G E B U N D L E D L AY O U T — S O L U T I O N S
• First we tried to not iterate, just use CSS class
cascades
• This was a trade off because we ended up adding a
large number of classes, two per node and one per
link
E D G E B U N D L E D L AY O U T — S O L U T I O N S
• The second attempt was to use CANVAS to draw
everything
• The problem here is that CANVAS is not great for text,
and mouseovers no longer worked
E D G E B U N D L E D L AY O U T — S O L U T I O N S
• The third attempt was to use CANVAS to draw links
and SVG for nodes
• The biggest problem was to make sure they
overlapped perfectly, ie, it was a small problem.
C A N VA S D O E S N O T
S U P P O R T B E Z I E R C U R V E S ! ! !
E X C E P T …
D 3 W I T H C A N VA S
• There are some great examples online…
• https://bocoup.com/weblog/d3js-and-canvas
• https://gist.github.com/mbostock/1276463
• But not quite what we wanted
D 3 W I T H C A N VA S
• Create a Custom XML NameSpace
• Map dummy nodes from this namespace for each link
• Each dummy node contains the SVG path required to
draw the curve as well as other attributes
• After all nodes have been mapped, call a renderer to
convert this to CANVAS
d3.ns.prefix.custom = "https://foo-bar.com/edge_bundling.html";
d3.select("body").append("custom:sketch")
.classed("link-container", true);
…
linkBinding.enter()
.append("custom:path")
.attr("lineCap", "round")
.attr("lineJoin", "round")
.attr("lineWidth", .2)
.attr("opacity", 0.1)
.attr("selected-opacity", 0.3);
linkBinding
.attr("selected-lineWidth", function(d) { return
weightScale(d.weight); })
.attr("d", function(d) { return line(d.path); });
C R E AT I N G N O D E S
var pathAttrs =
["strokeStyle", "lineCap", "lineJoin", "lineWidth"];
ctx.beginPath();
pathAttrs.forEach(function(a) {
var val = node.attr(selected + a) || node.attr(a);
if(a === "strokeStyle") {
var color = d3.rgb(val);
val = "rgba(" +
color.r + "," +
color.g + "," +
color.b + "," +
node.attr(selected + "opacity") + ")";
}
ctx[a] = val;
});
A P P LY I N G S T Y L E S
var path = node.attr("d"), m;
while((m = path.match(/^ *([MLCQ])([d.,e-]+) */))) {
var cmd = m[1];
var coords = m[2].split(",").map(pathToCoords);
path = path.replace(/^ *([MLCQ])([d.,e-]+) */, "");
switch(cmd) {
case "M":
ctx.moveTo(coords[0], coords[1]);
break;
case "L":
ctx.lineTo(coords[0], coords[1]);
break;
case "C":
ctx.bezierCurveTo(coords[0], coords[1], coords[2], coords[3],
coords[4], coords[5]);
break;
case "Q":
ctx.quadraticCurveTo(coords[0], coords[1],
coords[2], coords[3]);
break;
}
}
D R A W I N G C U R V E S
B U T I T S T I L L WA S N ’ T
FA S T E N O U G H !
E N H A N C E M E N T S
• Use 2 CANVAS elements,
• one to hold the background (ie, all links),
• the second to show the currently selected links
• Change opacity on the background to darken it
• If mouse pointer returns to last selected node, just
redisplay
S U M M A RY
• Number of DOM nodes is very significant
• Reduce calculations on in-memory objects
• Show approximate data, based on available pixels and
power
• Use CANVAS when mouse interaction is not required
• Cache repeated states rather than redrawing them
Thank You

Mais conteúdo relacionado

Semelhante a Improving D3 Performance with CANVAS and other Hacks

D3.js capita selecta
D3.js capita selectaD3.js capita selecta
D3.js capita selecta
Joris Klerkx
 
Fii Practic Frontend - BeeNear - laborator 4
Fii Practic Frontend - BeeNear - laborator 4Fii Practic Frontend - BeeNear - laborator 4
Fii Practic Frontend - BeeNear - laborator 4
BeeNear
 
FP Days: Down the Clojure Rabbit Hole
FP Days: Down the Clojure Rabbit HoleFP Days: Down the Clojure Rabbit Hole
FP Days: Down the Clojure Rabbit Hole
Christophe Grand
 

Semelhante a Improving D3 Performance with CANVAS and other Hacks (20)

Wanderu - Lessons from Building a Travel Site with Neo4j
Wanderu - Lessons from Building a Travel Site with Neo4jWanderu - Lessons from Building a Travel Site with Neo4j
Wanderu - Lessons from Building a Travel Site with Neo4j
 
D3.js capita selecta
D3.js capita selectaD3.js capita selecta
D3.js capita selecta
 
SVG (Devoxx 2011, 2011-NOV-14)
SVG (Devoxx 2011, 2011-NOV-14)SVG (Devoxx 2011, 2011-NOV-14)
SVG (Devoxx 2011, 2011-NOV-14)
 
Fii Practic Frontend - BeeNear - laborator 4
Fii Practic Frontend - BeeNear - laborator 4Fii Practic Frontend - BeeNear - laborator 4
Fii Practic Frontend - BeeNear - laborator 4
 
Visual Network Analysis
Visual Network AnalysisVisual Network Analysis
Visual Network Analysis
 
Fast track to getting started with DSE Max @ ING
Fast track to getting started with DSE Max @ INGFast track to getting started with DSE Max @ ING
Fast track to getting started with DSE Max @ ING
 
Network theory - PyCon 2015
Network theory - PyCon 2015Network theory - PyCon 2015
Network theory - PyCon 2015
 
Graph-Tool in Practice
Graph-Tool in PracticeGraph-Tool in Practice
Graph-Tool in Practice
 
Lecture 16 - Dijkstra's Algorithm.pdf
Lecture 16 - Dijkstra's Algorithm.pdfLecture 16 - Dijkstra's Algorithm.pdf
Lecture 16 - Dijkstra's Algorithm.pdf
 
Avoiding Deadlocks: Lessons Learned with Zephyr Health Using Neo4j and MongoD...
Avoiding Deadlocks: Lessons Learned with Zephyr Health Using Neo4j and MongoD...Avoiding Deadlocks: Lessons Learned with Zephyr Health Using Neo4j and MongoD...
Avoiding Deadlocks: Lessons Learned with Zephyr Health Using Neo4j and MongoD...
 
Social Network Analysis - Lecture 4 in Introduction to Computational Social S...
Social Network Analysis - Lecture 4 in Introduction to Computational Social S...Social Network Analysis - Lecture 4 in Introduction to Computational Social S...
Social Network Analysis - Lecture 4 in Introduction to Computational Social S...
 
FP Days: Down the Clojure Rabbit Hole
FP Days: Down the Clojure Rabbit HoleFP Days: Down the Clojure Rabbit Hole
FP Days: Down the Clojure Rabbit Hole
 
Advanced sass/compass
Advanced sass/compassAdvanced sass/compass
Advanced sass/compass
 
Thorny Path to the Large Scale Graph Processing, Алексей Зиновьев (Тамтэк)
Thorny Path to the Large Scale Graph Processing, Алексей Зиновьев (Тамтэк)Thorny Path to the Large Scale Graph Processing, Алексей Зиновьев (Тамтэк)
Thorny Path to the Large Scale Graph Processing, Алексей Зиновьев (Тамтэк)
 
Thorny path to the Large-Scale Graph Processing (Highload++, 2014)
Thorny path to the Large-Scale Graph Processing (Highload++, 2014)Thorny path to the Large-Scale Graph Processing (Highload++, 2014)
Thorny path to the Large-Scale Graph Processing (Highload++, 2014)
 
PostgreSQL is the new NoSQL - at Devoxx 2018
PostgreSQL is the new NoSQL  - at Devoxx 2018PostgreSQL is the new NoSQL  - at Devoxx 2018
PostgreSQL is the new NoSQL - at Devoxx 2018
 
Graphics 2D SVG
Graphics 2D SVGGraphics 2D SVG
Graphics 2D SVG
 
Data science at the command line
Data science at the command lineData science at the command line
Data science at the command line
 
Docker in development
Docker in developmentDocker in development
Docker in development
 
Apdm 101 Arc Gis Pipeline Data Model (1)
Apdm 101 Arc Gis Pipeline Data Model  (1)Apdm 101 Arc Gis Pipeline Data Model  (1)
Apdm 101 Arc Gis Pipeline Data Model (1)
 

Mais de Philip Tellis

Improving 3rd Party Script Performance With IFrames
Improving 3rd Party Script Performance With IFramesImproving 3rd Party Script Performance With IFrames
Improving 3rd Party Script Performance With IFrames
Philip Tellis
 
Analysing network characteristics with JavaScript
Analysing network characteristics with JavaScriptAnalysing network characteristics with JavaScript
Analysing network characteristics with JavaScript
Philip Tellis
 
A Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web TrafficA Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web Traffic
Philip Tellis
 

Mais de Philip Tellis (20)

Frontend Performance: Beginner to Expert to Crazy Person
Frontend Performance: Beginner to Expert to Crazy PersonFrontend Performance: Beginner to Expert to Crazy Person
Frontend Performance: Beginner to Expert to Crazy Person
 
Frontend Performance: De débutant à Expert à Fou Furieux
Frontend Performance: De débutant à Expert à Fou FurieuxFrontend Performance: De débutant à Expert à Fou Furieux
Frontend Performance: De débutant à Expert à Fou Furieux
 
Frontend Performance: Expert to Crazy Person
Frontend Performance: Expert to Crazy PersonFrontend Performance: Expert to Crazy Person
Frontend Performance: Expert to Crazy Person
 
Beyond Page Level Metrics
Beyond Page Level MetricsBeyond Page Level Metrics
Beyond Page Level Metrics
 
Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...
Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...
Frontend Performance: Beginner to Expert to Crazy Person (San Diego Web Perf ...
 
Frontend Performance: Beginner to Expert to Crazy Person
Frontend Performance: Beginner to Expert to Crazy PersonFrontend Performance: Beginner to Expert to Crazy Person
Frontend Performance: Beginner to Expert to Crazy Person
 
Frontend Performance: Beginner to Expert to Crazy Person
Frontend Performance: Beginner to Expert to Crazy PersonFrontend Performance: Beginner to Expert to Crazy Person
Frontend Performance: Beginner to Expert to Crazy Person
 
Frontend Performance: Beginner to Expert to Crazy Person
Frontend Performance: Beginner to Expert to Crazy PersonFrontend Performance: Beginner to Expert to Crazy Person
Frontend Performance: Beginner to Expert to Crazy Person
 
mmm... beacons
mmm... beaconsmmm... beacons
mmm... beacons
 
RUM Distillation 101 -- Part I
RUM Distillation 101 -- Part IRUM Distillation 101 -- Part I
RUM Distillation 101 -- Part I
 
Improving 3rd Party Script Performance With IFrames
Improving 3rd Party Script Performance With IFramesImproving 3rd Party Script Performance With IFrames
Improving 3rd Party Script Performance With IFrames
 
Extending Boomerang
Extending BoomerangExtending Boomerang
Extending Boomerang
 
Abusing JavaScript to measure Web Performance, or, "how does boomerang work?"
Abusing JavaScript to measure Web Performance, or, "how does boomerang work?"Abusing JavaScript to measure Web Performance, or, "how does boomerang work?"
Abusing JavaScript to measure Web Performance, or, "how does boomerang work?"
 
The Statistics of Web Performance Analysis
The Statistics of Web Performance AnalysisThe Statistics of Web Performance Analysis
The Statistics of Web Performance Analysis
 
Abusing JavaScript to Measure Web Performance
Abusing JavaScript to Measure Web PerformanceAbusing JavaScript to Measure Web Performance
Abusing JavaScript to Measure Web Performance
 
Rum for Breakfast
Rum for BreakfastRum for Breakfast
Rum for Breakfast
 
Analysing network characteristics with JavaScript
Analysing network characteristics with JavaScriptAnalysing network characteristics with JavaScript
Analysing network characteristics with JavaScript
 
A Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web TrafficA Node.JS bag of goodies for analyzing Web Traffic
A Node.JS bag of goodies for analyzing Web Traffic
 
Input sanitization
Input sanitizationInput sanitization
Input sanitization
 
Messing with JavaScript and the DOM to measure network characteristics
Messing with JavaScript and the DOM to measure network characteristicsMessing with JavaScript and the DOM to measure network characteristics
Messing with JavaScript and the DOM to measure network characteristics
 

Último

Último (20)

Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 

Improving D3 Performance with CANVAS and other Hacks

  • 1. I M P R O V I N G D 3 P E R F O R M A N C E W I T H C A N VA S A N D O T H E R H A C K S WebTechCon 2015 2015-10-27
  • 3. D 3 I S … • A JavaScript library that maps Data to DOM Nodes • Extended via layouts & plugins for rich data visualisations • You still need to write code to draw things • Fast on its own, but you can easily make it sluggish • BSD Licensed — http://d3js.org/
  • 4. H T T P S : / / G I T H U B . C O M / M B O S T O C K / D 3 / W I K I / G A L L E RY G E T S TA R T E D W I T H D 3
  • 5. B A S I C D 3 T U T O R I A L • Adding nodes • Mapping data to nodes • Data Driven Documents • Examples 01-06 at http://soasta.github.io/improving- d3-performance/d3/
  • 6. A N I M AT E D D 3 C H A R T S • Force Directed Layout • Reacting to user interaction • Reacting to changing data
  • 7. F O R C E D I R E C T E D L AY O U T U S I N G P H Y S I C S
  • 8. F O R C E D I R E C T E D L AY O U T • http://bl.ocks.org/mbostock/4062045 • Took basic Force Directed Layout and added enhancements: • Convex hulls • Labels • Mouseovers • Variable sized points
  • 9. F O R C E D I R E C T E D L AY O U T — P R O B L E M S • Rendering is O(n) based on number of SVG nodes • Calculations are O(n2 ) based on number of links • Drawing the hull is expensive as nodes move around a lot
  • 10. F O R C E D I R E C T E D L AY O U T — S O L U T I O N S • Reduce number of links by using a Minimum Spanning Tree • Identify clusters and only link one node from each cluster • Visually reduce nodes within the cluster using approximation • Add decorators later as the animation stabilizes
  • 11. F O R C E D I R E C T E D L AY O U T — A D D I T I O N A L O P T I O N S • We could use CANVAS to get rid of SVG nodes • Create subgroups within each group to further reduce links • Get rid of some of our visual enhancements
  • 12. E D G E B U N D L E D L AY O U T U S E R I N T E R A C T I O N
  • 13. E D G E B U N D L E D L AY O U T • http://bl.ocks.org/mbostock/7607999 • We added many more links • Links colored based on performance • Links sized based on volume of data flow • Mouseover should highlight connected links • Nodes sized based on volume within that node
  • 14. E D G E B U N D L E D L AY O U T — P R O B L E M S • Default behaviour is to iterate through every link on mouseover and change colour — this is slooooow! • Using CSS class to change colour causes major re- render • Quickly cycling through nodes has noticeable lag
  • 15. E D G E B U N D L E D L AY O U T — S O L U T I O N S • First we tried to not iterate, just use CSS class cascades • This was a trade off because we ended up adding a large number of classes, two per node and one per link
  • 16. E D G E B U N D L E D L AY O U T — S O L U T I O N S • The second attempt was to use CANVAS to draw everything • The problem here is that CANVAS is not great for text, and mouseovers no longer worked
  • 17. E D G E B U N D L E D L AY O U T — S O L U T I O N S • The third attempt was to use CANVAS to draw links and SVG for nodes • The biggest problem was to make sure they overlapped perfectly, ie, it was a small problem.
  • 18. C A N VA S D O E S N O T S U P P O R T B E Z I E R C U R V E S ! ! ! E X C E P T …
  • 19. D 3 W I T H C A N VA S • There are some great examples online… • https://bocoup.com/weblog/d3js-and-canvas • https://gist.github.com/mbostock/1276463 • But not quite what we wanted
  • 20. D 3 W I T H C A N VA S • Create a Custom XML NameSpace • Map dummy nodes from this namespace for each link • Each dummy node contains the SVG path required to draw the curve as well as other attributes • After all nodes have been mapped, call a renderer to convert this to CANVAS
  • 21. d3.ns.prefix.custom = "https://foo-bar.com/edge_bundling.html"; d3.select("body").append("custom:sketch") .classed("link-container", true); … linkBinding.enter() .append("custom:path") .attr("lineCap", "round") .attr("lineJoin", "round") .attr("lineWidth", .2) .attr("opacity", 0.1) .attr("selected-opacity", 0.3); linkBinding .attr("selected-lineWidth", function(d) { return weightScale(d.weight); }) .attr("d", function(d) { return line(d.path); }); C R E AT I N G N O D E S
  • 22. var pathAttrs = ["strokeStyle", "lineCap", "lineJoin", "lineWidth"]; ctx.beginPath(); pathAttrs.forEach(function(a) { var val = node.attr(selected + a) || node.attr(a); if(a === "strokeStyle") { var color = d3.rgb(val); val = "rgba(" + color.r + "," + color.g + "," + color.b + "," + node.attr(selected + "opacity") + ")"; } ctx[a] = val; }); A P P LY I N G S T Y L E S
  • 23. var path = node.attr("d"), m; while((m = path.match(/^ *([MLCQ])([d.,e-]+) */))) { var cmd = m[1]; var coords = m[2].split(",").map(pathToCoords); path = path.replace(/^ *([MLCQ])([d.,e-]+) */, ""); switch(cmd) { case "M": ctx.moveTo(coords[0], coords[1]); break; case "L": ctx.lineTo(coords[0], coords[1]); break; case "C": ctx.bezierCurveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]); break; case "Q": ctx.quadraticCurveTo(coords[0], coords[1], coords[2], coords[3]); break; } } D R A W I N G C U R V E S
  • 24. B U T I T S T I L L WA S N ’ T FA S T E N O U G H !
  • 25. E N H A N C E M E N T S • Use 2 CANVAS elements, • one to hold the background (ie, all links), • the second to show the currently selected links • Change opacity on the background to darken it • If mouse pointer returns to last selected node, just redisplay
  • 26. S U M M A RY • Number of DOM nodes is very significant • Reduce calculations on in-memory objects • Show approximate data, based on available pixels and power • Use CANVAS when mouse interaction is not required • Cache repeated states rather than redrawing them