From c095d51147909746f664966aaab8d1cbdbd0b464 Mon Sep 17 00:00:00 2001 From: holtzy Date: Fri, 27 Sep 2024 09:00:43 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20holtzy/r?= =?UTF-8?q?eact-graph-gallery@2d7563f90662192280fdaa76374885f1d9b527b2=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2d-density-plot.html | 4 +- 404.html | 4 +- .../_buildManifest.js | 2 +- .../_ssgManifest.js | 0 _next/static/chunks/3710-42861fd98b0c9a93.js | 1 - _next/static/chunks/3710-79d628355a0771e6.js | 1 + ...js => axis-variations-e8cf5bd8282a7c5f.js} | 2 +- ...99.js => axis-with-d3-1a6cdc32ad8e4d5a.js} | 2 +- .../introduction-to-react-5bacb05304b527fe.js | 1 + .../introduction-to-react-bee9ba8b631896a0.js | 1 - about.html | 4 +- all.html | 4 +- animation.html | 4 +- arc-diagram.html | 4 +- area-plot.html | 4 +- articles.html | 4 +- barplot.html | 4 +- boxplot.html | 4 +- bubble-map.html | 4 +- bubble-plot.html | 4 +- build-axis-with-react.html | 4 +- cartogram.html | 4 +- chord-diagram.html | 4 +- choropleth-map.html | 4 +- circular-barplot.html | 6 +- circular-packing.html | 4 +- connected-scatter-plot.html | 4 +- connection-map.html | 4 +- correlogram.html | 4 +- course/axis/axis-variations.html | 2 +- course/axis/axis-with-d3.html | 18 +- course/axis/bottom-axis.html | 4 +- course/axis/introduction.html | 2 +- course/axis/margin-and-translation.html | 4 +- .../hover-effect/css-descendant-selector.html | 4 +- course/hover-effect/css-pseudo-class.html | 4 +- course/hover-effect/internal-state.html | 4 +- course/hover-effect/introduction.html | 2 +- course/hover-effect/link-two-graphs.html | 4 +- course/hover-effect/toggle-class-in-js.html | 4 +- course/introduction/initial-setup.html | 2 +- course/introduction/introduction-to-d3.html | 2 +- .../introduction/introduction-to-react.html | 2 +- course/introduction/js-dataviz-libraries.html | 2 +- course/responsiveness/code-organization.html | 4 +- course/responsiveness/common-pitfalls.html | 2 +- course/responsiveness/introduction.html | 4 +- course/responsiveness/use-dimension-hook.html | 4 +- course/responsiveness/using-the-hook.html | 4 +- course/scales/introduction.html | 4 +- course/svg/introduction.html | 2 +- course/svg/main-svg-elements.html | 2 +- course/svg/path-element.html | 4 +- course/svg/tips-and-tricks.html | 2 +- cross-graph-highlight-interaction.html | 4 +- dataset-transition.html | 4 +- dendrogram.html | 4 +- density-plot.html | 4 +- donut.html | 4 +- example/arc-diagram-vertical.html | 4 +- .../barplot-data-transition-animation.html | 4 +- example/barplot-stacked-horizontal.html | 4 +- example/barplot-stacked-vertical.html | 4 +- example/boxplot-horizontal.html | 4 +- example/boxplot-jitter.html | 4 +- example/circle-packing-with-d3-force.html | 4 +- example/histogram-mirror.html | 4 +- example/histogram-small-multiple.html | 4 +- example/histogram-with-several-groups.html | 4 +- example/line-chart-synchronized-cursors.html | 4 +- .../network-diagram-with-colored-groups.html | 4 +- example/population-pyramid.html | 2 +- example/radar-chart-animation.html | 4 +- example/scatterplot-basic-canvas.html | 4 +- ...h-voronoi-for-closest-point-detection.html | 4 +- example/timeseries-moving-average.html | 4 +- fix-canvas-blurry-dataviz.html | 4 +- heatmap.html | 8 +- hexbin-map.html | 4 +- hierarchical-edge-bundling.html | 4 +- histogram.html | 6 +- img/js-lib-download-npm-trend.png | Bin 0 -> 103754 bytes img/react-website.png | Bin 0 -> 40328 bytes index.html | 4 +- interactivity.html | 4 +- line-chart.html | 4 +- lollipop-plot.html | 4 +- map.html | 4 +- network-chart.html | 4 +- parallel-plot.html | 4 +- pie-plot.html | 4 +- radar-chart.html | 4 +- react-d3-dataviz-course.html | 4 +- ...t-dataviz-animation-with-react-spring.html | 4 +- ridgeline.html | 4 +- sankey-diagram.html | 4 +- scatter-plot.html | 4 +- shape-morphism-for-dataviz-with-react.html | 4 +- sitemap.xml | 198 +++++++++--------- stacked-area-plot.html | 4 +- stacked-barplot-with-negative-values.html | 4 +- streamchart.html | 4 +- subscribe.html | 4 +- timeseries.html | 4 +- treemap.html | 4 +- typescript-d3-axis.html | 4 +- violin-plot.html | 6 +- viz-from-the-future.html | 4 +- voronoi.html | 4 +- what-is-a-color.html | 4 +- wordcloud.html | 4 +- 111 files changed, 312 insertions(+), 296 deletions(-) rename _next/static/{p3FATxv5KXzSVq1_ZIBgo => bC-NdMGULUAHiDorv_1gq}/_buildManifest.js (51%) rename _next/static/{p3FATxv5KXzSVq1_ZIBgo => bC-NdMGULUAHiDorv_1gq}/_ssgManifest.js (100%) delete mode 100644 _next/static/chunks/3710-42861fd98b0c9a93.js create mode 100644 _next/static/chunks/3710-79d628355a0771e6.js rename _next/static/chunks/pages/course/axis/{axis-variations-29684003ddc8ca1c.js => axis-variations-e8cf5bd8282a7c5f.js} (61%) rename _next/static/chunks/pages/course/axis/{axis-with-d3-c402b9adba801e99.js => axis-with-d3-1a6cdc32ad8e4d5a.js} (56%) create mode 100644 _next/static/chunks/pages/course/introduction/introduction-to-react-5bacb05304b527fe.js delete mode 100644 _next/static/chunks/pages/course/introduction/introduction-to-react-bee9ba8b631896a0.js create mode 100644 img/js-lib-download-npm-trend.png create mode 100644 img/react-website.png diff --git a/2d-density-plot.html b/2d-density-plot.html index e6dc120e..81ef6349 100644 --- a/2d-density-plot.html +++ b/2d-density-plot.html @@ -1,4 +1,4 @@ -How to build a 2d density chart with React and D3.

2d density chart

Dataviz logo representing a 2dDensity chart.

A 2D density chart is a graphical representation of data that uses color to show the concentration of data points in a given area. It shows the combined distribution of two quantitative variables. 2D density charts are often used in statistical analysis and data mining to identify trends, patterns, and correlations in the data.

In this tutorial, we will use the d3.js and React libraries to build a 2D density chart. It starts by describing how the data should be organized and how to initialize the Density2d component. It then explains how to prepare the data and compute bins. Once this is done, it shows how to render the shapes and suggests a few variations. 🙇‍♂️.

Useful links

The Data

A 2d density chart is basically a variation of the scatterplot, useful when the amount of data points is huge. As a result, it shares the same data structure.

The data is an array of object. For each object, at least 2 properties are required: x and y. The value of x is the position of the datapoint on the horizontal axis. The value of y is linked with the vertical axis.

const data = [
+How to build a 2d density chart with React and D3.

2d density chart

Dataviz logo representing a 2dDensity chart.

A 2D density chart is a graphical representation of data that uses color to show the concentration of data points in a given area. It shows the combined distribution of two quantitative variables. 2D density charts are often used in statistical analysis and data mining to identify trends, patterns, and correlations in the data.

In this tutorial, we will use the d3.js and React libraries to build a 2D density chart. It starts by describing how the data should be organized and how to initialize the Density2d component. It then explains how to prepare the data and compute bins. Once this is done, it shows how to render the shapes and suggests a few variations. 🙇‍♂️.

Useful links

The Data

A 2d density chart is basically a variation of the scatterplot, useful when the amount of data points is huge. As a result, it shares the same data structure.

The data is an array of object. For each object, at least 2 properties are required: x and y. The value of x is the position of the datapoint on the horizontal axis. The value of y is linked with the vertical axis.

const data = [
   {
     x: 2,
     y: 4
@@ -78,4 +78,4 @@
 }

I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




2D Density inspiration

If you're looking for inspiration to create your next 2D Density, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your 2D Density looks good!

visit

Variations

The hexbin representation above is just one member of a family of graphics allowing to study the combined distribution of two quantitative variables. You can read more about the existing variations in the data to viz project.

To put it in a nutshell, 2d histogram, Gaussian KDE, 2d density and Contour charts are the most common variations. It is of course possible to build them all using react and d3.js.

Here is an example with a contounr chart based on the same dataset than the previous example.


5101520

Contour chart made with React and D3.js.

ToDomake the contour chart above looks better
ToDoadd examples for 2d histograms and other variations
ToDoAdd example with a zoom feature implemented

Contact

👋 Hey, I'm Yan and I'm currently working on this project!

Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

    -
    \ No newline at end of file +
    \ No newline at end of file diff --git a/404.html b/404.html index 51609d0b..551d5b09 100644 --- a/404.html +++ b/404.html @@ -1,4 +1,4 @@ -How to build a scatter plot with React and D3.

    Oh No!

    Dataviz logo representing a ScatterPlot chart.

    It looks like the place you are looking for does not exist 🙈

    You probably want to go back to the gallery homepage!

    I'm in a good mood, so here is a chart example for you just in case you are interested in React and d3.js ☀️

    Useful links

    The countries with the highest vulnerability to climate change have the lowest CO2 emissions

    All countries sorted by their vulnerability and readiness to climate change. The size shows the CO2 emission per person in that country.

    High ReadinessLow ReadinessQatarBahrainU.S.Trinidad and TobagoCzech RepublicSingaporeNorwayIndiaSudanChadSomalia

    Reproduction of a chart originally published by Data Wrapper using react and d3.js.

    Contact

    👋 Hey, I'm Yan and I'm currently working on this project!

    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

    +How to build a scatter plot with React and D3.

    Oh No!

    Dataviz logo representing a ScatterPlot chart.

    It looks like the place you are looking for does not exist 🙈

    You probably want to go back to the gallery homepage!

    I'm in a good mood, so here is a chart example for you just in case you are interested in React and d3.js ☀️

    Useful links

    The countries with the highest vulnerability to climate change have the lowest CO2 emissions

    All countries sorted by their vulnerability and readiness to climate change. The size shows the CO2 emission per person in that country.

    High ReadinessLow ReadinessQatarBahrainU.S.Trinidad and TobagoCzech RepublicSingaporeNorwayIndiaSudanChadSomalia

    Reproduction of a chart originally published by Data Wrapper using react and d3.js.

    Contact

    👋 Hey, I'm Yan and I'm currently working on this project!

    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

      -
      \ No newline at end of file +
      \ No newline at end of file diff --git a/_next/static/p3FATxv5KXzSVq1_ZIBgo/_buildManifest.js b/_next/static/bC-NdMGULUAHiDorv_1gq/_buildManifest.js similarity index 51% rename from _next/static/p3FATxv5KXzSVq1_ZIBgo/_buildManifest.js rename to _next/static/bC-NdMGULUAHiDorv_1gq/_buildManifest.js index 9285195b..7895a430 100644 --- a/_next/static/p3FATxv5KXzSVq1_ZIBgo/_buildManifest.js +++ b/_next/static/bC-NdMGULUAHiDorv_1gq/_buildManifest.js @@ -1 +1 @@ -self.__BUILD_MANIFEST=function(s,a,e,c,t,i,o,r,n,p,d,u,l,h,b,f,g,m,k,j,v,x,w,z,y,_,I){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[s,"static/chunks/2718-c1b4ae8aebf23716.js",a,t,"static/chunks/pages/index-d41f25467ee6dcf3.js"],"/2d-density-plot":[s,e,i,o,a,c,t,v,r,"static/chunks/pages/2d-density-plot-147f90a5d8e8c593.js"],"/404":[s,e,i,a,c,t,m,"static/css/8a734e64c19c3976.css","static/chunks/pages/404-b85241062cab5048.js"],"/_error":["static/chunks/pages/_error-82b79221b9ed784b.js"],"/about":[s,e,i,a,c,t,h,"static/chunks/pages/about-3b56a821b500a5e6.js"],"/all":[s,e,a,c,t,n,f,"static/chunks/pages/all-c5ea439386fed3d0.js"],"/animation":[s,e,a,c,t,n,f,"static/chunks/pages/animation-fa9dfe1d4e131eb9.js"],"/arc-diagram":[s,e,i,o,a,c,t,n,d,"static/chunks/pages/arc-diagram-0cd124895e80ad94.js"],"/area-plot":[s,e,i,o,a,c,t,r,"static/chunks/pages/area-plot-f924661c3a9b2958.js"],"/articles":[s,e,a,c,t,h,"static/chunks/pages/articles-4f71b8e4bef1386a.js"],"/barplot":[s,e,i,o,p,a,c,t,n,k,d,"static/chunks/pages/barplot-673304709dd1fab4.js"],"/boxplot":[s,e,i,o,a,c,t,n,d,"static/chunks/pages/boxplot-82e704905eabb30a.js"],"/bubble-map":[s,e,i,o,p,a,c,t,n,g,d,"static/chunks/pages/bubble-map-485b7134a4e47eb4.js"],"/bubble-plot":[s,e,i,o,p,a,c,t,n,m,"static/css/ec7558f4d3e32e69.css","static/chunks/pages/bubble-plot-d62206987d094835.js"],"/build-axis-with-react":[s,e,i,o,a,c,t,r,"static/chunks/pages/build-axis-with-react-e547a8f59779247a.js"],"/cartogram":[s,e,a,c,t,h,"static/chunks/pages/cartogram-3909805a96300cc2.js"],"/chord-diagram":[s,e,i,o,a,c,t,r,"static/chunks/pages/chord-diagram-c630fcbbb34fadc5.js"],"/choropleth-map":[s,e,i,o,a,c,t,g,r,"static/chunks/pages/choropleth-map-36a7bf052e70cfb4.js"],"/circular-barplot":[s,e,i,o,a,c,t,r,"static/chunks/pages/circular-barplot-1aa8c2336ab3e058.js"],"/circular-packing":[s,e,i,o,p,a,c,t,n,d,"static/chunks/pages/circular-packing-a9fee065b643bd3a.js"],"/connected-scatter-plot":[s,e,i,o,a,c,t,r,"static/chunks/pages/connected-scatter-plot-846d452ea7cf227d.js"],"/connection-map":[s,e,i,o,a,c,t,g,r,"static/chunks/pages/connection-map-27b9a1c883c61e01.js"],"/correlogram":[s,e,i,o,a,c,t,"static/css/d54486714a313ae1.css","static/chunks/pages/correlogram-8c37581cff2c0f67.js"],"/course/axis/axis-variations":[s,e,a,c,l,"static/chunks/pages/course/axis/axis-variations-29684003ddc8ca1c.js"],"/course/axis/axis-with-d3":[s,e,i,o,a,c,u,"static/chunks/pages/course/axis/axis-with-d3-c402b9adba801e99.js"],"/course/axis/bottom-axis":[s,e,i,o,a,c,u,"static/chunks/pages/course/axis/bottom-axis-272ff8da119afd4c.js"],"/course/axis/introduction":[s,e,i,a,c,l,"static/chunks/pages/course/axis/introduction-cc94a936e34f47a3.js"],"/course/axis/margin-and-translation":[s,e,o,a,c,u,"static/chunks/pages/course/axis/margin-and-translation-1dd15c5814a91e12.js"],"/course/hover-effect/css-descendant-selector":[s,e,i,o,a,c,n,"static/css/8666b20defb3e011.css","static/chunks/pages/course/hover-effect/css-descendant-selector-bee614cc0a119133.js"],"/course/hover-effect/css-pseudo-class":[s,e,i,o,a,c,n,x,"static/css/69b5bd49186db9de.css","static/chunks/pages/course/hover-effect/css-pseudo-class-d62e9a8a70a63b8a.js"],"/course/hover-effect/internal-state":[s,e,i,o,a,c,n,j,"static/css/b8e43ac6f7da4f41.css","static/chunks/pages/course/hover-effect/internal-state-c530fd0159cbb1c9.js"],"/course/hover-effect/introduction":[s,e,i,p,a,c,x,"static/css/0ec73f568dde8513.css","static/chunks/pages/course/hover-effect/introduction-f55a4b3bae6d4f44.js"],"/course/hover-effect/link-two-graphs":[s,e,i,o,a,c,t,n,j,"static/css/c76003f718a0f9be.css","static/chunks/pages/course/hover-effect/link-two-graphs-73df4a48119378bb.js"],"/course/hover-effect/toggle-class-in-js":[s,e,i,o,a,c,"static/css/f5258d81ed13d0d5.css","static/chunks/pages/course/hover-effect/toggle-class-in-js-9b0499013d580797.js"],"/course/introduction/initial-setup":[s,e,a,c,l,"static/chunks/pages/course/introduction/initial-setup-9864d096096c6d74.js"],"/course/introduction/introduction-to-d3":[s,e,a,c,l,"static/chunks/pages/course/introduction/introduction-to-d3-6181d1c81df340d4.js"],"/course/introduction/introduction-to-react":[s,e,a,c,l,"static/chunks/pages/course/introduction/introduction-to-react-bee9ba8b631896a0.js"],"/course/introduction/js-dataviz-libraries":[s,e,a,c,l,"static/chunks/pages/course/introduction/js-dataviz-libraries-74c92e8842ad53dc.js"],"/course/responsiveness/code-organization":[s,e,o,a,c,u,"static/chunks/pages/course/responsiveness/code-organization-4dee38ef916f6e9b.js"],"/course/responsiveness/common-pitfalls":[s,e,a,c,l,"static/chunks/pages/course/responsiveness/common-pitfalls-b052d1cc732e6cb4.js"],"/course/responsiveness/introduction":[s,e,i,o,a,c,u,"static/chunks/pages/course/responsiveness/introduction-56eb4fa55687caf3.js"],"/course/responsiveness/use-dimension-hook":[s,e,o,a,c,u,"static/chunks/pages/course/responsiveness/use-dimension-hook-43c87ce446c179a8.js"],"/course/responsiveness/using-the-hook":[s,e,o,a,c,u,"static/chunks/pages/course/responsiveness/using-the-hook-bf478aef397c7778.js"],"/course/scales/introduction":[s,e,o,a,c,u,"static/chunks/pages/course/scales/introduction-a64b598ed70be2c3.js"],"/course/svg/introduction":[s,e,a,c,l,"static/chunks/pages/course/svg/introduction-22b600d19c2fd7b1.js"],"/course/svg/main-svg-elements":[s,e,o,w,a,c,u,"static/chunks/pages/course/svg/main-svg-elements-dbe2ca0a29bd02e7.js"],"/course/svg/path-element":[s,e,o,w,a,c,u,"static/chunks/pages/course/svg/path-element-35d32a7cf86bf3c2.js"],"/course/svg/tips-and-tricks":[s,e,"static/chunks/2860-d038ef2b7795bb05.js",a,c,l,"static/chunks/pages/course/svg/tips-and-tricks-88a63679798eac94.js"],"/cross-graph-highlight-interaction":[s,e,i,o,"static/chunks/8446-4892663fdb75b8e1.js",a,c,t,"static/css/507114ea18f6728e.css","static/chunks/pages/cross-graph-highlight-interaction-a4cacec5e5484d83.js"],"/dataset-transition":[s,e,i,o,p,a,c,t,k,r,"static/chunks/pages/dataset-transition-b4a7858906f02b49.js"],"/dendrogram":[s,e,i,o,a,c,t,z,r,"static/chunks/pages/dendrogram-c826d5b12a6b4aa4.js"],"/density-plot":[s,e,i,o,a,c,t,y,r,"static/chunks/pages/density-plot-0fd8894d1f59fa01.js"],"/donut":[s,e,i,o,p,b,a,c,t,_,"static/css/306a1a30c14677d4.css","static/chunks/pages/donut-9f07ef710315a712.js"],"/example/arc-diagram-vertical":[s,e,i,o,a,c,t,r,"static/chunks/pages/example/arc-diagram-vertical-510fec31f9d4aefe.js"],"/example/barplot-data-transition-animation":[s,e,i,o,p,a,c,t,k,r,"static/chunks/pages/example/barplot-data-transition-animation-fc8df0dba6abcc31.js"],"/example/barplot-stacked-horizontal":[s,e,i,o,a,c,t,n,d,"static/chunks/pages/example/barplot-stacked-horizontal-cc38dcf6fdc4ea69.js"],"/example/barplot-stacked-vertical":[s,e,i,a,c,t,n,f,"static/chunks/pages/example/barplot-stacked-vertical-642ee93340ed71c0.js"],"/example/boxplot-horizontal":[s,e,i,o,a,c,t,r,"static/chunks/pages/example/boxplot-horizontal-f3f4840afd5c9254.js"],"/example/boxplot-jitter":[s,e,i,o,a,c,t,r,"static/chunks/pages/example/boxplot-jitter-0c5bd9bd7102d91b.js"],"/example/circle-packing-with-d3-force":[s,e,i,o,a,c,t,r,"static/chunks/pages/example/circle-packing-with-d3-force-8e013bef41c752c8.js"],"/example/histogram-mirror":[s,e,i,o,a,c,t,r,"static/chunks/pages/example/histogram-mirror-54a46518e20f5fdf.js"],"/example/histogram-small-multiple":[s,e,i,o,a,c,t,r,"static/chunks/pages/example/histogram-small-multiple-7fcd166f8c70c891.js"],"/example/histogram-with-several-groups":[s,e,i,o,a,c,t,r,"static/chunks/pages/example/histogram-with-several-groups-65fcf3237ad480e5.js"],"/example/line-chart-synchronized-cursors":[s,e,i,o,p,a,c,t,r,"static/chunks/pages/example/line-chart-synchronized-cursors-8652c38f3204d236.js"],"/example/network-diagram-with-colored-groups":[s,e,i,o,a,c,t,r,"static/chunks/pages/example/network-diagram-with-colored-groups-64637dc93ab02c1f.js"],"/example/population-pyramid":[i,p,"static/css/d71181803328322d.css","static/chunks/pages/example/population-pyramid-67f94f5badec49bd.js"],"/example/radar-chart-animation":[s,e,i,o,p,a,c,t,r,"static/chunks/pages/example/radar-chart-animation-15a70ec580185e4b.js"],"/example/scatterplot-basic-canvas":[s,e,i,o,a,c,t,r,"static/chunks/pages/example/scatterplot-basic-canvas-e59e60397c156772.js"],"/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection":[s,e,i,o,a,c,t,r,"static/chunks/pages/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection-203d7a9d1bc1b8ef.js"],"/example/timeseries-moving-average":[s,e,i,o,a,c,t,n,"static/css/0051346e12b181a2.css","static/chunks/pages/example/timeseries-moving-average-812bda06f49b893b.js"],"/fix-canvas-blurry-dataviz":[s,e,o,a,c,t,r,"static/chunks/pages/fix-canvas-blurry-dataviz-4af0c3d36cc71b61.js"],"/heatmap":[s,e,i,o,a,c,t,"static/css/efd490e62b6b40d6.css","static/chunks/pages/heatmap-7ee0ec76c2108be6.js"],"/hexbin-map":[s,e,i,o,a,c,t,v,r,"static/chunks/pages/hexbin-map-cf918439d4f4fca5.js"],"/hierarchical-edge-bundling":[s,e,i,o,a,c,t,z,r,"static/chunks/pages/hierarchical-edge-bundling-479181149ed46c9c.js"],"/histogram":[s,e,i,o,p,a,c,t,n,d,"static/chunks/pages/histogram-66813aef02d7e800.js"],"/interactivity":[s,e,a,c,t,n,f,"static/chunks/pages/interactivity-54e994fb8fdc812d.js"],"/line-chart":[s,e,i,o,p,a,c,t,n,d,"static/chunks/pages/line-chart-a0b85a3167d15f83.js"],"/lollipop-plot":[s,e,i,o,p,a,c,t,n,"static/css/64f55f4f67c1b792.css","static/chunks/pages/lollipop-plot-6fe0f7f4f57c6fdd.js"],"/map":[s,e,i,o,a,c,t,g,r,"static/chunks/pages/map-19bb8bc3512eb38c.js"],"/network-chart":[s,e,i,o,a,c,t,n,d,"static/chunks/pages/network-chart-20eeb0eef115cf74.js"],"/parallel-plot":[s,e,i,o,a,c,t,r,"static/chunks/pages/parallel-plot-25970b16e6625e36.js"],"/pie-plot":[s,e,i,o,p,b,a,c,t,_,"static/css/7b5f8c9d016b3f7c.css","static/chunks/pages/pie-plot-90911147e22806e8.js"],"/radar-chart":[s,e,i,o,a,c,t,n,d,"static/chunks/pages/radar-chart-7f63336695bad06b.js"],"/react-d3-dataviz-course":[s,e,a,c,t,h,"static/chunks/pages/react-d3-dataviz-course-f771d9fed9984c64.js"],"/react-dataviz-animation-with-react-spring":[s,e,i,p,a,c,t,h,"static/chunks/pages/react-dataviz-animation-with-react-spring-991c78b1ba5ec831.js"],"/ridgeline":[s,e,i,o,a,c,t,n,y,d,"static/chunks/pages/ridgeline-496ccb41e3235595.js"],"/sankey-diagram":[s,e,i,o,a,c,t,r,"static/chunks/pages/sankey-diagram-dadacc5bf07b220d.js"],"/scatter-plot":[s,e,i,o,a,c,t,n,m,j,"static/css/1973cdfb43563a59.css","static/chunks/pages/scatter-plot-aac658433f84812b.js"],"/shape-morphism-for-dataviz-with-react":[s,e,i,o,p,b,a,c,t,r,"static/chunks/pages/shape-morphism-for-dataviz-with-react-c7253eef85ade9ff.js"],"/stacked-area-plot":[s,e,i,o,p,b,a,c,t,I,"static/css/c79e5809ea8fe7eb.css","static/chunks/pages/stacked-area-plot-8abcf4a980f9465b.js"],"/stacked-barplot-with-negative-values":[s,e,i,a,c,t,h,"static/chunks/pages/stacked-barplot-with-negative-values-918bd6b7a8902573.js"],"/streamchart":[s,e,i,o,p,b,a,c,t,I,"static/css/003d5c48b04543ca.css","static/chunks/pages/streamchart-80bed00e20cde110.js"],"/subscribe":[s,e,a,c,t,h,"static/chunks/pages/subscribe-cd6b3b49e0189ed1.js"],"/timeseries":[s,e,i,o,p,a,c,t,n,d,"static/chunks/pages/timeseries-700dd1034af1c2a0.js"],"/treemap":[s,e,i,o,a,c,t,"static/css/25919ae4f53719a0.css","static/chunks/pages/treemap-ae99d40681a9dfd4.js"],"/typescript-d3-axis":[s,e,i,o,a,c,t,r,"static/chunks/pages/typescript-d3-axis-55f5ab0e8153b725.js"],"/violin-plot":[s,e,i,o,a,c,t,r,"static/chunks/pages/violin-plot-5e04f2c69ac70eb5.js"],"/viz-from-the-future":[s,e,a,c,t,"static/css/8d4c0e152872e92c.css","static/chunks/pages/viz-from-the-future-49fa6f74df593093.js"],"/voronoi":[s,e,i,o,a,c,t,n,d,"static/chunks/pages/voronoi-7431c12c9500bb92.js"],"/what-is-a-color":[s,e,a,c,t,h,"static/chunks/pages/what-is-a-color-2ceba4025243af3a.js"],"/wordcloud":[s,e,i,o,a,c,t,r,"static/chunks/pages/wordcloud-f3768ea1506d7f1c.js"],sortedPages:["/","/2d-density-plot","/404","/_app","/_error","/about","/all","/animation","/arc-diagram","/area-plot","/articles","/barplot","/boxplot","/bubble-map","/bubble-plot","/build-axis-with-react","/cartogram","/chord-diagram","/choropleth-map","/circular-barplot","/circular-packing","/connected-scatter-plot","/connection-map","/correlogram","/course/axis/axis-variations","/course/axis/axis-with-d3","/course/axis/bottom-axis","/course/axis/introduction","/course/axis/margin-and-translation","/course/hover-effect/css-descendant-selector","/course/hover-effect/css-pseudo-class","/course/hover-effect/internal-state","/course/hover-effect/introduction","/course/hover-effect/link-two-graphs","/course/hover-effect/toggle-class-in-js","/course/introduction/initial-setup","/course/introduction/introduction-to-d3","/course/introduction/introduction-to-react","/course/introduction/js-dataviz-libraries","/course/responsiveness/code-organization","/course/responsiveness/common-pitfalls","/course/responsiveness/introduction","/course/responsiveness/use-dimension-hook","/course/responsiveness/using-the-hook","/course/scales/introduction","/course/svg/introduction","/course/svg/main-svg-elements","/course/svg/path-element","/course/svg/tips-and-tricks","/cross-graph-highlight-interaction","/dataset-transition","/dendrogram","/density-plot","/donut","/example/arc-diagram-vertical","/example/barplot-data-transition-animation","/example/barplot-stacked-horizontal","/example/barplot-stacked-vertical","/example/boxplot-horizontal","/example/boxplot-jitter","/example/circle-packing-with-d3-force","/example/histogram-mirror","/example/histogram-small-multiple","/example/histogram-with-several-groups","/example/line-chart-synchronized-cursors","/example/network-diagram-with-colored-groups","/example/population-pyramid","/example/radar-chart-animation","/example/scatterplot-basic-canvas","/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection","/example/timeseries-moving-average","/fix-canvas-blurry-dataviz","/heatmap","/hexbin-map","/hierarchical-edge-bundling","/histogram","/interactivity","/line-chart","/lollipop-plot","/map","/network-chart","/parallel-plot","/pie-plot","/radar-chart","/react-d3-dataviz-course","/react-dataviz-animation-with-react-spring","/ridgeline","/sankey-diagram","/scatter-plot","/shape-morphism-for-dataviz-with-react","/stacked-area-plot","/stacked-barplot-with-negative-values","/streamchart","/subscribe","/timeseries","/treemap","/typescript-d3-axis","/violin-plot","/viz-from-the-future","/voronoi","/what-is-a-color","/wordcloud"]}}("static/chunks/2343-fd77427f6d276a64.js","static/chunks/8190-bc54b059aeb5396b.js","static/chunks/7754-86d7d1d8f1f2cbb4.js","static/chunks/3710-42861fd98b0c9a93.js","static/chunks/2594-166023395f0e3eec.js","static/chunks/8657-581e9b42e1f41b29.js","static/chunks/7823-7fe55b50301cbfb1.js","static/css/3f9dc76f65000636.css","static/chunks/693-fc37b082b568d0e9.js","static/chunks/2236-19fcef54ecc4f5b6.js","static/css/bf3bc3250ab9e729.css","static/css/0fa95a85e3c094ce.css","static/css/4aaaca05e34861fe.css","static/css/2247407c30b587b7.css","static/chunks/7303-2813398c13243040.js","static/css/537902226fc25775.css","static/chunks/301-fb0066bc9a032722.js","static/chunks/814-6f6cd086489440d9.js","static/chunks/4369-3cf45ab8af8a21da.js","static/chunks/6155-0ba4f3b6f1f1f5ca.js","static/chunks/4131-4e76bf573a6a50e1.js","static/chunks/2830-adbbaa28bd9788fd.js","static/chunks/4133-cb2169106fc9e4f5.js","static/chunks/9041-b8dc7e7055ab97a1.js","static/chunks/7443-dd841eedb9d57660.js","static/chunks/7067-ad41ed7893ce1ebd.js","static/chunks/3646-bfca271cd623b31b.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); \ No newline at end of file +self.__BUILD_MANIFEST=function(s,a,c,e,t,i,o,r,n,p,d,u,l,h,b,f,g,m,k,j,v,x,w,z,y,_,I){return{__rewrites:{beforeFiles:[],afterFiles:[],fallback:[]},"/":[s,"static/chunks/2718-c1b4ae8aebf23716.js",a,t,"static/chunks/pages/index-d41f25467ee6dcf3.js"],"/2d-density-plot":[s,c,i,o,a,e,t,v,r,"static/chunks/pages/2d-density-plot-147f90a5d8e8c593.js"],"/404":[s,c,i,a,e,t,m,"static/css/8a734e64c19c3976.css","static/chunks/pages/404-b85241062cab5048.js"],"/_error":["static/chunks/pages/_error-82b79221b9ed784b.js"],"/about":[s,c,i,a,e,t,h,"static/chunks/pages/about-3b56a821b500a5e6.js"],"/all":[s,c,a,e,t,n,f,"static/chunks/pages/all-c5ea439386fed3d0.js"],"/animation":[s,c,a,e,t,n,f,"static/chunks/pages/animation-fa9dfe1d4e131eb9.js"],"/arc-diagram":[s,c,i,o,a,e,t,n,d,"static/chunks/pages/arc-diagram-0cd124895e80ad94.js"],"/area-plot":[s,c,i,o,a,e,t,r,"static/chunks/pages/area-plot-f924661c3a9b2958.js"],"/articles":[s,c,a,e,t,h,"static/chunks/pages/articles-4f71b8e4bef1386a.js"],"/barplot":[s,c,i,o,p,a,e,t,n,k,d,"static/chunks/pages/barplot-673304709dd1fab4.js"],"/boxplot":[s,c,i,o,a,e,t,n,d,"static/chunks/pages/boxplot-82e704905eabb30a.js"],"/bubble-map":[s,c,i,o,p,a,e,t,n,g,d,"static/chunks/pages/bubble-map-485b7134a4e47eb4.js"],"/bubble-plot":[s,c,i,o,p,a,e,t,n,m,"static/css/ec7558f4d3e32e69.css","static/chunks/pages/bubble-plot-d62206987d094835.js"],"/build-axis-with-react":[s,c,i,o,a,e,t,r,"static/chunks/pages/build-axis-with-react-e547a8f59779247a.js"],"/cartogram":[s,c,a,e,t,h,"static/chunks/pages/cartogram-3909805a96300cc2.js"],"/chord-diagram":[s,c,i,o,a,e,t,r,"static/chunks/pages/chord-diagram-c630fcbbb34fadc5.js"],"/choropleth-map":[s,c,i,o,a,e,t,g,r,"static/chunks/pages/choropleth-map-36a7bf052e70cfb4.js"],"/circular-barplot":[s,c,i,o,a,e,t,r,"static/chunks/pages/circular-barplot-1aa8c2336ab3e058.js"],"/circular-packing":[s,c,i,o,p,a,e,t,n,d,"static/chunks/pages/circular-packing-a9fee065b643bd3a.js"],"/connected-scatter-plot":[s,c,i,o,a,e,t,r,"static/chunks/pages/connected-scatter-plot-846d452ea7cf227d.js"],"/connection-map":[s,c,i,o,a,e,t,g,r,"static/chunks/pages/connection-map-27b9a1c883c61e01.js"],"/correlogram":[s,c,i,o,a,e,t,"static/css/d54486714a313ae1.css","static/chunks/pages/correlogram-8c37581cff2c0f67.js"],"/course/axis/axis-variations":[s,c,a,e,l,"static/chunks/pages/course/axis/axis-variations-e8cf5bd8282a7c5f.js"],"/course/axis/axis-with-d3":[s,c,i,o,a,e,u,"static/chunks/pages/course/axis/axis-with-d3-1a6cdc32ad8e4d5a.js"],"/course/axis/bottom-axis":[s,c,i,o,a,e,u,"static/chunks/pages/course/axis/bottom-axis-272ff8da119afd4c.js"],"/course/axis/introduction":[s,c,i,a,e,l,"static/chunks/pages/course/axis/introduction-cc94a936e34f47a3.js"],"/course/axis/margin-and-translation":[s,c,o,a,e,u,"static/chunks/pages/course/axis/margin-and-translation-1dd15c5814a91e12.js"],"/course/hover-effect/css-descendant-selector":[s,c,i,o,a,e,n,"static/css/8666b20defb3e011.css","static/chunks/pages/course/hover-effect/css-descendant-selector-bee614cc0a119133.js"],"/course/hover-effect/css-pseudo-class":[s,c,i,o,a,e,n,x,"static/css/69b5bd49186db9de.css","static/chunks/pages/course/hover-effect/css-pseudo-class-d62e9a8a70a63b8a.js"],"/course/hover-effect/internal-state":[s,c,i,o,a,e,n,j,"static/css/b8e43ac6f7da4f41.css","static/chunks/pages/course/hover-effect/internal-state-c530fd0159cbb1c9.js"],"/course/hover-effect/introduction":[s,c,i,p,a,e,x,"static/css/0ec73f568dde8513.css","static/chunks/pages/course/hover-effect/introduction-f55a4b3bae6d4f44.js"],"/course/hover-effect/link-two-graphs":[s,c,i,o,a,e,t,n,j,"static/css/c76003f718a0f9be.css","static/chunks/pages/course/hover-effect/link-two-graphs-73df4a48119378bb.js"],"/course/hover-effect/toggle-class-in-js":[s,c,i,o,a,e,"static/css/f5258d81ed13d0d5.css","static/chunks/pages/course/hover-effect/toggle-class-in-js-9b0499013d580797.js"],"/course/introduction/initial-setup":[s,c,a,e,l,"static/chunks/pages/course/introduction/initial-setup-9864d096096c6d74.js"],"/course/introduction/introduction-to-d3":[s,c,a,e,l,"static/chunks/pages/course/introduction/introduction-to-d3-6181d1c81df340d4.js"],"/course/introduction/introduction-to-react":[s,c,a,e,l,"static/chunks/pages/course/introduction/introduction-to-react-5bacb05304b527fe.js"],"/course/introduction/js-dataviz-libraries":[s,c,a,e,l,"static/chunks/pages/course/introduction/js-dataviz-libraries-74c92e8842ad53dc.js"],"/course/responsiveness/code-organization":[s,c,o,a,e,u,"static/chunks/pages/course/responsiveness/code-organization-4dee38ef916f6e9b.js"],"/course/responsiveness/common-pitfalls":[s,c,a,e,l,"static/chunks/pages/course/responsiveness/common-pitfalls-b052d1cc732e6cb4.js"],"/course/responsiveness/introduction":[s,c,i,o,a,e,u,"static/chunks/pages/course/responsiveness/introduction-56eb4fa55687caf3.js"],"/course/responsiveness/use-dimension-hook":[s,c,o,a,e,u,"static/chunks/pages/course/responsiveness/use-dimension-hook-43c87ce446c179a8.js"],"/course/responsiveness/using-the-hook":[s,c,o,a,e,u,"static/chunks/pages/course/responsiveness/using-the-hook-bf478aef397c7778.js"],"/course/scales/introduction":[s,c,o,a,e,u,"static/chunks/pages/course/scales/introduction-a64b598ed70be2c3.js"],"/course/svg/introduction":[s,c,a,e,l,"static/chunks/pages/course/svg/introduction-22b600d19c2fd7b1.js"],"/course/svg/main-svg-elements":[s,c,o,w,a,e,u,"static/chunks/pages/course/svg/main-svg-elements-dbe2ca0a29bd02e7.js"],"/course/svg/path-element":[s,c,o,w,a,e,u,"static/chunks/pages/course/svg/path-element-35d32a7cf86bf3c2.js"],"/course/svg/tips-and-tricks":[s,c,"static/chunks/2860-d038ef2b7795bb05.js",a,e,l,"static/chunks/pages/course/svg/tips-and-tricks-88a63679798eac94.js"],"/cross-graph-highlight-interaction":[s,c,i,o,"static/chunks/8446-4892663fdb75b8e1.js",a,e,t,"static/css/507114ea18f6728e.css","static/chunks/pages/cross-graph-highlight-interaction-a4cacec5e5484d83.js"],"/dataset-transition":[s,c,i,o,p,a,e,t,k,r,"static/chunks/pages/dataset-transition-b4a7858906f02b49.js"],"/dendrogram":[s,c,i,o,a,e,t,z,r,"static/chunks/pages/dendrogram-c826d5b12a6b4aa4.js"],"/density-plot":[s,c,i,o,a,e,t,y,r,"static/chunks/pages/density-plot-0fd8894d1f59fa01.js"],"/donut":[s,c,i,o,p,b,a,e,t,_,"static/css/306a1a30c14677d4.css","static/chunks/pages/donut-9f07ef710315a712.js"],"/example/arc-diagram-vertical":[s,c,i,o,a,e,t,r,"static/chunks/pages/example/arc-diagram-vertical-510fec31f9d4aefe.js"],"/example/barplot-data-transition-animation":[s,c,i,o,p,a,e,t,k,r,"static/chunks/pages/example/barplot-data-transition-animation-fc8df0dba6abcc31.js"],"/example/barplot-stacked-horizontal":[s,c,i,o,a,e,t,n,d,"static/chunks/pages/example/barplot-stacked-horizontal-cc38dcf6fdc4ea69.js"],"/example/barplot-stacked-vertical":[s,c,i,a,e,t,n,f,"static/chunks/pages/example/barplot-stacked-vertical-642ee93340ed71c0.js"],"/example/boxplot-horizontal":[s,c,i,o,a,e,t,r,"static/chunks/pages/example/boxplot-horizontal-f3f4840afd5c9254.js"],"/example/boxplot-jitter":[s,c,i,o,a,e,t,r,"static/chunks/pages/example/boxplot-jitter-0c5bd9bd7102d91b.js"],"/example/circle-packing-with-d3-force":[s,c,i,o,a,e,t,r,"static/chunks/pages/example/circle-packing-with-d3-force-8e013bef41c752c8.js"],"/example/histogram-mirror":[s,c,i,o,a,e,t,r,"static/chunks/pages/example/histogram-mirror-54a46518e20f5fdf.js"],"/example/histogram-small-multiple":[s,c,i,o,a,e,t,r,"static/chunks/pages/example/histogram-small-multiple-7fcd166f8c70c891.js"],"/example/histogram-with-several-groups":[s,c,i,o,a,e,t,r,"static/chunks/pages/example/histogram-with-several-groups-65fcf3237ad480e5.js"],"/example/line-chart-synchronized-cursors":[s,c,i,o,p,a,e,t,r,"static/chunks/pages/example/line-chart-synchronized-cursors-8652c38f3204d236.js"],"/example/network-diagram-with-colored-groups":[s,c,i,o,a,e,t,r,"static/chunks/pages/example/network-diagram-with-colored-groups-64637dc93ab02c1f.js"],"/example/population-pyramid":[i,p,"static/css/d71181803328322d.css","static/chunks/pages/example/population-pyramid-67f94f5badec49bd.js"],"/example/radar-chart-animation":[s,c,i,o,p,a,e,t,r,"static/chunks/pages/example/radar-chart-animation-15a70ec580185e4b.js"],"/example/scatterplot-basic-canvas":[s,c,i,o,a,e,t,r,"static/chunks/pages/example/scatterplot-basic-canvas-e59e60397c156772.js"],"/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection":[s,c,i,o,a,e,t,r,"static/chunks/pages/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection-203d7a9d1bc1b8ef.js"],"/example/timeseries-moving-average":[s,c,i,o,a,e,t,n,"static/css/0051346e12b181a2.css","static/chunks/pages/example/timeseries-moving-average-812bda06f49b893b.js"],"/fix-canvas-blurry-dataviz":[s,c,o,a,e,t,r,"static/chunks/pages/fix-canvas-blurry-dataviz-4af0c3d36cc71b61.js"],"/heatmap":[s,c,i,o,a,e,t,"static/css/efd490e62b6b40d6.css","static/chunks/pages/heatmap-7ee0ec76c2108be6.js"],"/hexbin-map":[s,c,i,o,a,e,t,v,r,"static/chunks/pages/hexbin-map-cf918439d4f4fca5.js"],"/hierarchical-edge-bundling":[s,c,i,o,a,e,t,z,r,"static/chunks/pages/hierarchical-edge-bundling-479181149ed46c9c.js"],"/histogram":[s,c,i,o,p,a,e,t,n,d,"static/chunks/pages/histogram-66813aef02d7e800.js"],"/interactivity":[s,c,a,e,t,n,f,"static/chunks/pages/interactivity-54e994fb8fdc812d.js"],"/line-chart":[s,c,i,o,p,a,e,t,n,d,"static/chunks/pages/line-chart-a0b85a3167d15f83.js"],"/lollipop-plot":[s,c,i,o,p,a,e,t,n,"static/css/64f55f4f67c1b792.css","static/chunks/pages/lollipop-plot-6fe0f7f4f57c6fdd.js"],"/map":[s,c,i,o,a,e,t,g,r,"static/chunks/pages/map-19bb8bc3512eb38c.js"],"/network-chart":[s,c,i,o,a,e,t,n,d,"static/chunks/pages/network-chart-20eeb0eef115cf74.js"],"/parallel-plot":[s,c,i,o,a,e,t,r,"static/chunks/pages/parallel-plot-25970b16e6625e36.js"],"/pie-plot":[s,c,i,o,p,b,a,e,t,_,"static/css/7b5f8c9d016b3f7c.css","static/chunks/pages/pie-plot-90911147e22806e8.js"],"/radar-chart":[s,c,i,o,a,e,t,n,d,"static/chunks/pages/radar-chart-7f63336695bad06b.js"],"/react-d3-dataviz-course":[s,c,a,e,t,h,"static/chunks/pages/react-d3-dataviz-course-f771d9fed9984c64.js"],"/react-dataviz-animation-with-react-spring":[s,c,i,p,a,e,t,h,"static/chunks/pages/react-dataviz-animation-with-react-spring-991c78b1ba5ec831.js"],"/ridgeline":[s,c,i,o,a,e,t,n,y,d,"static/chunks/pages/ridgeline-496ccb41e3235595.js"],"/sankey-diagram":[s,c,i,o,a,e,t,r,"static/chunks/pages/sankey-diagram-dadacc5bf07b220d.js"],"/scatter-plot":[s,c,i,o,a,e,t,n,m,j,"static/css/1973cdfb43563a59.css","static/chunks/pages/scatter-plot-aac658433f84812b.js"],"/shape-morphism-for-dataviz-with-react":[s,c,i,o,p,b,a,e,t,r,"static/chunks/pages/shape-morphism-for-dataviz-with-react-c7253eef85ade9ff.js"],"/stacked-area-plot":[s,c,i,o,p,b,a,e,t,I,"static/css/c79e5809ea8fe7eb.css","static/chunks/pages/stacked-area-plot-8abcf4a980f9465b.js"],"/stacked-barplot-with-negative-values":[s,c,i,a,e,t,h,"static/chunks/pages/stacked-barplot-with-negative-values-918bd6b7a8902573.js"],"/streamchart":[s,c,i,o,p,b,a,e,t,I,"static/css/003d5c48b04543ca.css","static/chunks/pages/streamchart-80bed00e20cde110.js"],"/subscribe":[s,c,a,e,t,h,"static/chunks/pages/subscribe-cd6b3b49e0189ed1.js"],"/timeseries":[s,c,i,o,p,a,e,t,n,d,"static/chunks/pages/timeseries-700dd1034af1c2a0.js"],"/treemap":[s,c,i,o,a,e,t,"static/css/25919ae4f53719a0.css","static/chunks/pages/treemap-ae99d40681a9dfd4.js"],"/typescript-d3-axis":[s,c,i,o,a,e,t,r,"static/chunks/pages/typescript-d3-axis-55f5ab0e8153b725.js"],"/violin-plot":[s,c,i,o,a,e,t,r,"static/chunks/pages/violin-plot-5e04f2c69ac70eb5.js"],"/viz-from-the-future":[s,c,a,e,t,"static/css/8d4c0e152872e92c.css","static/chunks/pages/viz-from-the-future-49fa6f74df593093.js"],"/voronoi":[s,c,i,o,a,e,t,n,d,"static/chunks/pages/voronoi-7431c12c9500bb92.js"],"/what-is-a-color":[s,c,a,e,t,h,"static/chunks/pages/what-is-a-color-2ceba4025243af3a.js"],"/wordcloud":[s,c,i,o,a,e,t,r,"static/chunks/pages/wordcloud-f3768ea1506d7f1c.js"],sortedPages:["/","/2d-density-plot","/404","/_app","/_error","/about","/all","/animation","/arc-diagram","/area-plot","/articles","/barplot","/boxplot","/bubble-map","/bubble-plot","/build-axis-with-react","/cartogram","/chord-diagram","/choropleth-map","/circular-barplot","/circular-packing","/connected-scatter-plot","/connection-map","/correlogram","/course/axis/axis-variations","/course/axis/axis-with-d3","/course/axis/bottom-axis","/course/axis/introduction","/course/axis/margin-and-translation","/course/hover-effect/css-descendant-selector","/course/hover-effect/css-pseudo-class","/course/hover-effect/internal-state","/course/hover-effect/introduction","/course/hover-effect/link-two-graphs","/course/hover-effect/toggle-class-in-js","/course/introduction/initial-setup","/course/introduction/introduction-to-d3","/course/introduction/introduction-to-react","/course/introduction/js-dataviz-libraries","/course/responsiveness/code-organization","/course/responsiveness/common-pitfalls","/course/responsiveness/introduction","/course/responsiveness/use-dimension-hook","/course/responsiveness/using-the-hook","/course/scales/introduction","/course/svg/introduction","/course/svg/main-svg-elements","/course/svg/path-element","/course/svg/tips-and-tricks","/cross-graph-highlight-interaction","/dataset-transition","/dendrogram","/density-plot","/donut","/example/arc-diagram-vertical","/example/barplot-data-transition-animation","/example/barplot-stacked-horizontal","/example/barplot-stacked-vertical","/example/boxplot-horizontal","/example/boxplot-jitter","/example/circle-packing-with-d3-force","/example/histogram-mirror","/example/histogram-small-multiple","/example/histogram-with-several-groups","/example/line-chart-synchronized-cursors","/example/network-diagram-with-colored-groups","/example/population-pyramid","/example/radar-chart-animation","/example/scatterplot-basic-canvas","/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection","/example/timeseries-moving-average","/fix-canvas-blurry-dataviz","/heatmap","/hexbin-map","/hierarchical-edge-bundling","/histogram","/interactivity","/line-chart","/lollipop-plot","/map","/network-chart","/parallel-plot","/pie-plot","/radar-chart","/react-d3-dataviz-course","/react-dataviz-animation-with-react-spring","/ridgeline","/sankey-diagram","/scatter-plot","/shape-morphism-for-dataviz-with-react","/stacked-area-plot","/stacked-barplot-with-negative-values","/streamchart","/subscribe","/timeseries","/treemap","/typescript-d3-axis","/violin-plot","/viz-from-the-future","/voronoi","/what-is-a-color","/wordcloud"]}}("static/chunks/2343-fd77427f6d276a64.js","static/chunks/8190-bc54b059aeb5396b.js","static/chunks/7754-86d7d1d8f1f2cbb4.js","static/chunks/3710-79d628355a0771e6.js","static/chunks/2594-166023395f0e3eec.js","static/chunks/8657-581e9b42e1f41b29.js","static/chunks/7823-7fe55b50301cbfb1.js","static/css/3f9dc76f65000636.css","static/chunks/693-fc37b082b568d0e9.js","static/chunks/2236-19fcef54ecc4f5b6.js","static/css/bf3bc3250ab9e729.css","static/css/0fa95a85e3c094ce.css","static/css/4aaaca05e34861fe.css","static/css/2247407c30b587b7.css","static/chunks/7303-2813398c13243040.js","static/css/537902226fc25775.css","static/chunks/301-fb0066bc9a032722.js","static/chunks/814-6f6cd086489440d9.js","static/chunks/4369-3cf45ab8af8a21da.js","static/chunks/6155-0ba4f3b6f1f1f5ca.js","static/chunks/4131-4e76bf573a6a50e1.js","static/chunks/2830-adbbaa28bd9788fd.js","static/chunks/4133-cb2169106fc9e4f5.js","static/chunks/9041-b8dc7e7055ab97a1.js","static/chunks/7443-dd841eedb9d57660.js","static/chunks/7067-ad41ed7893ce1ebd.js","static/chunks/3646-bfca271cd623b31b.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB(); \ No newline at end of file diff --git a/_next/static/p3FATxv5KXzSVq1_ZIBgo/_ssgManifest.js b/_next/static/bC-NdMGULUAHiDorv_1gq/_ssgManifest.js similarity index 100% rename from _next/static/p3FATxv5KXzSVq1_ZIBgo/_ssgManifest.js rename to _next/static/bC-NdMGULUAHiDorv_1gq/_ssgManifest.js diff --git a/_next/static/chunks/3710-42861fd98b0c9a93.js b/_next/static/chunks/3710-42861fd98b0c9a93.js deleted file mode 100644 index 14bd554d..00000000 --- a/_next/static/chunks/3710-42861fd98b0c9a93.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3710],{26865:function(e,t,a){"use strict";a.d(t,{y:function(){return i}});var s=a(85893),n=a(8117);let i=e=>{let{lessonStatus:t}=e;return"free"===t?(0,s.jsx)(n.C,{variant:"outlineGreen",className:"font-extralight opacity-90",children:"Free"}):"wip"===t?(0,s.jsx)(n.C,{variant:"outlineOrange",className:"font-extralight opacity-90",children:"Wip"}):"membersOnly"===t?(0,s.jsx)(n.C,{className:"font-extralight opacity-90",children:"Members Only"}):"not available"===t?(0,s.jsx)(n.C,{variant:"outlineDestructive",className:"font-extralight opacity-90",children:"Unavail."}):null}},56438:function(e,t,a){"use strict";a.d(t,{J:function(){return r}});var s=a(85893),n=a(41664),i=a.n(n);let r=e=>{let{children:t,href:a,isFilled:n,size:r="md",isFaded:o}=e,d=a.startsWith("www")||a.startsWith("http"),l="font-normal rounded mr-1 cursor-pointer border-reactGallery border ";n?l+=" bg-reactGallery hover:bg-reactGallery text-white ":l+=" bg-white hover:bg-reactGallery hover:text-white text-reactGallery ","sm"===r&&(l+="text-sm py-1 px-2 "),"md"===r&&(l+="text-md py-2 px-4 "),o&&(l+="opacity-60");let c=(0,s.jsx)("span",{className:l,children:t});return d?(0,s.jsx)("a",{href:a,target:"_blank",children:c}):(0,s.jsx)(i(),{href:a,passHref:!0,children:c})}},43710:function(e,t,a){"use strict";a.d(t,{Z:function(){return H}});var s=a(85893),n=a(67294),i=a(28843),r=a(77522),o=a(61859),d=a(56438),l=a(21832),c=a.n(l);let m=e=>{let{direction:t,text:a,children:n}=e;return(0,s.jsx)("span",{className:c().tooltip+" "+c()[t],id:a,children:n})};var h=a(95887),u=a(26865),p=a(88426),x=a(64998);a(9404);let f=n.forwardRef((e,t)=>{let{...a}=e;return(0,s.jsx)("nav",{ref:t,"aria-label":"breadcrumb",...a})});f.displayName="Breadcrumb";let g=n.forwardRef((e,t)=>{let{className:a,...n}=e;return(0,s.jsx)("ol",{ref:t,className:(0,r.cn)("flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",a),...n})});g.displayName="BreadcrumbList";let j=n.forwardRef((e,t)=>{let{className:a,...n}=e;return(0,s.jsx)("li",{ref:t,className:(0,r.cn)("inline-flex items-center gap-1.5",a),...n})});j.displayName="BreadcrumbItem";let v=n.forwardRef((e,t)=>{let{asChild:a,className:n,...i}=e,o=a?p.g7:"a";return(0,s.jsx)(o,{ref:t,className:(0,r.cn)("transition-colors hover:text-foreground",n),...i})});v.displayName="BreadcrumbLink";let w=n.forwardRef((e,t)=>{let{className:a,...n}=e;return(0,s.jsx)("span",{ref:t,role:"link","aria-disabled":"true","aria-current":"page",className:(0,r.cn)("font-normal text-foreground",a),...n})});w.displayName="BreadcrumbPage";let b=e=>{let{children:t,className:a,...n}=e;return(0,s.jsx)("li",{role:"presentation","aria-hidden":"true",className:(0,r.cn)("[&>svg]:size-3.5",a),...n,children:null!=t?t:(0,s.jsx)(x.Z,{})})};b.displayName="BreadcrumbSeparator";var y=a(93133),k=a(13742),N=a(50316);let F=y.fC,I=y.xz;y.ZA;let T=y.Uv,z=y.Tr;y.Ee;let S=n.forwardRef((e,t)=>{let{className:a,inset:n,children:i,...o}=e;return(0,s.jsxs)(y.fF,{ref:t,className:(0,r.cn)("flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",n&&"pl-8",a),...o,children:[i,(0,s.jsx)(x.Z,{className:"ml-auto h-4 w-4"})]})});S.displayName=y.fF.displayName;let C=n.forwardRef((e,t)=>{let{className:a,...n}=e;return(0,s.jsx)(y.tu,{ref:t,className:(0,r.cn)("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",a),...n})});C.displayName=y.tu.displayName;let L=n.forwardRef((e,t)=>{let{className:a,sideOffset:n=4,...i}=e;return(0,s.jsx)(y.Uv,{children:(0,s.jsx)(y.VY,{ref:t,sideOffset:n,className:(0,r.cn)("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",a),...i})})});L.displayName=y.VY.displayName;let R=n.forwardRef((e,t)=>{let{className:a,inset:n,...i}=e;return(0,s.jsx)(y.ck,{ref:t,className:(0,r.cn)("relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",n&&"pl-8",a),...i})});R.displayName=y.ck.displayName;let _=n.forwardRef((e,t)=>{let{className:a,children:n,checked:i,...o}=e;return(0,s.jsxs)(y.oC,{ref:t,className:(0,r.cn)("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",a),checked:i,...o,children:[(0,s.jsx)("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:(0,s.jsx)(y.wU,{children:(0,s.jsx)(k.Z,{className:"h-4 w-4"})})}),n]})});_.displayName=y.oC.displayName;let G=n.forwardRef((e,t)=>{let{className:a,children:n,...i}=e;return(0,s.jsxs)(y.Rk,{ref:t,className:(0,r.cn)("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",a),...i,children:[(0,s.jsx)("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:(0,s.jsx)(y.wU,{children:(0,s.jsx)(N.Z,{className:"h-2 w-2 fill-current"})})}),n]})});G.displayName=y.Rk.displayName;let B=n.forwardRef((e,t)=>{let{className:a,inset:n,...i}=e;return(0,s.jsx)(y.__,{ref:t,className:(0,r.cn)("px-2 py-1.5 text-sm font-semibold",n&&"pl-8",a),...i})});B.displayName=y.__.displayName;let V=n.forwardRef((e,t)=>{let{className:a,...n}=e;return(0,s.jsx)(y.Z0,{ref:t,className:(0,r.cn)("-mx-1 my-1 h-px bg-muted",a),...n})});V.displayName=y.Z0.displayName;var W=a(5),A=a(89181),D=a(11236),U=a(41664),Y=a.n(U);let Z=e=>{let{selectedLesson:t}=e,a=t.moduleId,n=A.F.find(e=>e.id===a);return n?(0,s.jsx)(f,{children:(0,s.jsxs)(g,{children:[(0,s.jsx)(j,{children:(0,s.jsx)(v,{href:"/react-d3-dataviz-course",className:(0,W.d)({variant:"outline",size:"sm"})+" no-underline text-xs border-gray-200 h-8 text-gray-500",children:"Course"})}),(0,s.jsx)(b,{}),(0,s.jsx)(j,{children:(0,s.jsxs)(F,{children:[(0,s.jsx)(I,{asChild:!0,children:(0,s.jsx)(W.z,{variant:"outline",size:"sm",className:"text-xs border-gray-200 h-8",children:n.name})}),(0,s.jsx)(L,{children:A.F.map((e,n)=>(0,s.jsxs)(z,{children:[(0,s.jsxs)(S,{children:[(0,s.jsx)(N.Z,{fill:"black",size:8,className:"mr-2",opacity:e.id===a?1:0}),(0,s.jsx)("span",{children:e.name})]}),(0,s.jsx)(T,{children:(0,s.jsx)(C,{children:D.Y.filter(t=>t.moduleId===e.id).map((e,a)=>(0,s.jsx)(Y(),{className:"no-underline text-black",href:e.link,children:(0,s.jsxs)(R,{children:[(0,s.jsx)(N.Z,{fill:"black",size:8,className:"mr-2",opacity:e.name===t.name?1:0}),(0,s.jsx)("span",{children:e.name})]})},a))})})]},n))})]})}),(0,s.jsx)(b,{}),(0,s.jsx)(j,{children:(0,s.jsxs)(F,{children:[(0,s.jsx)(I,{asChild:!0,children:(0,s.jsx)(W.z,{variant:"outline",size:"sm",className:"text-xs border-gray-200 h-8",children:t.name})}),(0,s.jsx)(L,{children:D.Y.filter(e=>e.moduleId===a).map((e,a)=>(0,s.jsx)(Y(),{className:"no-underline text-black",href:e.link,children:(0,s.jsxs)(R,{className:"flex justify-between gap-4",children:[(0,s.jsxs)("div",{className:"flex items-center",children:[(0,s.jsx)(N.Z,{fill:"black",size:8,className:"mr-2",opacity:e.name===t.name?1:0}),e.name]}),(0,s.jsx)(u.y,{lessonStatus:e.status})]})},a))})]})})]})}):null};function H(e){let{title:t,description:a,chartType:n,showSectionLink:l=!1,showInspirationLink:c=!0,showD3GalleryLink:p=!0,lessonStatus:x,readTime:f,selectedLesson:g}=e,j=i.c.find(e=>e.id===n);return(0,s.jsxs)("div",{className:"w-full pt-1 sm:pt-28 pb-20 ",children:[g&&(0,s.jsx)("div",{className:"mb-4",children:(0,s.jsx)(Z,{selectedLesson:g})}),(0,s.jsxs)("div",{className:"flex justify-start items-center",children:[(0,s.jsx)("h1",{children:t}),n&&j&&(0,s.jsx)("div",{className:"w-20 ml-4",children:(0,s.jsx)(h.Z,{chartLogo:null==j?void 0:j.logo})})]}),(0,s.jsx)(o.r,{}),(0,s.jsx)("div",{className:"max-w-xxl py-2",children:a}),n&&(0,s.jsx)("span",{className:"text-gray-400 text-sm font-light",children:"Useful links"}),j&&(0,s.jsxs)("div",{className:"flex flex-row flex-wrap",children:[l&&(0,s.jsx)(m,{text:"visit related section in the gallery",direction:"bottom",children:(0,s.jsx)(d.J,{href:(0,r.y)(j.reactURL),size:"sm",children:j.label+" section"})}),c&&(0,s.jsx)(m,{text:"Hundreds of stunning dataviz projects to gather inspiration",direction:"bottom",children:(0,s.jsx)(d.J,{href:"https://www.dataviz-inspiration.com/"+j.id,size:"sm",children:"inspiration"})}),p&&(0,s.jsx)(m,{text:"Pure d3 implementation, no React",direction:"bottom",children:(0,s.jsx)(d.J,{href:j.d3URL,size:"sm",children:"d3 gallery"})}),(0,s.jsx)(m,{text:"Dataviz theory about this chart",direction:"bottom",children:(0,s.jsx)(d.J,{href:j.dataToVizURL,isFilled:!0,size:"sm",children:"About this chart"})})]}),x&&f&&(0,s.jsxs)("div",{className:"flex flex-row items-center flex-wrap gap-2",children:[(0,s.jsx)(u.y,{lessonStatus:x}),(0,s.jsx)("span",{className:"text-xs",children:f+" minutes read"})]})]})}},8117:function(e,t,a){"use strict";a.d(t,{C:function(){return o}});var s=a(85893);a(67294);var n=a(45139),i=a(77522);let r=(0,n.j)("inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",secondary:"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",destructive:"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",outline:"text-foreground",outlineDestructive:"text-xs text-destructive border-destructive",outlineGreen:"text-xs text-green-500 border-green-500",outlineOrange:"text-xs text-orange-500 border-orange-500"}},defaultVariants:{variant:"default"}});function o(e){let{className:t,variant:a,...n}=e;return(0,s.jsx)("div",{className:(0,i.cn)(r({variant:a}),t),...n})}},5:function(e,t,a){"use strict";a.d(t,{d:function(){return d},z:function(){return l}});var s=a(85893),n=a(67294),i=a(88426),r=a(45139),o=a(77522);let d=(0,r.j)("inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",{variants:{variant:{default:"bg-primary text-primary-foreground hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground hover:bg-destructive/90",outline:"border border-input bg-background hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-10 px-4 py-2",sm:"h-9 rounded-md px-3",lg:"h-11 rounded-md px-8",icon:"h-10 w-10"}},defaultVariants:{variant:"default",size:"default"}}),l=n.forwardRef((e,t)=>{let{className:a,variant:n,size:r,asChild:l=!1,...c}=e,m=l?i.g7:"button";return(0,s.jsx)(m,{className:(0,o.cn)(d({variant:n,size:r,className:a})),ref:t,...c})});l.displayName="Button"},11236:function(e,t,a){"use strict";a.d(t,{Y:function(){return n}});var s=a(85893);let n=[{name:"What is react",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"React is the most widely used javascript library when it comes to building user interfaces."})}),readTime:4,link:"/course/introduction/introduction-to-react",status:"wip",moduleId:"introduction"},{name:"Chart libraries: don't",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Why it will make you save time at the beginning, but is a bad idea on the long run"})}),readTime:4,link:"/course/introduction/js-dataviz-libraries",status:"wip",moduleId:"introduction"},{name:"What is d3",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"React is the most widely used javascript library when it comes to building user interfaces."})}),readTime:4,link:"/course/introduction/introduction-to-d3",status:"wip",moduleId:"introduction"},{name:"Initial setup",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Be ready to build graph in 10 seconds."})}),readTime:4,link:"/course/introduction/initial-setup",status:"wip",moduleId:"introduction"},{name:"Introduction to svg",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"SVG stands for vector graphic. Let's see why it is useful and widespread in dataviz."})}),readTime:4,link:"/course/svg/introduction",status:"free",moduleId:"svg"},{name:"Main SVG elements",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Let's learn how to draw the basic SVG shapes: circle, rectangles, segment and text."})}),readTime:4,link:"/course/svg/main-svg-elements",status:"free",moduleId:"svg"},{name:"The path element",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"path is the most complicated yet most useful svg element."})}),readTime:4,link:"/course/svg/path-element",status:"free",moduleId:"svg"},{name:"SVG tips & tricks",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"path is the most complicated yet most useful svg element."})}),readTime:4,link:"/course/svg/tips-and-tricks",status:"wip",moduleId:"svg"},{name:"Introduction to scales",description:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("p",{children:"Thanks to SVG we now know how to build any shape anywhere on the screen. But we do not want to draw theme anywhere."}),(0,s.jsx)("p",{children:"We want to draw them on a spot determined by data. And we need a scale for this."})]}),readTime:4,link:"/course/scales/introduction",status:"wip",moduleId:"scales"},{name:"Linear Scales",description:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("p",{children:"Thanks to SVG we now know how to build any shape anywhere on the screen. But we do not want to draw theme anywhere."}),(0,s.jsx)("p",{children:"We want to draw them on a spot determined by data. And we need a scale for this."})]}),readTime:4,link:"/course/scales/linear-scale",status:"wip",moduleId:"scales"},{name:"Other scale types",description:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("p",{children:"Thanks to SVG we now know how to build any shape anywhere on the screen. But we do not want to draw theme anywhere."}),(0,s.jsx)("p",{children:"We want to draw them on a spot determined by data. And we need a scale for this."})]}),readTime:4,link:"/course/scales/other-scale-types",status:"wip",moduleId:"scales"},{name:"Introduction",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"How to add margins around the chart withouth the headache"})}),readTime:4,link:"/course/axis/introduction",status:"wip",moduleId:"axis"},{name:"Margin and translation",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"How to add margins around the chart withouth the headache"})}),readTime:4,link:"/course/axis/margin-and-translation",status:"wip",moduleId:"axis"},{name:"Build a bottom axis",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Let's learn how to build a bottom axis component"})}),readTime:4,link:"/course/axis/bottom-axis",status:"not available",moduleId:"axis"},{name:"Axis component variations",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Bottom axis? Axis with grids? Axis title? Let's see how to create those variations."})}),readTime:4,link:"/course/axis/axis-variations",status:"not available",moduleId:"axis"},{name:"Alternative: use d3 helper",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"D3 has some great functions to draw the axes. I do not recommend it, but you can use them!"})}),readTime:4,link:"/course/axis/axis-with-d3",status:"not available",moduleId:"axis"},{name:"Introduction to responsiveness",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Learn the basics of what responsiveness means and why it is crucial for creating dynamic charts."})}),readTime:4,link:"/course/responsiveness/introduction",status:"free",moduleId:"responsiveness"},{name:"Creating a useDimensions Hook",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Discover how to create a custom hook that listens for changes in dimensions, a key component for responsive charts."})}),readTime:4,link:"/course/responsiveness/use-dimension-hook",status:"wip",moduleId:"responsiveness"},{name:"Integrating the Hook with Your Graph",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Learn how to pass the results of the useDimensions hook to your graph components to make them fully responsive."})}),readTime:4,link:"/course/responsiveness/using-the-hook",status:"wip",moduleId:"responsiveness"},{name:"Best Practices for Code Organization",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Explore suggested ways to organize your code when working with responsive charts in React and D3."})}),readTime:4,link:"/course/responsiveness/code-organization",status:"wip",moduleId:"responsiveness"},{name:"Common Pitfalls and How to Avoid Them",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Identify common issues you might face when implementing responsive charts and learn strategies to overcome them."})}),readTime:4,link:"/course/responsiveness/common-pitfalls",status:"wip",moduleId:"responsiveness"},{name:"What is it?",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"What's an hover effect? Why is it important? How to make it look good?"})}),readTime:3,link:"/course/hover-effect/introduction",status:"free",moduleId:"hover effect"},{name:"Strategy 1: CSS pseudo element",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"First simple but weak strategy using css pseudo element. Good for performance, but weak in term of design."})}),readTime:4,link:"/course/hover-effect/css-pseudo-class",status:"free",moduleId:"hover effect"},{name:"Strategy 2: CSS descendant selector",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"With smart usage of css descending selectors, you can start creating good looking hover effects."})}),readTime:4,link:"/course/hover-effect/css-descendant-selector",status:"wip",moduleId:"hover effect"},{name:"Strategy 3: toggle css classes",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"With smart usage of css descending selectors, you can start creating good looking hover effects."})}),readTime:4,link:"/course/hover-effect/toggle-class-in-js",status:"wip",moduleId:"hover effect"},{name:"Strategy 4: react internal state",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Perfect to build complicated UIs, but mind the performances!"})}),readTime:4,link:"/course/hover-effect/internal-state",status:"wip",moduleId:"hover effect"},{name:"Design consideration",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Before coding, let's check what a tooltip is, when it can be useful, and how to make it look good."})}),readTime:4,link:"/course/responsiveness/introduction",status:"not available",moduleId:"tooltip"},{name:"Tooltip component",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Let's create a tooltip component"})}),readTime:4,link:"",status:"not available",moduleId:"tooltip"},{name:"Display on hover",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Now, let's displays the tooltip only on hover, at the right position."})}),readTime:4,link:"",status:"not available",moduleId:"tooltip"},{name:"Templates",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Several tooltip template components ready to be used in your graph."})}),readTime:4,link:"",status:"not available",moduleId:"tooltip"},{name:"Do you really need a legend?",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Check the few alternatives that exist instead of using a legend"})}),readTime:4,link:"",status:"not available",moduleId:"legend"},{name:"Categoric legend",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Check the few alternatives that exist instead of using a legend"})}),readTime:4,link:"",status:"not available",moduleId:"legend"},{name:"Continuous legend",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Check the few alternatives that exist instead of using a legend"})}),readTime:4,link:"",status:"not available",moduleId:"legend"},{name:"local JSON file",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Be ready to build graph in 10 seconds."})}),readTime:4,link:"",status:"not available",moduleId:"reading-data"},{name:"local csv file",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Be ready to build graph in 10 seconds."})}),readTime:4,link:"",status:"not available",moduleId:"reading-data"},{name:"data fetching",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Be ready to build graph in 10 seconds."})}),readTime:4,link:"",status:"not available",moduleId:"reading-data"},{name:"spinner for data loading",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Be ready to build graph in 10 seconds."})}),readTime:4,link:"",status:"not available",moduleId:"reading-data"},{name:"What's a spring animation",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"There are 2 big families of animation. Let's understand why spring animations are more natural."})}),readTime:4,link:"",status:"not available",moduleId:"animation"},{name:"Most simple: animating a circle",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Let's try to make the most simple animation with react-spring. Just a circle that moves from right to left."})}),readTime:4,link:"",status:"not available",moduleId:"animation"},{name:"Application on a scatterplot",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Now, let's create a reusable circle component that we can use to animate a scatterplot transition."})}),readTime:4,link:"",status:"not available",moduleId:"animation"},{name:"Enter, Update, Exit",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Let's see how to deal with shapes that appear, move and leave the graph."})}),readTime:4,link:"",status:"not available",moduleId:"animation"},{name:"What is it, and why is it useful?",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Canvas is the alternative to SVG to increase performance. This lesson explains what is it and why it's faster."})}),readTime:4,link:"",status:"not available",moduleId:"canvas"},{name:"Draw basic shapes",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"A quick intro to drawing circles, rectangles, lines, paths and any shape you need."})}),readTime:4,link:"",status:"not available",moduleId:"canvas"},{name:"Tooltip",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"You don't draw the tooltip in canvas. Let's see how to mix layers to use the best of both worlds and display a tooltip."})}),readTime:4,link:"",status:"not available",moduleId:"canvas"},{name:"Hover effect",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Let's use a little trick for a nice hover effect: using 2 canvas layers: one for the normal state, one for the hovered state."})}),readTime:4,link:"",status:"not available",moduleId:"canvas"}]},89181:function(e,t,a){"use strict";a.d(t,{F:function(){return n}});var s=a(85893);let n=[{id:"introduction",name:"Introduction",description:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("p",{children:["While you're likely familiar with React, you might not know that D3 is the ",(0,s.jsx)("b",{children:"essential JavaScript library"})," for data visualization."]}),(0,s.jsxs)("p",{children:["This module provides a quick overview of the ",(0,s.jsx)("b",{children:"tools needed"})," to create great charts in a browser."]})]})},{id:"svg",name:"SVG",description:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("p",{children:"A graph is basically a compendium of shapes drawn on a screen."}),(0,s.jsx)("p",{children:"The most common way to draw shapes in a browser is to use SVG. Let's learn the essential of what SVG is, step by step."})]})},{id:"scales",name:"Scales",description:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("p",{children:"Your svg area goes from 0 to 500px. Your data goes from 0 to 100. If the value of a data point is 30, where should you draw it?"}),(0,s.jsx)("p",{children:"You need a scale to find out."})]})},{id:"axis",name:"Axes",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Now that we know how to add shapes on the graph, it is time to add context to it. Let's see how to draw axes."})})},{id:"responsiveness",name:"Responsiveness",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Some people have big monitors when others will read your work on their phone. Let's see how to make your graph look good in any situation."})})},{id:"hover effect",name:"Hover effect",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"You want something to happen when a graph element is hovered. This module dives into several strategies using CSS and Javascript. It provides a clear mental modal of the main use cases and how to deal with each of them."})})},{id:"tooltip",name:"Tooltip",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Let's check how to add a tooltip. Give a tooltip definition. Give several tooltip component starters."})})},{id:"reading-data",name:"Reading data",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Your data can be a json file or a tabular format. It can be hosted locally or available through an API. How can you read it?"})})},{id:"legend",name:"Legend",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsx)("p",{children:"Those little legends are often small, but as complicated to build as the main graph. This module provides a few ready to use legend components."})})},{id:"animation",name:"Animation",description:(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)("p",{children:["Let's dig into those smooth dataset transition that make the viz magical. It's challenging, but ",(0,s.jsx)("code",{children:"react-spring"})," is of great help here."]})})},{id:"canvas",name:"Canvas",description:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("p",{children:"With thousands of shapes on your graph, using SVG will make your graph slow."}),(0,s.jsx)("p",{children:"Canvas is an alternative way to draw on a screen. Much more performant, but harder to deal with."})]})}]},21832:function(e){e.exports={tooltip:"tooltip_tooltip__b_kg5",right:"tooltip_right__zvLDU",left:"tooltip_left__mQ0Xf",bottom:"tooltip_bottom__MVFNa",top:"tooltip_top__kPfp4"}}}]); \ No newline at end of file diff --git a/_next/static/chunks/3710-79d628355a0771e6.js b/_next/static/chunks/3710-79d628355a0771e6.js new file mode 100644 index 00000000..7b728f9d --- /dev/null +++ b/_next/static/chunks/3710-79d628355a0771e6.js @@ -0,0 +1 @@ +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3710],{26865:function(e,t,s){"use strict";s.d(t,{y:function(){return i}});var a=s(85893),n=s(8117);let i=e=>{let{lessonStatus:t}=e;return"free"===t?(0,a.jsx)(n.C,{variant:"outlineGreen",className:"font-extralight opacity-90",children:"Free"}):"wip"===t?(0,a.jsx)(n.C,{variant:"outlineOrange",className:"font-extralight opacity-90",children:"Wip"}):"membersOnly"===t?(0,a.jsx)(n.C,{className:"font-extralight opacity-90",children:"Members Only"}):"not available"===t?(0,a.jsx)(n.C,{variant:"outlineDestructive",className:"font-extralight opacity-90",children:"Unavail."}):null}},56438:function(e,t,s){"use strict";s.d(t,{J:function(){return r}});var a=s(85893),n=s(41664),i=s.n(n);let r=e=>{let{children:t,href:s,isFilled:n,size:r="md",isFaded:o}=e,d=s.startsWith("www")||s.startsWith("http"),l="font-normal rounded mr-1 cursor-pointer border-reactGallery border ";n?l+=" bg-reactGallery hover:bg-reactGallery text-white ":l+=" bg-white hover:bg-reactGallery hover:text-white text-reactGallery ","sm"===r&&(l+="text-sm py-1 px-2 "),"md"===r&&(l+="text-md py-2 px-4 "),o&&(l+="opacity-60");let c=(0,a.jsx)("span",{className:l,children:t});return d?(0,a.jsx)("a",{href:s,target:"_blank",children:c}):(0,a.jsx)(i(),{href:s,passHref:!0,children:c})}},43710:function(e,t,s){"use strict";s.d(t,{Z:function(){return H}});var a=s(85893),n=s(67294),i=s(28843),r=s(77522),o=s(61859),d=s(56438),l=s(21832),c=s.n(l);let m=e=>{let{direction:t,text:s,children:n}=e;return(0,a.jsx)("span",{className:c().tooltip+" "+c()[t],id:s,children:n})};var h=s(95887),u=s(26865),p=s(88426),x=s(64998);s(9404);let f=n.forwardRef((e,t)=>{let{...s}=e;return(0,a.jsx)("nav",{ref:t,"aria-label":"breadcrumb",...s})});f.displayName="Breadcrumb";let g=n.forwardRef((e,t)=>{let{className:s,...n}=e;return(0,a.jsx)("ol",{ref:t,className:(0,r.cn)("flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",s),...n})});g.displayName="BreadcrumbList";let j=n.forwardRef((e,t)=>{let{className:s,...n}=e;return(0,a.jsx)("li",{ref:t,className:(0,r.cn)("inline-flex items-center gap-1.5",s),...n})});j.displayName="BreadcrumbItem";let v=n.forwardRef((e,t)=>{let{asChild:s,className:n,...i}=e,o=s?p.g7:"a";return(0,a.jsx)(o,{ref:t,className:(0,r.cn)("transition-colors hover:text-foreground",n),...i})});v.displayName="BreadcrumbLink";let w=n.forwardRef((e,t)=>{let{className:s,...n}=e;return(0,a.jsx)("span",{ref:t,role:"link","aria-disabled":"true","aria-current":"page",className:(0,r.cn)("font-normal text-foreground",s),...n})});w.displayName="BreadcrumbPage";let b=e=>{let{children:t,className:s,...n}=e;return(0,a.jsx)("li",{role:"presentation","aria-hidden":"true",className:(0,r.cn)("[&>svg]:size-3.5",s),...n,children:null!=t?t:(0,a.jsx)(x.Z,{})})};b.displayName="BreadcrumbSeparator";var y=s(93133),k=s(13742),N=s(50316);let F=y.fC,I=y.xz;y.ZA;let T=y.Uv,z=y.Tr;y.Ee;let S=n.forwardRef((e,t)=>{let{className:s,inset:n,children:i,...o}=e;return(0,a.jsxs)(y.fF,{ref:t,className:(0,r.cn)("flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",n&&"pl-8",s),...o,children:[i,(0,a.jsx)(x.Z,{className:"ml-auto h-4 w-4"})]})});S.displayName=y.fF.displayName;let C=n.forwardRef((e,t)=>{let{className:s,...n}=e;return(0,a.jsx)(y.tu,{ref:t,className:(0,r.cn)("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",s),...n})});C.displayName=y.tu.displayName;let L=n.forwardRef((e,t)=>{let{className:s,sideOffset:n=4,...i}=e;return(0,a.jsx)(y.Uv,{children:(0,a.jsx)(y.VY,{ref:t,sideOffset:n,className:(0,r.cn)("z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",s),...i})})});L.displayName=y.VY.displayName;let R=n.forwardRef((e,t)=>{let{className:s,inset:n,...i}=e;return(0,a.jsx)(y.ck,{ref:t,className:(0,r.cn)("relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",n&&"pl-8",s),...i})});R.displayName=y.ck.displayName;let _=n.forwardRef((e,t)=>{let{className:s,children:n,checked:i,...o}=e;return(0,a.jsxs)(y.oC,{ref:t,className:(0,r.cn)("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",s),checked:i,...o,children:[(0,a.jsx)("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:(0,a.jsx)(y.wU,{children:(0,a.jsx)(k.Z,{className:"h-4 w-4"})})}),n]})});_.displayName=y.oC.displayName;let G=n.forwardRef((e,t)=>{let{className:s,children:n,...i}=e;return(0,a.jsxs)(y.Rk,{ref:t,className:(0,r.cn)("relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",s),...i,children:[(0,a.jsx)("span",{className:"absolute left-2 flex h-3.5 w-3.5 items-center justify-center",children:(0,a.jsx)(y.wU,{children:(0,a.jsx)(N.Z,{className:"h-2 w-2 fill-current"})})}),n]})});G.displayName=y.Rk.displayName;let B=n.forwardRef((e,t)=>{let{className:s,inset:n,...i}=e;return(0,a.jsx)(y.__,{ref:t,className:(0,r.cn)("px-2 py-1.5 text-sm font-semibold",n&&"pl-8",s),...i})});B.displayName=y.__.displayName;let V=n.forwardRef((e,t)=>{let{className:s,...n}=e;return(0,a.jsx)(y.Z0,{ref:t,className:(0,r.cn)("-mx-1 my-1 h-px bg-muted",s),...n})});V.displayName=y.Z0.displayName;var W=s(5),A=s(89181),D=s(11236),U=s(41664),Y=s.n(U);let Z=e=>{let{selectedLesson:t}=e,s=t.moduleId,n=A.F.find(e=>e.id===s);return n?(0,a.jsx)(f,{children:(0,a.jsxs)(g,{children:[(0,a.jsx)(j,{children:(0,a.jsx)(v,{href:"/react-d3-dataviz-course",className:(0,W.d)({variant:"outline",size:"sm"})+" no-underline text-xs border-gray-200 h-8 text-gray-500",children:"Course"})}),(0,a.jsx)(b,{}),(0,a.jsx)(j,{children:(0,a.jsxs)(F,{children:[(0,a.jsx)(I,{asChild:!0,children:(0,a.jsx)(W.z,{variant:"outline",size:"sm",className:"text-xs border-gray-200 h-8",children:n.name})}),(0,a.jsx)(L,{children:A.F.map((e,n)=>(0,a.jsxs)(z,{children:[(0,a.jsxs)(S,{children:[(0,a.jsx)(N.Z,{fill:"black",size:8,className:"mr-2",opacity:e.id===s?1:0}),(0,a.jsx)("span",{children:e.name})]}),(0,a.jsx)(T,{children:(0,a.jsx)(C,{children:D.Y.filter(t=>t.moduleId===e.id).map((e,s)=>(0,a.jsx)(Y(),{className:"no-underline text-black",href:e.link,children:(0,a.jsxs)(R,{children:[(0,a.jsx)(N.Z,{fill:"black",size:8,className:"mr-2",opacity:e.name===t.name?1:0}),(0,a.jsx)("span",{children:e.name})]})},s))})})]},n))})]})}),(0,a.jsx)(b,{}),(0,a.jsx)(j,{children:(0,a.jsxs)(F,{children:[(0,a.jsx)(I,{asChild:!0,children:(0,a.jsx)(W.z,{variant:"outline",size:"sm",className:"text-xs border-gray-200 h-8",children:t.name})}),(0,a.jsx)(L,{children:D.Y.filter(e=>e.moduleId===s).map((e,s)=>(0,a.jsx)(Y(),{className:"no-underline text-black",href:e.link,children:(0,a.jsxs)(R,{className:"flex justify-between gap-4",children:[(0,a.jsxs)("div",{className:"flex items-center",children:[(0,a.jsx)(N.Z,{fill:"black",size:8,className:"mr-2",opacity:e.name===t.name?1:0}),e.name]}),(0,a.jsx)(u.y,{lessonStatus:e.status})]})},s))})]})})]})}):null};function H(e){let{title:t,description:s,chartType:n,showSectionLink:l=!1,showInspirationLink:c=!0,showD3GalleryLink:p=!0,lessonStatus:x,readTime:f,selectedLesson:g}=e,j=i.c.find(e=>e.id===n);return(0,a.jsxs)("div",{className:"w-full pt-1 sm:pt-28 pb-20 ",children:[g&&(0,a.jsx)("div",{className:"mb-4",children:(0,a.jsx)(Z,{selectedLesson:g})}),(0,a.jsxs)("div",{className:"flex justify-start items-center",children:[(0,a.jsx)("h1",{children:t}),n&&j&&(0,a.jsx)("div",{className:"w-20 ml-4",children:(0,a.jsx)(h.Z,{chartLogo:null==j?void 0:j.logo})})]}),(0,a.jsx)(o.r,{}),(0,a.jsx)("div",{className:"max-w-xxl py-2",children:s}),n&&(0,a.jsx)("span",{className:"text-gray-400 text-sm font-light",children:"Useful links"}),j&&(0,a.jsxs)("div",{className:"flex flex-row flex-wrap",children:[l&&(0,a.jsx)(m,{text:"visit related section in the gallery",direction:"bottom",children:(0,a.jsx)(d.J,{href:(0,r.y)(j.reactURL),size:"sm",children:j.label+" section"})}),c&&(0,a.jsx)(m,{text:"Hundreds of stunning dataviz projects to gather inspiration",direction:"bottom",children:(0,a.jsx)(d.J,{href:"https://www.dataviz-inspiration.com/"+j.id,size:"sm",children:"inspiration"})}),p&&(0,a.jsx)(m,{text:"Pure d3 implementation, no React",direction:"bottom",children:(0,a.jsx)(d.J,{href:j.d3URL,size:"sm",children:"d3 gallery"})}),(0,a.jsx)(m,{text:"Dataviz theory about this chart",direction:"bottom",children:(0,a.jsx)(d.J,{href:j.dataToVizURL,isFilled:!0,size:"sm",children:"About this chart"})})]}),x&&f&&(0,a.jsxs)("div",{className:"flex flex-row items-center flex-wrap gap-2",children:[(0,a.jsx)(u.y,{lessonStatus:x}),(0,a.jsx)("span",{className:"text-xs",children:f+" minutes read"})]})]})}},8117:function(e,t,s){"use strict";s.d(t,{C:function(){return o}});var a=s(85893);s(67294);var n=s(45139),i=s(77522);let r=(0,n.j)("inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",{variants:{variant:{default:"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",secondary:"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",destructive:"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",outline:"text-foreground",outlineDestructive:"text-xs text-destructive border-destructive",outlineGreen:"text-xs text-green-500 border-green-500",outlineOrange:"text-xs text-orange-500 border-orange-500"}},defaultVariants:{variant:"default"}});function o(e){let{className:t,variant:s,...n}=e;return(0,a.jsx)("div",{className:(0,i.cn)(r({variant:s}),t),...n})}},5:function(e,t,s){"use strict";s.d(t,{d:function(){return d},z:function(){return l}});var a=s(85893),n=s(67294),i=s(88426),r=s(45139),o=s(77522);let d=(0,r.j)("inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",{variants:{variant:{default:"bg-primary text-primary-foreground hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground hover:bg-destructive/90",outline:"border border-input bg-background hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-10 px-4 py-2",sm:"h-9 rounded-md px-3",lg:"h-11 rounded-md px-8",icon:"h-10 w-10"}},defaultVariants:{variant:"default",size:"default"}}),l=n.forwardRef((e,t)=>{let{className:s,variant:n,size:r,asChild:l=!1,...c}=e,m=l?i.g7:"button";return(0,a.jsx)(m,{className:(0,o.cn)(d({variant:n,size:r,className:s})),ref:t,...c})});l.displayName="Button"},11236:function(e,t,s){"use strict";s.d(t,{Y:function(){return n}});var a=s(85893);let n=[{name:"What is react",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"React is the most widely used javascript library when it comes to building user interfaces."})}),readTime:4,link:"/course/introduction/introduction-to-react",status:"wip",moduleId:"introduction"},{name:"Chart libraries: don't",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Why it will make you save time at the beginning, but is a bad idea on the long run"})}),readTime:4,link:"/course/introduction/js-dataviz-libraries",status:"wip",moduleId:"introduction"},{name:"What is d3",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"React is the most widely used javascript library when it comes to building user interfaces."})}),readTime:4,link:"/course/introduction/introduction-to-d3",status:"wip",moduleId:"introduction"},{name:"Initial setup",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Be ready to build graph in 10 seconds."})}),readTime:4,link:"/course/introduction/initial-setup",status:"wip",moduleId:"introduction"},{name:"Introduction to svg",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"SVG stands for vector graphic. Let's see why it is useful and widespread in dataviz."})}),readTime:4,link:"/course/svg/introduction",status:"free",moduleId:"svg"},{name:"Main SVG elements",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Let's learn how to draw the basic SVG shapes: circle, rectangles, segment and text."})}),readTime:4,link:"/course/svg/main-svg-elements",status:"free",moduleId:"svg"},{name:"The path element",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"path is the most complicated yet most useful svg element."})}),readTime:4,link:"/course/svg/path-element",status:"free",moduleId:"svg"},{name:"SVG tips & tricks",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"path is the most complicated yet most useful svg element."})}),readTime:4,link:"/course/svg/tips-and-tricks",status:"wip",moduleId:"svg"},{name:"Introduction to scales",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("p",{children:"Thanks to SVG we now know how to build any shape anywhere on the screen. But we do not want to draw theme anywhere."}),(0,a.jsx)("p",{children:"We want to draw them on a spot determined by data. And we need a scale for this."})]}),readTime:4,link:"/course/scales/introduction",status:"wip",moduleId:"scales"},{name:"Linear Scales",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("p",{children:"Thanks to SVG we now know how to build any shape anywhere on the screen. But we do not want to draw theme anywhere."}),(0,a.jsx)("p",{children:"We want to draw them on a spot determined by data. And we need a scale for this."})]}),readTime:4,link:"/course/scales/linear-scale",status:"wip",moduleId:"scales"},{name:"Other scale types",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("p",{children:"Thanks to SVG we now know how to build any shape anywhere on the screen. But we do not want to draw theme anywhere."}),(0,a.jsx)("p",{children:"We want to draw them on a spot determined by data. And we need a scale for this."})]}),readTime:4,link:"/course/scales/other-scale-types",status:"wip",moduleId:"scales"},{name:"Introduction",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"How to add margins around the chart withouth the headache"})}),readTime:4,link:"/course/axis/introduction",status:"wip",moduleId:"axis"},{name:"Margin and translation",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"How to add margins around the chart withouth the headache"})}),readTime:4,link:"/course/axis/margin-and-translation",status:"wip",moduleId:"axis"},{name:"Build a bottom axis",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Let's learn how to build a bottom axis component"})}),readTime:4,link:"/course/axis/bottom-axis",status:"wip",moduleId:"axis"},{name:"Axis component variations",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Bottom axis? Axis with grids? Axis title? Let's see how to create those variations."})}),readTime:4,link:"/course/axis/axis-variations",status:"wip",moduleId:"axis"},{name:"Alternative: use d3 helper",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"D3 has some great functions to draw the axes. I do not recommend it, but you can use them!"})}),readTime:4,link:"/course/axis/axis-with-d3",status:"wip",moduleId:"axis"},{name:"Introduction to responsiveness",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Learn the basics of what responsiveness means and why it is crucial for creating dynamic charts."})}),readTime:4,link:"/course/responsiveness/introduction",status:"free",moduleId:"responsiveness"},{name:"Creating a useDimensions Hook",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Discover how to create a custom hook that listens for changes in dimensions, a key component for responsive charts."})}),readTime:4,link:"/course/responsiveness/use-dimension-hook",status:"wip",moduleId:"responsiveness"},{name:"Integrating the Hook with Your Graph",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Learn how to pass the results of the useDimensions hook to your graph components to make them fully responsive."})}),readTime:4,link:"/course/responsiveness/using-the-hook",status:"wip",moduleId:"responsiveness"},{name:"Best Practices for Code Organization",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Explore suggested ways to organize your code when working with responsive charts in React and D3."})}),readTime:4,link:"/course/responsiveness/code-organization",status:"wip",moduleId:"responsiveness"},{name:"Common Pitfalls and How to Avoid Them",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Identify common issues you might face when implementing responsive charts and learn strategies to overcome them."})}),readTime:4,link:"/course/responsiveness/common-pitfalls",status:"wip",moduleId:"responsiveness"},{name:"What is it?",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"What's an hover effect? Why is it important? How to make it look good?"})}),readTime:3,link:"/course/hover-effect/introduction",status:"free",moduleId:"hover effect"},{name:"Strategy 1: CSS pseudo element",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"First simple but weak strategy using css pseudo element. Good for performance, but weak in term of design."})}),readTime:4,link:"/course/hover-effect/css-pseudo-class",status:"free",moduleId:"hover effect"},{name:"Strategy 2: CSS descendant selector",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"With smart usage of css descending selectors, you can start creating good looking hover effects."})}),readTime:4,link:"/course/hover-effect/css-descendant-selector",status:"wip",moduleId:"hover effect"},{name:"Strategy 3: toggle css classes",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"With smart usage of css descending selectors, you can start creating good looking hover effects."})}),readTime:4,link:"/course/hover-effect/toggle-class-in-js",status:"wip",moduleId:"hover effect"},{name:"Strategy 4: react internal state",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Perfect to build complicated UIs, but mind the performances!"})}),readTime:4,link:"/course/hover-effect/internal-state",status:"wip",moduleId:"hover effect"},{name:"Design consideration",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Before coding, let's check what a tooltip is, when it can be useful, and how to make it look good."})}),readTime:4,link:"/course/responsiveness/introduction",status:"not available",moduleId:"tooltip"},{name:"Tooltip component",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Let's create a tooltip component"})}),readTime:4,link:"",status:"not available",moduleId:"tooltip"},{name:"Display on hover",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Now, let's displays the tooltip only on hover, at the right position."})}),readTime:4,link:"",status:"not available",moduleId:"tooltip"},{name:"Templates",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Several tooltip template components ready to be used in your graph."})}),readTime:4,link:"",status:"not available",moduleId:"tooltip"},{name:"Do you really need a legend?",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Check the few alternatives that exist instead of using a legend"})}),readTime:4,link:"",status:"not available",moduleId:"legend"},{name:"Categoric legend",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Check the few alternatives that exist instead of using a legend"})}),readTime:4,link:"",status:"not available",moduleId:"legend"},{name:"Continuous legend",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Check the few alternatives that exist instead of using a legend"})}),readTime:4,link:"",status:"not available",moduleId:"legend"},{name:"local JSON file",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Be ready to build graph in 10 seconds."})}),readTime:4,link:"",status:"not available",moduleId:"reading-data"},{name:"local csv file",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Be ready to build graph in 10 seconds."})}),readTime:4,link:"",status:"not available",moduleId:"reading-data"},{name:"data fetching",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Be ready to build graph in 10 seconds."})}),readTime:4,link:"",status:"not available",moduleId:"reading-data"},{name:"spinner for data loading",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Be ready to build graph in 10 seconds."})}),readTime:4,link:"",status:"not available",moduleId:"reading-data"},{name:"What's a spring animation",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"There are 2 big families of animation. Let's understand why spring animations are more natural."})}),readTime:4,link:"",status:"not available",moduleId:"animation"},{name:"Most simple: animating a circle",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Let's try to make the most simple animation with react-spring. Just a circle that moves from right to left."})}),readTime:4,link:"",status:"not available",moduleId:"animation"},{name:"Application on a scatterplot",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Now, let's create a reusable circle component that we can use to animate a scatterplot transition."})}),readTime:4,link:"",status:"not available",moduleId:"animation"},{name:"Enter, Update, Exit",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Let's see how to deal with shapes that appear, move and leave the graph."})}),readTime:4,link:"",status:"not available",moduleId:"animation"},{name:"What is it, and why is it useful?",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Canvas is the alternative to SVG to increase performance. This lesson explains what is it and why it's faster."})}),readTime:4,link:"",status:"not available",moduleId:"canvas"},{name:"Draw basic shapes",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"A quick intro to drawing circles, rectangles, lines, paths and any shape you need."})}),readTime:4,link:"",status:"not available",moduleId:"canvas"},{name:"Tooltip",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"You don't draw the tooltip in canvas. Let's see how to mix layers to use the best of both worlds and display a tooltip."})}),readTime:4,link:"",status:"not available",moduleId:"canvas"},{name:"Hover effect",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Let's use a little trick for a nice hover effect: using 2 canvas layers: one for the normal state, one for the hovered state."})}),readTime:4,link:"",status:"not available",moduleId:"canvas"}]},89181:function(e,t,s){"use strict";s.d(t,{F:function(){return n}});var a=s(85893);let n=[{id:"introduction",name:"Introduction",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("p",{children:["While you're likely familiar with React, you might not know that D3 is the ",(0,a.jsx)("b",{children:"essential JavaScript library"})," for data visualization."]}),(0,a.jsxs)("p",{children:["This module provides a quick overview of the ",(0,a.jsx)("b",{children:"tools needed"})," to create great charts in a browser."]})]})},{id:"svg",name:"SVG",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("p",{children:"A graph is basically a compendium of shapes drawn on a screen."}),(0,a.jsx)("p",{children:"The most common way to draw shapes in a browser is to use SVG. Let's learn the essential of what SVG is, step by step."})]})},{id:"scales",name:"Scales",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("p",{children:"Your svg area goes from 0 to 500px. Your data goes from 0 to 100. If the value of a data point is 30, where should you draw it?"}),(0,a.jsx)("p",{children:"You need a scale to find out."})]})},{id:"axis",name:"Axes",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Now that we know how to add shapes on the graph, it is time to add context to it. Let's see how to draw axes."})})},{id:"responsiveness",name:"Responsiveness",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Some people have big monitors when others will read your work on their phone. Let's see how to make your graph look good in any situation."})})},{id:"hover effect",name:"Hover effect",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"You want something to happen when a graph element is hovered. This module dives into several strategies using CSS and Javascript. It provides a clear mental modal of the main use cases and how to deal with each of them."})})},{id:"tooltip",name:"Tooltip",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Let's check how to add a tooltip. Give a tooltip definition. Give several tooltip component starters."})})},{id:"reading-data",name:"Reading data",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Your data can be a json file or a tabular format. It can be hosted locally or available through an API. How can you read it?"})})},{id:"legend",name:"Legend",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{children:"Those little legends are often small, but as complicated to build as the main graph. This module provides a few ready to use legend components."})})},{id:"animation",name:"Animation",description:(0,a.jsx)(a.Fragment,{children:(0,a.jsxs)("p",{children:["Let's dig into those smooth dataset transition that make the viz magical. It's challenging, but ",(0,a.jsx)("code",{children:"react-spring"})," is of great help here."]})})},{id:"canvas",name:"Canvas",description:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("p",{children:"With thousands of shapes on your graph, using SVG will make your graph slow."}),(0,a.jsx)("p",{children:"Canvas is an alternative way to draw on a screen. Much more performant, but harder to deal with."})]})}]},21832:function(e){e.exports={tooltip:"tooltip_tooltip__b_kg5",right:"tooltip_right__zvLDU",left:"tooltip_left__mQ0Xf",bottom:"tooltip_bottom__MVFNa",top:"tooltip_top__kPfp4"}}}]); \ No newline at end of file diff --git a/_next/static/chunks/pages/course/axis/axis-variations-29684003ddc8ca1c.js b/_next/static/chunks/pages/course/axis/axis-variations-e8cf5bd8282a7c5f.js similarity index 61% rename from _next/static/chunks/pages/course/axis/axis-variations-29684003ddc8ca1c.js rename to _next/static/chunks/pages/course/axis/axis-variations-e8cf5bd8282a7c5f.js index f43f3581..5e3121a8 100644 --- a/_next/static/chunks/pages/course/axis/axis-variations-29684003ddc8ca1c.js +++ b/_next/static/chunks/pages/course/axis/axis-variations-e8cf5bd8282a7c5f.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3269],{34737:function(e,s,t){(window.__NEXT_P=window.__NEXT_P||[]).push(["/course/axis/axis-variations",function(){return t(54294)}])},41843:function(e,s,t){"use strict";t.d(s,{p:function(){return o}});var i=t(85893),n=t(49700),r=t(63476),a=t(17414),l=t(41664),c=t.n(l);let o=e=>{let{children:s,title:t,seoDescription:l,previousTocItem:o,nextTocItem:d}=e;return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(a.A,{title:t,seoDescription:l}),(0,i.jsx)(n.Z,{}),(0,i.jsx)("div",{className:"wrapper",children:s}),(0,i.jsxs)("div",{className:"flex justify-center items-center space-x-6 my-24 py-12 bg-muted/50",children:[o?(0,i.jsxs)(c(),{href:o.link,className:"text-gray-500 no-underline flex flex-col justify-start items-end w-96 h-32 border-r border-black p-8 hover:bg-muted ",children:[(0,i.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l to-fuchsia-300 from-blue-400 bg-clip-text",children:"← Previous"}),(0,i.jsx)("p",{children:o.name})]}):(0,i.jsx)("div",{className:"w-96"}),d&&(0,i.jsxs)(c(),{href:d.link,className:"text-gray-500 no-underline flex flex-col justify-start w-96 h-32 border-l border-black p-8 hover:bg-muted ",children:[(0,i.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l from-fuchsia-300 to-blue-400 bg-clip-text",children:"Next →"}),(0,i.jsx)("p",{children:d.name})]})]}),(0,i.jsx)("div",{className:"wrapper",children:(0,i.jsx)(r.Z,{})})]})}},54294:function(e,s,t){"use strict";t.r(s),t.d(s,{default:function(){return l}});var i=t(85893);t(67294);var n=t(43710),r=t(41843),a=t(11236);function l(){let e=a.Y.find(e=>"/course/axis/axis-variations"===e.link);return e?(0,i.jsxs)(r.p,{title:e.name,seoDescription:"",nextTocItem:a.Y.find(e=>"/course/axis/axis-with-d3"===e.link),previousTocItem:a.Y.find(e=>"/course/axis/bottom-axis"===e.link),children:[(0,i.jsx)(n.Z,{title:e.name,lessonStatus:e.status,readTime:e.readTime,selectedLesson:e,description:(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("p",{children:"In the previous lesson we made a reusable component for the bottom axis."}),(0,i.jsx)("p",{children:"This lesson suggests many variation: left axis, adding grids, dealing with titles..."})]})}),(0,i.jsx)("h2",{children:"Left axis"}),(0,i.jsx)("h2",{children:"Gallery"}),(0,i.jsx)("p",{children:"Show a gallery with the various axis styles available in the gallery."})]}):null}}},function(e){e.O(0,[2343,7754,8190,3710,9774,2888,179],function(){return e(e.s=34737)}),_N_E=e.O()}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3269],{34737:function(e,s,t){(window.__NEXT_P=window.__NEXT_P||[]).push(["/course/axis/axis-variations",function(){return t(54294)}])},41843:function(e,s,t){"use strict";t.d(s,{p:function(){return c}});var i=t(85893),n=t(49700),r=t(63476),a=t(17414),l=t(41664),o=t.n(l);let c=e=>{let{children:s,title:t,seoDescription:l,previousTocItem:c,nextTocItem:d}=e;return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(a.A,{title:t,seoDescription:l}),(0,i.jsx)(n.Z,{}),(0,i.jsx)("div",{className:"wrapper",children:s}),(0,i.jsxs)("div",{className:"flex justify-center items-center space-x-6 my-24 py-12 bg-muted/50",children:[c?(0,i.jsxs)(o(),{href:c.link,className:"text-gray-500 no-underline flex flex-col justify-start items-end w-96 h-32 border-r border-black p-8 hover:bg-muted ",children:[(0,i.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l to-fuchsia-300 from-blue-400 bg-clip-text",children:"← Previous"}),(0,i.jsx)("p",{children:c.name})]}):(0,i.jsx)("div",{className:"w-96"}),d&&(0,i.jsxs)(o(),{href:d.link,className:"text-gray-500 no-underline flex flex-col justify-start w-96 h-32 border-l border-black p-8 hover:bg-muted ",children:[(0,i.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l from-fuchsia-300 to-blue-400 bg-clip-text",children:"Next →"}),(0,i.jsx)("p",{children:d.name})]})]}),(0,i.jsx)("div",{className:"wrapper",children:(0,i.jsx)(r.Z,{})})]})}},54294:function(e,s,t){"use strict";t.r(s),t.d(s,{default:function(){return l}});var i=t(85893);t(67294);var n=t(43710),r=t(41843),a=t(11236);function l(){let e=a.Y.find(e=>"/course/axis/axis-variations"===e.link);return e?(0,i.jsxs)(r.p,{title:e.name,seoDescription:"",nextTocItem:a.Y.find(e=>"/course/axis/axis-with-d3"===e.link),previousTocItem:a.Y.find(e=>"/course/axis/bottom-axis"===e.link),children:[(0,i.jsx)(n.Z,{title:e.name,lessonStatus:e.status,readTime:e.readTime,selectedLesson:e,description:(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)("p",{children:"In the previous lesson we made a reusable component for the bottom axis."}),(0,i.jsx)("p",{children:"This lesson suggests many variation: left axis, adding grids, dealing with titles..."})]})}),(0,i.jsx)("h2",{children:"Gallery"}),(0,i.jsx)("p",{children:"Show a gallery with the various axis styles available in the gallery."}),(0,i.jsx)("p",{children:"I need a first series of button: linear / ordinal / bandwidth / time / any = type of scale"}),(0,i.jsx)("p",{children:"Then a second series: left / bottom "}),(0,i.jsx)("p",{children:"Then it shows all the example in the gallery using this setup with a set of images"}),(0,i.jsx)("p",{children:"When user clicks on an image, it opens the sandbox so user has the code ready to copy paste."})]}):null}}},function(e){e.O(0,[2343,7754,8190,3710,9774,2888,179],function(){return e(e.s=34737)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/_next/static/chunks/pages/course/axis/axis-with-d3-c402b9adba801e99.js b/_next/static/chunks/pages/course/axis/axis-with-d3-1a6cdc32ad8e4d5a.js similarity index 56% rename from _next/static/chunks/pages/course/axis/axis-with-d3-c402b9adba801e99.js rename to _next/static/chunks/pages/course/axis/axis-with-d3-1a6cdc32ad8e4d5a.js index b42b6571..10131825 100644 --- a/_next/static/chunks/pages/course/axis/axis-with-d3-c402b9adba801e99.js +++ b/_next/static/chunks/pages/course/axis/axis-with-d3-1a6cdc32ad8e4d5a.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3856],{90111:function(e,t,n){(window.__NEXT_P=window.__NEXT_P||[]).push(["/course/axis/axis-with-d3",function(){return n(70703)}])},81122:function(e,t,n){"use strict";n.d(t,{$:function(){return c}});var s=n(85893),i=n(67294),r=n(59973),a=n(80615),l=n(88578),o=n(5);let c=e=>{let{VizComponent:t,vizName:n,height:c=400,maxWidth:d=800,caption:h}=e,[u,x]=(0,i.useState)(!1),f=(0,i.useRef)(null),m=(0,r.B)(f);return(0,s.jsx)("div",{style:{marginLeft:"-50vw",left:"50%"},className:"my-4 py-4 w-screen relative",children:u?(0,s.jsxs)("div",{className:"flex flex-col items-center justify-center w-full",children:[(0,s.jsx)("div",{style:{maxWidth:2e3},className:"w-full z-50",children:(0,s.jsx)(l.X,{vizName:n})}),(0,s.jsx)("div",{className:"flex justify-center mt-2",children:(0,s.jsx)(o.z,{size:"sm",onClick:()=>x(!u),children:"Hide Sandbox"})})]}):(0,s.jsxs)("div",{className:"flex flex-col items-center justify-center",children:[(0,s.jsx)("div",{className:"bg-gray-100 bg-opacity-50 w-screen flex justify-center z-50 pointer-events-none",children:(0,s.jsx)("div",{style:{height:c,width:"100%",maxWidth:d},ref:f,className:"pointer-events-auto",children:(0,s.jsx)(t,{height:c,width:m.width})})}),(0,s.jsx)(a.Y,{children:h}),(0,s.jsx)("div",{className:"flex justify-center",children:(0,s.jsx)(o.z,{size:"sm",onClick:()=>x(!u),children:"Show code"})})]})})}},88578:function(e,t,n){"use strict";n.d(t,{X:function(){return i}});var s=n(85893);n(67294);let i=e=>{let{vizName:t}=e;return(0,s.jsx)("iframe",{src:"https://codesandbox.io/embed/github/holtzy/react-graph-gallery/tree/main/viz/"+t+"?fontsize=14&hidenavigation=1&theme=dark&expanddevtools=0",style:{width:"100%",height:"500px",border:"solid",borderWidth:2,borderRadius:"4px",overflow:"hidden"},allow:"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking",sandbox:"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"})}},41843:function(e,t,n){"use strict";n.d(t,{p:function(){return c}});var s=n(85893),i=n(49700),r=n(63476),a=n(17414),l=n(41664),o=n.n(l);let c=e=>{let{children:t,title:n,seoDescription:l,previousTocItem:c,nextTocItem:d}=e;return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(a.A,{title:n,seoDescription:l}),(0,s.jsx)(i.Z,{}),(0,s.jsx)("div",{className:"wrapper",children:t}),(0,s.jsxs)("div",{className:"flex justify-center items-center space-x-6 my-24 py-12 bg-muted/50",children:[c?(0,s.jsxs)(o(),{href:c.link,className:"text-gray-500 no-underline flex flex-col justify-start items-end w-96 h-32 border-r border-black p-8 hover:bg-muted ",children:[(0,s.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l to-fuchsia-300 from-blue-400 bg-clip-text",children:"← Previous"}),(0,s.jsx)("p",{children:c.name})]}):(0,s.jsx)("div",{className:"w-96"}),d&&(0,s.jsxs)(o(),{href:d.link,className:"text-gray-500 no-underline flex flex-col justify-start w-96 h-32 border-l border-black p-8 hover:bg-muted ",children:[(0,s.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l from-fuchsia-300 to-blue-400 bg-clip-text",children:"Next →"}),(0,s.jsx)("p",{children:d.name})]})]}),(0,s.jsx)("div",{className:"wrapper",children:(0,s.jsx)(r.Z,{})})]})}},80615:function(e,t,n){"use strict";n.d(t,{Y:function(){return i}});var s=n(85893);let i=e=>{let{children:t}=e;return(0,s.jsx)("p",{className:"text-sm text-gray-500 max-w-xs italic text-center mt-4 font-light",children:t})}},3572:function(e,t,n){"use strict";n.d(t,{d:function(){return d}});var s=n(85893),i=n(32581),r=n(15660),a=n.n(r),l=n(67294),o=n(45993),c=n.n(o);let d=e=>{let{code:t}=e,[n,r]=(0,l.useState)(!1),o=(0,l.useRef)(null);(0,l.useEffect)(()=>{o.current&&a().highlightElement(o.current)},[o,t]);let d=(0,s.jsx)("div",{onClick:()=>{navigator.clipboard.writeText(t),r(!0)},className:c().codeChunckCopyButton,children:n?"Copied":(0,s.jsx)(i.Z,{size:14,style:{padding:0}})});return(0,s.jsxs)("div",{className:"mb-6 relative",children:[(0,s.jsx)("pre",{className:"rounded-md line-numbers",children:(0,s.jsx)("code",{ref:o,className:"language-javascript",children:t})}),(0,s.jsx)("div",{className:c().copyButtonContainer,children:d})]})}},59973:function(e,t,n){"use strict";n.d(t,{B:function(){return i}});var s=n(67294);let i=e=>{let t=()=>({width:e.current?e.current.offsetWidth:0,height:e.current?e.current.offsetHeight:0}),[n,i]=(0,s.useState)(t),r=()=>{i(t())};return(0,s.useEffect)(()=>(window.addEventListener("resize",r),()=>window.removeEventListener("resize",r)),[]),(0,s.useEffect)(()=>{r()},[e]),n}},70703:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return h}});var s=n(85893);n(67294);var i=n(43710),r=n(41843),a=n(11236),l=n(3572),o=n(19618),c=n(81122);let d=void 0;function h(){let e=a.Y.find(e=>"/course/axis/axis-with-d3"===e.link);return e?(0,s.jsxs)(r.p,{title:e.name,seoDescription:"",nextTocItem:a.Y.find(e=>e.link===d),previousTocItem:a.Y.find(e=>"/course/axis/axis-variations"===e.link),children:[(0,s.jsx)(i.Z,{title:e.name,lessonStatus:e.status,readTime:e.readTime,selectedLesson:e,description:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("p",{children:"d3 offers some very smart functions when it comes to building axes."}),(0,s.jsx)("p",{children:"I personnaly prefer to avoid using d3 rendering functions like this. I have more control when using react for rendering. But if you are familiar with d3, it can be very handy to use those functions, and here is how to wrap them in a usEffect"})]})}),(0,s.jsx)("h2",{children:"The d3 axis module"}),(0,s.jsx)("p",{children:"Explain what it is with links and examples"}),(0,s.jsx)("h2",{children:"How to use in a react app."}),(0,s.jsxs)("p",{children:["If you're a d3.js afficionados and want to deal with as little react as possible, you can still use the good old ",(0,s.jsx)("code",{children:"axisBottom()"})," and"," ",(0,s.jsx)("code",{children:"axisLeft()"})," methods of d3 and wrap them in a",(0,s.jsx)("code",{children:"useEffect()"})," hook."]}),(0,s.jsx)("p",{children:"Here is an example below:"}),(0,s.jsx)(c.$,{vizName:"AxisBasicD3",VizComponent:o.d,maxWidth:600,height:300,caption:"This axis is rendered using d3. The d3 necessary functions are called from a useEffect"}),(0,s.jsx)("h2",{children:"Explanation"}),(0,s.jsx)("p",{children:"Everything starts with a ref"}),(0,s.jsx)(l.d,{code:"\nconst axesRef = useRef(null);\n ".trim()})]}):null}},19618:function(e,t,n){"use strict";n.d(t,{d:function(){return c}});var s=n(85893),i=n(67294),r=n(88657);let a=e=>{let{width:t,height:n}=e;return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("defs",{children:(0,s.jsx)("pattern",{id:"pattern_rkDsm",patternUnits:"userSpaceOnUse",width:"9.5",height:"2.5",patternTransform:"rotate(41)",children:(0,s.jsx)("line",{x1:"0",y:"0",x2:"0",y2:"9.5",stroke:"#D9B9F3",strokeWidth:"1"})})}),(0,s.jsx)("rect",{width:t,height:n,fill:"url(#pattern_rkDsm)",opacity:"1"})]})},l={top:30,right:30,bottom:50,left:50},o=e=>{let{width:t,height:n}=e,o=(0,i.useRef)(null),c=t-l.right-l.left,d=n-l.top-l.bottom,h=(0,i.useMemo)(()=>r.BYU().domain([0,10]).range([0,c]),[t]),u=(0,i.useMemo)(()=>r.BYU().domain([0,10]).range([d,0]),[n]);return(0,i.useEffect)(()=>{let e=r.Ys(o.current);e.selectAll("*").remove();let t=r.LLu(h);e.append("g").attr("transform","translate(0,"+d+")").call(t);let n=r.y4O(u);e.append("g").call(n)},[h,u,d]),(0,s.jsx)("div",{children:(0,s.jsxs)("svg",{width:t,height:n,style:{display:"inline-block"},children:[(0,s.jsx)("g",{width:c,height:d,transform:"translate(".concat([l.left,l.top].join(","),")"),children:(0,s.jsx)(a,{width:c,height:d})}),(0,s.jsx)("g",{width:c,height:d,ref:o,transform:"translate(".concat([l.left,l.top].join(","),")")})]})})},c=e=>{let{width:t=700,height:n=400}=e;return(0,s.jsx)(o,{width:t,height:n})}},45993:function(e){e.exports={codeChunckCopyButton:"code-block_codeChunckCopyButton__yPrL_",copyButtonContainer:"code-block_copyButtonContainer__BrX9E"}}},function(e){e.O(0,[2343,7754,8657,7823,8190,3710,9774,2888,179],function(){return e(e.s=90111)}),_N_E=e.O()}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3856],{90111:function(e,t,n){(window.__NEXT_P=window.__NEXT_P||[]).push(["/course/axis/axis-with-d3",function(){return n(70703)}])},81122:function(e,t,n){"use strict";n.d(t,{$:function(){return o}});var s=n(85893),i=n(67294),r=n(59973),a=n(80615),l=n(88578),c=n(5);let o=e=>{let{VizComponent:t,vizName:n,height:o=400,maxWidth:d=800,caption:h}=e,[u,x]=(0,i.useState)(!1),f=(0,i.useRef)(null),m=(0,r.B)(f);return(0,s.jsx)("div",{style:{marginLeft:"-50vw",left:"50%"},className:"my-4 py-4 w-screen relative",children:u?(0,s.jsxs)("div",{className:"flex flex-col items-center justify-center w-full",children:[(0,s.jsx)("div",{style:{maxWidth:2e3},className:"w-full z-50",children:(0,s.jsx)(l.X,{vizName:n})}),(0,s.jsx)("div",{className:"flex justify-center mt-2",children:(0,s.jsx)(c.z,{size:"sm",onClick:()=>x(!u),children:"Hide Sandbox"})})]}):(0,s.jsxs)("div",{className:"flex flex-col items-center justify-center",children:[(0,s.jsx)("div",{className:"bg-gray-100 bg-opacity-50 w-screen flex justify-center z-50 pointer-events-none",children:(0,s.jsx)("div",{style:{height:o,width:"100%",maxWidth:d},ref:f,className:"pointer-events-auto",children:(0,s.jsx)(t,{height:o,width:m.width})})}),(0,s.jsx)(a.Y,{children:h}),(0,s.jsx)("div",{className:"flex justify-center",children:(0,s.jsx)(c.z,{size:"sm",onClick:()=>x(!u),children:"Show code"})})]})})}},88578:function(e,t,n){"use strict";n.d(t,{X:function(){return i}});var s=n(85893);n(67294);let i=e=>{let{vizName:t}=e;return(0,s.jsx)("iframe",{src:"https://codesandbox.io/embed/github/holtzy/react-graph-gallery/tree/main/viz/"+t+"?fontsize=14&hidenavigation=1&theme=dark&expanddevtools=0",style:{width:"100%",height:"500px",border:"solid",borderWidth:2,borderRadius:"4px",overflow:"hidden"},allow:"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking",sandbox:"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"})}},41843:function(e,t,n){"use strict";n.d(t,{p:function(){return o}});var s=n(85893),i=n(49700),r=n(63476),a=n(17414),l=n(41664),c=n.n(l);let o=e=>{let{children:t,title:n,seoDescription:l,previousTocItem:o,nextTocItem:d}=e;return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(a.A,{title:n,seoDescription:l}),(0,s.jsx)(i.Z,{}),(0,s.jsx)("div",{className:"wrapper",children:t}),(0,s.jsxs)("div",{className:"flex justify-center items-center space-x-6 my-24 py-12 bg-muted/50",children:[o?(0,s.jsxs)(c(),{href:o.link,className:"text-gray-500 no-underline flex flex-col justify-start items-end w-96 h-32 border-r border-black p-8 hover:bg-muted ",children:[(0,s.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l to-fuchsia-300 from-blue-400 bg-clip-text",children:"← Previous"}),(0,s.jsx)("p",{children:o.name})]}):(0,s.jsx)("div",{className:"w-96"}),d&&(0,s.jsxs)(c(),{href:d.link,className:"text-gray-500 no-underline flex flex-col justify-start w-96 h-32 border-l border-black p-8 hover:bg-muted ",children:[(0,s.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l from-fuchsia-300 to-blue-400 bg-clip-text",children:"Next →"}),(0,s.jsx)("p",{children:d.name})]})]}),(0,s.jsx)("div",{className:"wrapper",children:(0,s.jsx)(r.Z,{})})]})}},80615:function(e,t,n){"use strict";n.d(t,{Y:function(){return i}});var s=n(85893);let i=e=>{let{children:t}=e;return(0,s.jsx)("p",{className:"text-sm text-gray-500 max-w-xs italic text-center mt-4 font-light",children:t})}},3572:function(e,t,n){"use strict";n.d(t,{d:function(){return d}});var s=n(85893),i=n(32581),r=n(15660),a=n.n(r),l=n(67294),c=n(45993),o=n.n(c);let d=e=>{let{code:t}=e,[n,r]=(0,l.useState)(!1),c=(0,l.useRef)(null);(0,l.useEffect)(()=>{c.current&&a().highlightElement(c.current)},[c,t]);let d=(0,s.jsx)("div",{onClick:()=>{navigator.clipboard.writeText(t),r(!0)},className:o().codeChunckCopyButton,children:n?"Copied":(0,s.jsx)(i.Z,{size:14,style:{padding:0}})});return(0,s.jsxs)("div",{className:"mb-6 relative",children:[(0,s.jsx)("pre",{className:"rounded-md line-numbers",children:(0,s.jsx)("code",{ref:c,className:"language-javascript",children:t})}),(0,s.jsx)("div",{className:o().copyButtonContainer,children:d})]})}},59973:function(e,t,n){"use strict";n.d(t,{B:function(){return i}});var s=n(67294);let i=e=>{let t=()=>({width:e.current?e.current.offsetWidth:0,height:e.current?e.current.offsetHeight:0}),[n,i]=(0,s.useState)(t),r=()=>{i(t())};return(0,s.useEffect)(()=>(window.addEventListener("resize",r),()=>window.removeEventListener("resize",r)),[]),(0,s.useEffect)(()=>{r()},[e]),n}},70703:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return h}});var s=n(85893);n(67294);var i=n(43710),r=n(41843),a=n(11236),l=n(3572),c=n(19618),o=n(81122);let d=void 0;function h(){let e=a.Y.find(e=>"/course/axis/axis-with-d3"===e.link);return e?(0,s.jsxs)(r.p,{title:e.name,seoDescription:"",nextTocItem:a.Y.find(e=>e.link===d),previousTocItem:a.Y.find(e=>"/course/axis/axis-variations"===e.link),children:[(0,s.jsx)(i.Z,{title:e.name,lessonStatus:e.status,readTime:e.readTime,selectedLesson:e,description:(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("p",{children:"d3 offers some very smart functions when it comes to building axes."}),(0,s.jsx)("p",{children:"I personnaly prefer to avoid using d3 rendering functions like this. I have more control when using react for rendering. But if you are familiar with d3, it can be very handy to use those functions, and here is how to wrap them in a usEffect"})]})}),(0,s.jsx)("h2",{children:"The d3 axis module"}),(0,s.jsx)("p",{children:"Explain what it is with links and examples"}),(0,s.jsx)("h2",{children:"How to use in a react app."}),(0,s.jsxs)("p",{children:["If you're a d3.js afficionados and want to deal with as little react as possible, you can still use the good old ",(0,s.jsx)("code",{children:"axisBottom()"})," and"," ",(0,s.jsx)("code",{children:"axisLeft()"})," methods of d3 and wrap them in a",(0,s.jsx)("code",{children:"useEffect()"})," hook."]}),(0,s.jsx)("p",{children:"Here is an example below:"}),(0,s.jsx)(o.$,{vizName:"AxisBasicD3",VizComponent:c.d,maxWidth:600,height:300,caption:"This axis is rendered using d3. The d3 necessary functions are called from a useEffect"}),(0,s.jsx)("h2",{children:"Explanation"}),(0,s.jsx)("p",{children:"Everything starts with a ref"}),(0,s.jsx)(l.d,{code:"\nconst axesRef = useRef(null);\n ".trim()}),(0,s.jsx)("p",{children:"This ref is used to target a specific svg element where the axis will be drawn:"}),(0,s.jsx)(l.d,{code:"\n".trim()}),(0,s.jsxs)("p",{children:["And then a ",(0,s.jsx)("code",{children:"useEffect"})," is used to call the d3 functions that render the axis."]}),(0,s.jsx)(l.d,{code:'\nuseEffect(() => {\n const svgElement = d3.select(axesRef.current);\n svgElement.selectAll("*").remove();\n const xAxisGenerator = d3.axisBottom(xScale);\n svgElement\n .append("g")\n .attr("transform", "translate(0," + boundsHeight + ")")\n .call(xAxisGenerator);\n\n const yAxisGenerator = d3.axisLeft(yScale);\n svgElement.append("g").call(yAxisGenerator);\n}, [xScale, yScale, boundsHeight]);\n\n '.trim()})]}):null}},19618:function(e,t,n){"use strict";n.d(t,{d:function(){return o}});var s=n(85893),i=n(67294),r=n(88657);let a=e=>{let{width:t,height:n}=e;return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("defs",{children:(0,s.jsx)("pattern",{id:"pattern_rkDsm",patternUnits:"userSpaceOnUse",width:"9.5",height:"2.5",patternTransform:"rotate(41)",children:(0,s.jsx)("line",{x1:"0",y:"0",x2:"0",y2:"9.5",stroke:"#D9B9F3",strokeWidth:"1"})})}),(0,s.jsx)("rect",{width:t,height:n,fill:"url(#pattern_rkDsm)",opacity:"1"})]})},l={top:30,right:30,bottom:50,left:50},c=e=>{let{width:t,height:n}=e,c=(0,i.useRef)(null),o=t-l.right-l.left,d=n-l.top-l.bottom,h=(0,i.useMemo)(()=>r.BYU().domain([0,10]).range([0,o]),[t]),u=(0,i.useMemo)(()=>r.BYU().domain([0,10]).range([d,0]),[n]);return(0,i.useEffect)(()=>{let e=r.Ys(c.current);e.selectAll("*").remove();let t=r.LLu(h);e.append("g").attr("transform","translate(0,"+d+")").call(t);let n=r.y4O(u);e.append("g").call(n)},[h,u,d]),(0,s.jsx)("div",{children:(0,s.jsxs)("svg",{width:t,height:n,style:{display:"inline-block"},children:[(0,s.jsx)("g",{width:o,height:d,transform:"translate(".concat([l.left,l.top].join(","),")"),children:(0,s.jsx)(a,{width:o,height:d})}),(0,s.jsx)("g",{width:o,height:d,ref:c,transform:"translate(".concat([l.left,l.top].join(","),")")})]})})},o=e=>{let{width:t=700,height:n=400}=e;return(0,s.jsx)(c,{width:t,height:n})}},45993:function(e){e.exports={codeChunckCopyButton:"code-block_codeChunckCopyButton__yPrL_",copyButtonContainer:"code-block_copyButtonContainer__BrX9E"}}},function(e){e.O(0,[2343,7754,8657,7823,8190,3710,9774,2888,179],function(){return e(e.s=90111)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/_next/static/chunks/pages/course/introduction/introduction-to-react-5bacb05304b527fe.js b/_next/static/chunks/pages/course/introduction/introduction-to-react-5bacb05304b527fe.js new file mode 100644 index 00000000..9457701b --- /dev/null +++ b/_next/static/chunks/pages/course/introduction/introduction-to-react-5bacb05304b527fe.js @@ -0,0 +1 @@ +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9347],{28531:function(e,t,i){(window.__NEXT_P=window.__NEXT_P||[]).push(["/course/introduction/introduction-to-react",function(){return i(75950)}])},88578:function(e,t,i){"use strict";i.d(t,{X:function(){return s}});var n=i(85893);i(67294);let s=e=>{let{vizName:t}=e;return(0,n.jsx)("iframe",{src:"https://codesandbox.io/embed/github/holtzy/react-graph-gallery/tree/main/viz/"+t+"?fontsize=14&hidenavigation=1&theme=dark&expanddevtools=0",style:{width:"100%",height:"500px",border:"solid",borderWidth:2,borderRadius:"4px",overflow:"hidden"},allow:"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking",sandbox:"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"})}},41843:function(e,t,i){"use strict";i.d(t,{p:function(){return c}});var n=i(85893),s=i(49700),r=i(63476),a=i(17414),o=i(41664),l=i.n(o);let c=e=>{let{children:t,title:i,seoDescription:o,previousTocItem:c,nextTocItem:d}=e;return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(a.A,{title:i,seoDescription:o}),(0,n.jsx)(s.Z,{}),(0,n.jsx)("div",{className:"wrapper",children:t}),(0,n.jsxs)("div",{className:"flex justify-center items-center space-x-6 my-24 py-12 bg-muted/50",children:[c?(0,n.jsxs)(l(),{href:c.link,className:"text-gray-500 no-underline flex flex-col justify-start items-end w-96 h-32 border-r border-black p-8 hover:bg-muted ",children:[(0,n.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l to-fuchsia-300 from-blue-400 bg-clip-text",children:"← Previous"}),(0,n.jsx)("p",{children:c.name})]}):(0,n.jsx)("div",{className:"w-96"}),d&&(0,n.jsxs)(l(),{href:d.link,className:"text-gray-500 no-underline flex flex-col justify-start w-96 h-32 border-l border-black p-8 hover:bg-muted ",children:[(0,n.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l from-fuchsia-300 to-blue-400 bg-clip-text",children:"Next →"}),(0,n.jsx)("p",{children:d.name})]})]}),(0,n.jsx)("div",{className:"wrapper",children:(0,n.jsx)(r.Z,{})})]})}},80615:function(e,t,i){"use strict";i.d(t,{Y:function(){return s}});var n=i(85893);let s=e=>{let{children:t}=e;return(0,n.jsx)("p",{className:"text-sm text-gray-500 max-w-xs italic text-center mt-4 font-light",children:t})}},75950:function(e,t,i){"use strict";i.r(t),i.d(t,{default:function(){return d}});var n=i(85893);i(67294);var s=i(43710),r=i(41843),a=i(11236),o=i(80615),l=i(88578);let c=void 0;function d(){let e=a.Y.find(e=>"/course/introduction/introduction-to-react"===e.link);return e?(0,n.jsxs)(r.p,{title:e.name,seoDescription:"",nextTocItem:a.Y.find(e=>"/course/introduction/js-dataviz-libraries"===e.link),previousTocItem:a.Y.find(e=>e.link===c),children:[(0,n.jsx)(s.Z,{title:e.name,lessonStatus:e.status,readTime:e.readTime,selectedLesson:e,description:(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)("p",{children:["React is a ",(0,n.jsx)("b",{children:"JavaScript library"})," used for creating dynamic and interactive user interfaces through ",(0,n.jsx)("b",{children:"reusable components"}),". Developed by Facebook, it simplifies the process of managing application state and updating the user interface efficiently."]}),(0,n.jsx)("p",{children:"This lesson will offer a concise overview of React and its key features."})]})}),(0,n.jsx)("h2",{children:"Why React?"}),(0,n.jsx)("p",{children:"React was introduced in 2013, transforming the landscape of web development."}),(0,n.jsxs)("p",{children:["Prior to its ",(0,n.jsx)("b",{children:"component-based architecture"}),", building web applications was complex and cumbersome."]}),(0,n.jsxs)("div",{className:"flex flex-col items-center mt-8 mb-12",children:[(0,n.jsx)("img",{src:"/img/react-website.png",style:{width:"100%",maxWidth:400},alt:"Screenshot of the React website front page"}),(0,n.jsx)(o.Y,{children:"If you make charts for the web and don't know react, you're missing out!"})]}),(0,n.jsxs)("p",{children:["This is particularly evident in applications that involve"," ",(0,n.jsx)("b",{children:"data visualization"}),". The ability to create reusable components, like a ",(0,n.jsx)("code",{children:"Scatterplot"})," component, that can be utilized throughout your app, is a game-changer for your development process."]}),(0,n.jsx)("p",{children:(0,n.jsx)("br",{})}),(0,n.jsx)("p",{children:"If you're building a data visualization application, React offers everything you need:"}),(0,n.jsxs)("ul",{children:[(0,n.jsxs)("li",{children:["Robust ",(0,n.jsx)("b",{children:"state management"}),", perfectly suited for dynamic data."]}),(0,n.jsxs)("li",{children:["A ",(0,n.jsx)("b",{children:"component-driven approach"}),", ideal for creating interactive visualizations."]}),(0,n.jsxs)("li",{children:["Extensive community support and comprehensive ",(0,n.jsx)("b",{children:"documentation"}),"."]})]}),(0,n.jsx)("h2",{children:"Expected knowledge"}),(0,n.jsxs)("p",{children:["This course focuses on ",(0,n.jsx)("strong",{children:"Data Visualization"})," using React."]}),(0,n.jsxs)("p",{children:["We won’t cover the basics of React, as that’s a vast topic deserving its own dedicated course! For a solid introduction, check out this"," ",(0,n.jsx)("a",{href:"https://www.codecademy.com/learn/learn-react-introduction",target:"_blank",children:"intro by Codecademy"}),"."]}),(0,n.jsx)("p",{children:"Basically, you should just be able to understand what's happening in this sandbox:"}),(0,n.jsx)("div",{className:"full-bleed my-4 max-w-7xl mx-auto",children:(0,n.jsx)(l.X,{vizName:"SvgCircle"})}),(0,n.jsx)("p",{children:"However, you don’t need to be a React expert to take this course. Even seasoned developers will find valuable insights here: creating visualizations with React and D3 involves specialized knowledge that differs significantly from typical UI development."}),(0,n.jsx)("p",{children:"Lastly, you don’t need prior experience with D3 to get started! We’ll use it sparingly and provide a thorough explanation of how it works."}),(0,n.jsx)("h2",{children:"Alternatives"}),(0,n.jsx)("p",{children:"Talk about Vue and "}),(0,n.jsx)("p",{children:"Link: https://gist.github.com/tkrotoff/b1caa4c3a185629299ec234d2314e190"}),(0,n.jsxs)("div",{className:"flex flex-col items-center mt-8 mb-12",children:[(0,n.jsx)("img",{src:"/img/js-lib-download-npm-trend.png",style:{width:"100%",maxWidth:900},alt:"schema showing the number of download evolution of the main JS libraries"}),(0,n.jsx)(o.Y,{children:"React is big"})]})]}):null}}},function(e){e.O(0,[2343,7754,8190,3710,9774,2888,179],function(){return e(e.s=28531)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/_next/static/chunks/pages/course/introduction/introduction-to-react-bee9ba8b631896a0.js b/_next/static/chunks/pages/course/introduction/introduction-to-react-bee9ba8b631896a0.js deleted file mode 100644 index 29a690e8..00000000 --- a/_next/static/chunks/pages/course/introduction/introduction-to-react-bee9ba8b631896a0.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9347],{28531:function(e,t,n){(window.__NEXT_P=window.__NEXT_P||[]).push(["/course/introduction/introduction-to-react",function(){return n(75950)}])},41843:function(e,t,n){"use strict";n.d(t,{p:function(){return o}});var i=n(85893),s=n(49700),r=n(63476),a=n(17414),c=n(41664),l=n.n(c);let o=e=>{let{children:t,title:n,seoDescription:c,previousTocItem:o,nextTocItem:d}=e;return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(a.A,{title:n,seoDescription:c}),(0,i.jsx)(s.Z,{}),(0,i.jsx)("div",{className:"wrapper",children:t}),(0,i.jsxs)("div",{className:"flex justify-center items-center space-x-6 my-24 py-12 bg-muted/50",children:[o?(0,i.jsxs)(l(),{href:o.link,className:"text-gray-500 no-underline flex flex-col justify-start items-end w-96 h-32 border-r border-black p-8 hover:bg-muted ",children:[(0,i.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l to-fuchsia-300 from-blue-400 bg-clip-text",children:"← Previous"}),(0,i.jsx)("p",{children:o.name})]}):(0,i.jsx)("div",{className:"w-96"}),d&&(0,i.jsxs)(l(),{href:d.link,className:"text-gray-500 no-underline flex flex-col justify-start w-96 h-32 border-l border-black p-8 hover:bg-muted ",children:[(0,i.jsx)("span",{className:"uppercase font-light text-transparent bg-gradient-to-l from-fuchsia-300 to-blue-400 bg-clip-text",children:"Next →"}),(0,i.jsx)("p",{children:d.name})]})]}),(0,i.jsx)("div",{className:"wrapper",children:(0,i.jsx)(r.Z,{})})]})}},75950:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return l}});var i=n(85893);n(67294);var s=n(43710),r=n(41843),a=n(11236);let c=void 0;function l(){let e=a.Y.find(e=>"/course/introduction/introduction-to-react"===e.link);return e?(0,i.jsxs)(r.p,{title:e.name,seoDescription:"",nextTocItem:a.Y.find(e=>"/course/introduction/js-dataviz-libraries"===e.link),previousTocItem:a.Y.find(e=>e.link===c),children:[(0,i.jsx)(s.Z,{title:e.name,lessonStatus:e.status,readTime:e.readTime,selectedLesson:e,description:(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)("p",{children:["React is a ",(0,i.jsx)("b",{children:"JavaScript library"})," used for creating dynamic and interactive user interfaces through reusable components. Developed by Facebook, it simplifies the process of managing application state and updating the user interface efficiently."]}),(0,i.jsx)("p",{children:"This lesson will offer a concise overview of React and its key features."})]})}),(0,i.jsx)("h2",{children:"Why React?"}),(0,i.jsx)("p",{children:"Explain why react is great?"}),(0,i.jsxs)("ul",{children:[(0,i.jsx)("li",{children:"Widespread, full of doc. Show a graph that compares with others."}),(0,i.jsx)("li",{children:"Great state management: exactly what we need"}),(0,i.jsx)("li",{children:"Based on the concept of component: exactly what we need for dataviz"})]}),(0,i.jsx)("h2",{children:"Expected knowledge"}),(0,i.jsx)("p",{children:"Explain that this is not a react course. If you know nothing about react, you gonna struggle here. So learn somewhere first."}),(0,i.jsx)("p",{children:"Explain that building viz is a very specific need, thus this course."})]}):null}}},function(e){e.O(0,[2343,7754,8190,3710,9774,2888,179],function(){return e(e.s=28531)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/about.html b/about.html index 79cc8d82..28facd18 100644 --- a/about.html +++ b/about.html @@ -1,4 +1,4 @@ -About the gallery

      React + D3.js = ❤️


      A love story – So simple powerful yet so complicated

      A few years ago I created the d3 graph gallery, a website showcasing hundreds of simple charts made with d3.js. It worked well! Thousands of people use it daily to learn d3. 🎉

      Since then, React became the most popular framework to build user interfaces. This rose a question: how to build a chart in react? That's a complicated question with many answers. Here are the 3 most common approaches.

      3 ways to draw a chart in react

      → 1️⃣ Charting libraries

      There is a myriad of charting libraries offering react components for every chart type. HighChart, ReCharts, React-viz, plot, visX and so many more. Those libraries are awesome: you'll get a working chart in minutes using them.

      But simplicity comes with a cost: the time you saved in the first place will be lost when you'll try to reach a high level of customization.

      If you want to build something unique, you need to draw shapes one by one.

      → 2️⃣ D3 for rendering in a useEffect hook

      If you're familiar with d3.js already, it's possible to use any of its examples (from a block or the gallery) by using a useEffect hook.

      Basically, you can create a div in the DOM using react. You can then use the drawing methods of the d3-selection module like append or axisBottom to target this div, and add the content of the chart.

      Let's apply this to draw axes:

      You can use all the d3 knowlege you have in a useEffect hook to build the graph in a react context.

      This works but comes with some caveats. To put it in a nutshell you now have 2 tools trying to control the DOM: react and d3. That's hard to maintain for large applications.

      → 3️⃣ D3 for maths, React for rendering

      This gallery suggests using d3.js only for the math utils it provides. And to add entries to the DOM using react, like for any other UI element.

      Let's say we want to build a scatterplot. The scaleLinear function of d3.js is used to build the scales. Now that we can easily know the position of a circle on the screen, we can just loop through all data items and render them as a circle svg element.

      012345678910

      Use d3.js to compute the scales. Use React to render the circles.

      Learn concepts, Get templates

      This gallery is all about using the power of the d3 math utils and the react rendering engine.

      The first goal is to teach the concepts. Many examples are provided for each chart type. Each one targets a specific theme like color, axis, responsiveness, hover effect, or tooltips.

      The second goal is to provide templates for each viz type. Building a viz from scratch is time-consuming, so better tweak an existing example.

      All graph examples come with an explanation and a code sandbox allowing you to play with the code.

      I built this website with ❤️. I hope it will help you create stunning vizs in a minimum amount of time. Reach me on Twitter, contribute on github and subscribe to the newsletter to know when new chart types are published!

      Contact

      👋 Hey, I'm Yan and I'm currently working on this project!

      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

      +About the gallery

      React + D3.js = ❤️


      A love story – So simple powerful yet so complicated

      A few years ago I created the d3 graph gallery, a website showcasing hundreds of simple charts made with d3.js. It worked well! Thousands of people use it daily to learn d3. 🎉

      Since then, React became the most popular framework to build user interfaces. This rose a question: how to build a chart in react? That's a complicated question with many answers. Here are the 3 most common approaches.

      3 ways to draw a chart in react

      → 1️⃣ Charting libraries

      There is a myriad of charting libraries offering react components for every chart type. HighChart, ReCharts, React-viz, plot, visX and so many more. Those libraries are awesome: you'll get a working chart in minutes using them.

      But simplicity comes with a cost: the time you saved in the first place will be lost when you'll try to reach a high level of customization.

      If you want to build something unique, you need to draw shapes one by one.

      → 2️⃣ D3 for rendering in a useEffect hook

      If you're familiar with d3.js already, it's possible to use any of its examples (from a block or the gallery) by using a useEffect hook.

      Basically, you can create a div in the DOM using react. You can then use the drawing methods of the d3-selection module like append or axisBottom to target this div, and add the content of the chart.

      Let's apply this to draw axes:

      You can use all the d3 knowlege you have in a useEffect hook to build the graph in a react context.

      This works but comes with some caveats. To put it in a nutshell you now have 2 tools trying to control the DOM: react and d3. That's hard to maintain for large applications.

      → 3️⃣ D3 for maths, React for rendering

      This gallery suggests using d3.js only for the math utils it provides. And to add entries to the DOM using react, like for any other UI element.

      Let's say we want to build a scatterplot. The scaleLinear function of d3.js is used to build the scales. Now that we can easily know the position of a circle on the screen, we can just loop through all data items and render them as a circle svg element.

      012345678910

      Use d3.js to compute the scales. Use React to render the circles.

      Learn concepts, Get templates

      This gallery is all about using the power of the d3 math utils and the react rendering engine.

      The first goal is to teach the concepts. Many examples are provided for each chart type. Each one targets a specific theme like color, axis, responsiveness, hover effect, or tooltips.

      The second goal is to provide templates for each viz type. Building a viz from scratch is time-consuming, so better tweak an existing example.

      All graph examples come with an explanation and a code sandbox allowing you to play with the code.

      I built this website with ❤️. I hope it will help you create stunning vizs in a minimum amount of time. Reach me on Twitter, contribute on github and subscribe to the newsletter to know when new chart types are published!

      Contact

      👋 Hey, I'm Yan and I'm currently working on this project!

      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

        -
        \ No newline at end of file +
        \ No newline at end of file diff --git a/all.html b/all.html index 76b7d41c..c15b5d82 100644 --- a/all.html +++ b/all.html @@ -1,4 +1,4 @@ -All graphs

        All graphs

        Dataviz logo representing a DataArt2 chart.

        The react graph gallery displays hundreds of graphs made with React, often with the help of d3.js. This page provides an overview of all charts showcased in this gallery.

        Note that all chart types are presented on the welcome page of the gallery. It is probably a more convenient way to browse this website if you know what you are looking for!

        Useful links
        Picture of an empty chart area with X and Y axes

        Scales and axes

        How to map your data in a 2d space, and how to draw the axes

        GIF of a scatterplot with hover effect

        Scatterplot Hover effect

        How to add a hover effect to highlight a group on a scatterplot

        Most basic scatterplot made with react and d3

        Basic scatter plot

        Add circles to get a basic scatter plot

        Scatterplot with tooltip made with react and d3

        Add tooltip

        Get more details about each datapoint by adding a tooltip on hover

        Scatterplot with hover effect made with react and d3

        Add a hover effect

        Highlight a specific group on hover

        Real life example of a scatterplot made with react and d3

        Real life use-case

        Reproduction of a data wrapper chart representing countries CO2 data

        gif of a scatterplot with voronoi diagram for closest point detection

        Closest point detection with Voronoi

        Using a voronoi diagram in the scatterplot background is a smart way to efficiently find the mouse closest point

        a scatterplot made with react and rendered in canvas

        Scatterplot in Canvas

        Learn how to render a scatterplot in canvas to improve performances

        Picture of a simple heatmap made with react and d3.js

        Basic heatmap

        Most basic heatmap

        Picture of a heatmap with a tooltip that appears on hover

        Heatmap with tooltip

        Learn how to add a tooltip to a heatmap with react

        Picture of a continuous color scale built with d3.js

        Continuous color scale

        How to add a color legend to your chart that uses a continuous color scale

        Picture of a heatmap showing the effect of vaccination, built with react and d3

        Vaccination heatmap

        Reproduction of a famous vaccination heatmap using d3 and react

        Picture of a correlogram built with react and d3

        Basic correlogram

        Learn how to build a correlogram with react and d3

        Picture of a simple bubble plot with a legend made with react and d3.js

        Bubble plot

        Learn how to build a bubble plot with react and d3.js

        GIF of a bubble plot smoothly transitioning data

        Bubble plot data set transition

        How to smoothly animate the transition between dataset

        Picture of a hexbin chart made with React and d3.js

        Hexbin chart

        A hexbin chart split the figure in hexagons to show a 2d density

        Picture of a connected scatter plot made with React and d3.js

        Simple connected scatterplot

        A very simple connected scatter plot showing the evolution of 1 numeric variable

        gif of a violin plot smoothly transitioning to a boxplot using shape morphism

        Violin to Boxplot transition

        Using shape morphism to smoothly transition from a boxplot to a violin and reverse

        GIF showing a violin plot with varying bucket size

        Bucket size effect

        Interactive example showing the bucket size effect on a violin chart

        Picture of a violin shape built with react and d3

        Violin shape

        How to build the shape of a violin with SVG

        GIF showing a mirror transition between a boxplot and a violin plot

        Boxplot to Violin plot

        Interactive example showing the difference between a boxplot and a violin

        Picture of a basic violin chart built in react

        Basic violin plot

        Learn how to build a basic violin chart with d3 and react

        Picture of a violin plot with variable bucket size

        Violin with variable bucket size

        A violin plot with a slider to change the bucket size in use

        Picture of a basic density plot built with React and d3

        Basic density plot

        Most basic density plot built with React and d3

        Picture of a density plot with multiple groups

        Density plot with multiple groups

        How to add several groups on the same density plot

        Picture of a simple histogram made with react and d3.js

        Histogram

        Learn how to build a histogram with react and d3.js

        GIF of a histogram with animated data transition

        Histogram dataset transition

        How to animate the transition between datasets

        picture of a mirror histogram made with react and d3.js

        Mirror histogram

        Create a mirror histogram to compare the distribution of 2 groups in a dataset

        Picture of a histogram with small multiple built with react and d3.js

        Small multiple

        Create one panel per group to show its distribution separately

        Picture of a histogram with multiple groups built with react and d3.js

        Multiple groups

        A histogram with <b>multiple</b> groups displayed on the same axis.

        Picture of a boxplot with jitter built using react and d3.js

        Boxplot with jitter

        Add individual data points using jitter on top of the boxplot

        Picture of a box component, allowing to build a boxplot later on

        Boxplot shape

        How to build a boxplot shape in SVG

        Picture of a basic boxplot built with react and d3

        Basic boxplot

        How to build a basic boxplot with react

        Picture of a horizontal boxplot built with react and d3

        Horizontal boxplot

        How to build a horizontal boxplot with react

        Picture of a basic ridgeline chart built with react and d3

        Basic ridgeline chart

        Most basic version of a ridgeline plot

        Picture of a horizontal barplot made with React and d3

        Basic barplot

        Most basic barplot built with React and d3

        GIF of a data update on a React barplot

        Barplot dataset transition

        How to smoothly animate the transition between dataset

        Picture of a stacked barchart made with react and d3

        Horizontal Stacked Barplot

        Represent group and subgroup values by stacking the data

        Picture of a vertical stacked barchart made with react and d3

        Vertical Stacked Barplot

        Represent group and subgroup values by stacking the data

        Picture of a very simple lollipop chart

        Most basic lollipop plot

        Learn how to build a very simple lollipop chart with React and D3.js

        Picture of a very simple dumbbell chart

        Most basic dumbbell plot

        Learn how to build a very simple dumbbell chart with React and D3.js

        Picture of a lollipop chart with hover effect

        Lollipop with hover effect

        Learn how to add a hover effect to your lollipop chart

        Picture of a lollipop with buttons and animated transition

        Animation between dataset

        Learn how to build a smooth animated transition between 2 datasets

        Picture of the background grid of a radar chart

        Most basic line chart

        Learn how to build the background grid of a radar chart

        Picture of a very simple radar chart with 1 group only made with react and d3

        Most basic radar chart

        The most basic radar chart one can make using d3 and react

        Picture of a radar chart made with react and d3, with several groups displayed on the figure.

        Multi-group radar chart

        Radar chart with several groups displayed

        GIF of a radar chart, a line chart and a lollipop that animate between dataset

        Radar chart, line chart an lollipop with animated transition

        Three charts connected to same buttons, with smooth, synchronized animation when a button is clicked

        Picture of a simple treemap

        Basic treemap

        Most simple treemap, with 1 level of hierarchy only

        Picture of a simple treemap with 2 levels of hierarchy

        Treemap with 2 levels

        Simple treemap with 2 levels of hierarchy

        Picture of a simple treemap

        Hover effect

        Treemap with hover effect to highlight a group

        Picture of the most basic donut chart

        Basic Donut chart

        Most simple donut chart. No annotation, static figure.

        Picture of a simple donut chart with inline labels

        Inline labels

        Donut chart with inline labels and connection lines

        GIF of a donut chart with a hover effect

        Hover effect

        Donut chart with hover effect to highlight a slice

        GIF of a donut chart switching between 2 datasets

        Data transition

        How to smoothly transition dataset

        GIF of a donut chart switching between to a barplot and reverse

        Shape morphism

        Transition between a barplot and a donut chart

        Picture of the most basic pie chart

        Basic Pie chart

        Most simple pie chart. No annotation, static figure.

        Picture of a simple pie chart with inline labels

        Inline labels

        pie chart with inline labels and connection lines

        Picture of a very simple line chart made with react and d3

        Most basic line chart

        The most basic line chart one can make using d3 and react

        GIF of a line chart that animates between 2 dataset

        Line chart with dataset transition

        How to smoothly animate the transition between 2 dataset on a line chart

        line charts with synchronized cursors

        Synchronized cursors

        Add a cursor synchronized on all your charts

        Picture of a basic area chart made with React and D3

        Basic Area Chart

        Most basic version of an area chart made with react and d3.js

        picture of a basic stacked area plot made with react

        Basis stacked area chart

        Most basic version of a stacked area chart. Explains how to use the stack() function of d3.js

        Picture of a basic streamgraph made using Reacrt and d3.js

        Basic Streamgraph

        Most basic streamgraph one can build using d3 and react

        GIF of a streamgraph react component that supports hover effect

        Streamgraph with hover effect

        How to add a hover effect on a streamgraph to highlight a group

        GIF of a streamgraph

        Offset and Smoothing transition

        An interactive streamgraph example showing how to animate transition between the chart stacking features.

        GIF of a streamgraph with multiple interactive features

        Streamgraph application

        Streamgraph with a slider to zoom on a time stamp and with interactive inline legends

        Picture of a timeseries chart made with React and D3.js: scatterplot and line chart in use.

        Timeseries with moving average

        A scatterplot used for timeseries, with the moving average shown as a line chart on top.

        Picture of a very basic circle packing chart

        Most basic circular packing chart

        The most basic circular packing chart one can make using d3.js and React.

        Picture of a very basic circle packing chart with 2 levels of hierarchy

        Circular packing: 2 levels of hierarchy

        A simple circular packing chart with 2 levels of hierarchy built with React and d3.

        Picture of a circle packing chart made using the d3-force plugin

        Circle Pack with d3-force

        Another approach to build a circle packing chart using physical forces to compute node positions.

        Picture of a vertical arc diagram

        Vertical arc diagram

        The vertical version of the arc diagram is more convenient to display labels

        Picture of a very simple network chart built with React and D3.js.

        Most basic network chart

        Most basic network chart using the d3-force plugin to apply physical forces.

        Picture of a playground allowing to play with the various d3 forces

        Play with forces

        A playground to discover the effect of the various forces you can apply to your particles

        Picture of a force directed network chart showing character co-occurence in les miserables

        Force directed graph

        A force directed network chart showing character co-occurence in les miserables

        Contact

        👋 Hey, I'm Yan and I'm currently working on this project!

        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

        +All graphs

        All graphs

        Dataviz logo representing a DataArt2 chart.

        The react graph gallery displays hundreds of graphs made with React, often with the help of d3.js. This page provides an overview of all charts showcased in this gallery.

        Note that all chart types are presented on the welcome page of the gallery. It is probably a more convenient way to browse this website if you know what you are looking for!

        Useful links
        Picture of an empty chart area with X and Y axes

        Scales and axes

        How to map your data in a 2d space, and how to draw the axes

        GIF of a scatterplot with hover effect

        Scatterplot Hover effect

        How to add a hover effect to highlight a group on a scatterplot

        Most basic scatterplot made with react and d3

        Basic scatter plot

        Add circles to get a basic scatter plot

        Scatterplot with tooltip made with react and d3

        Add tooltip

        Get more details about each datapoint by adding a tooltip on hover

        Scatterplot with hover effect made with react and d3

        Add a hover effect

        Highlight a specific group on hover

        Real life example of a scatterplot made with react and d3

        Real life use-case

        Reproduction of a data wrapper chart representing countries CO2 data

        gif of a scatterplot with voronoi diagram for closest point detection

        Closest point detection with Voronoi

        Using a voronoi diagram in the scatterplot background is a smart way to efficiently find the mouse closest point

        a scatterplot made with react and rendered in canvas

        Scatterplot in Canvas

        Learn how to render a scatterplot in canvas to improve performances

        Picture of a simple heatmap made with react and d3.js

        Basic heatmap

        Most basic heatmap

        Picture of a heatmap with a tooltip that appears on hover

        Heatmap with tooltip

        Learn how to add a tooltip to a heatmap with react

        Picture of a continuous color scale built with d3.js

        Continuous color scale

        How to add a color legend to your chart that uses a continuous color scale

        Picture of a heatmap showing the effect of vaccination, built with react and d3

        Vaccination heatmap

        Reproduction of a famous vaccination heatmap using d3 and react

        Picture of a correlogram built with react and d3

        Basic correlogram

        Learn how to build a correlogram with react and d3

        Picture of a simple bubble plot with a legend made with react and d3.js

        Bubble plot

        Learn how to build a bubble plot with react and d3.js

        GIF of a bubble plot smoothly transitioning data

        Bubble plot data set transition

        How to smoothly animate the transition between dataset

        Picture of a hexbin chart made with React and d3.js

        Hexbin chart

        A hexbin chart split the figure in hexagons to show a 2d density

        Picture of a connected scatter plot made with React and d3.js

        Simple connected scatterplot

        A very simple connected scatter plot showing the evolution of 1 numeric variable

        gif of a violin plot smoothly transitioning to a boxplot using shape morphism

        Violin to Boxplot transition

        Using shape morphism to smoothly transition from a boxplot to a violin and reverse

        GIF showing a violin plot with varying bucket size

        Bucket size effect

        Interactive example showing the bucket size effect on a violin chart

        Picture of a violin shape built with react and d3

        Violin shape

        How to build the shape of a violin with SVG

        GIF showing a mirror transition between a boxplot and a violin plot

        Boxplot to Violin plot

        Interactive example showing the difference between a boxplot and a violin

        Picture of a basic violin chart built in react

        Basic violin plot

        Learn how to build a basic violin chart with d3 and react

        Picture of a violin plot with variable bucket size

        Violin with variable bucket size

        A violin plot with a slider to change the bucket size in use

        Picture of a basic density plot built with React and d3

        Basic density plot

        Most basic density plot built with React and d3

        Picture of a density plot with multiple groups

        Density plot with multiple groups

        How to add several groups on the same density plot

        Picture of a simple histogram made with react and d3.js

        Histogram

        Learn how to build a histogram with react and d3.js

        GIF of a histogram with animated data transition

        Histogram dataset transition

        How to animate the transition between datasets

        picture of a mirror histogram made with react and d3.js

        Mirror histogram

        Create a mirror histogram to compare the distribution of 2 groups in a dataset

        Picture of a histogram with small multiple built with react and d3.js

        Small multiple

        Create one panel per group to show its distribution separately

        Picture of a histogram with multiple groups built with react and d3.js

        Multiple groups

        A histogram with <b>multiple</b> groups displayed on the same axis.

        Picture of a boxplot with jitter built using react and d3.js

        Boxplot with jitter

        Add individual data points using jitter on top of the boxplot

        Picture of a box component, allowing to build a boxplot later on

        Boxplot shape

        How to build a boxplot shape in SVG

        Picture of a basic boxplot built with react and d3

        Basic boxplot

        How to build a basic boxplot with react

        Picture of a horizontal boxplot built with react and d3

        Horizontal boxplot

        How to build a horizontal boxplot with react

        Picture of a basic ridgeline chart built with react and d3

        Basic ridgeline chart

        Most basic version of a ridgeline plot

        Picture of a horizontal barplot made with React and d3

        Basic barplot

        Most basic barplot built with React and d3

        GIF of a data update on a React barplot

        Barplot dataset transition

        How to smoothly animate the transition between dataset

        Picture of a stacked barchart made with react and d3

        Horizontal Stacked Barplot

        Represent group and subgroup values by stacking the data

        Picture of a vertical stacked barchart made with react and d3

        Vertical Stacked Barplot

        Represent group and subgroup values by stacking the data

        Picture of a very simple lollipop chart

        Most basic lollipop plot

        Learn how to build a very simple lollipop chart with React and D3.js

        Picture of a very simple dumbbell chart

        Most basic dumbbell plot

        Learn how to build a very simple dumbbell chart with React and D3.js

        Picture of a lollipop chart with hover effect

        Lollipop with hover effect

        Learn how to add a hover effect to your lollipop chart

        Picture of a lollipop with buttons and animated transition

        Animation between dataset

        Learn how to build a smooth animated transition between 2 datasets

        Picture of the background grid of a radar chart

        Most basic line chart

        Learn how to build the background grid of a radar chart

        Picture of a very simple radar chart with 1 group only made with react and d3

        Most basic radar chart

        The most basic radar chart one can make using d3 and react

        Picture of a radar chart made with react and d3, with several groups displayed on the figure.

        Multi-group radar chart

        Radar chart with several groups displayed

        GIF of a radar chart, a line chart and a lollipop that animate between dataset

        Radar chart, line chart an lollipop with animated transition

        Three charts connected to same buttons, with smooth, synchronized animation when a button is clicked

        Picture of a simple treemap

        Basic treemap

        Most simple treemap, with 1 level of hierarchy only

        Picture of a simple treemap with 2 levels of hierarchy

        Treemap with 2 levels

        Simple treemap with 2 levels of hierarchy

        Picture of a simple treemap

        Hover effect

        Treemap with hover effect to highlight a group

        Picture of the most basic donut chart

        Basic Donut chart

        Most simple donut chart. No annotation, static figure.

        Picture of a simple donut chart with inline labels

        Inline labels

        Donut chart with inline labels and connection lines

        GIF of a donut chart with a hover effect

        Hover effect

        Donut chart with hover effect to highlight a slice

        GIF of a donut chart switching between 2 datasets

        Data transition

        How to smoothly transition dataset

        GIF of a donut chart switching between to a barplot and reverse

        Shape morphism

        Transition between a barplot and a donut chart

        Picture of the most basic pie chart

        Basic Pie chart

        Most simple pie chart. No annotation, static figure.

        Picture of a simple pie chart with inline labels

        Inline labels

        pie chart with inline labels and connection lines

        Picture of a very simple line chart made with react and d3

        Most basic line chart

        The most basic line chart one can make using d3 and react

        GIF of a line chart that animates between 2 dataset

        Line chart with dataset transition

        How to smoothly animate the transition between 2 dataset on a line chart

        line charts with synchronized cursors

        Synchronized cursors

        Add a cursor synchronized on all your charts

        Picture of a basic area chart made with React and D3

        Basic Area Chart

        Most basic version of an area chart made with react and d3.js

        picture of a basic stacked area plot made with react

        Basis stacked area chart

        Most basic version of a stacked area chart. Explains how to use the stack() function of d3.js

        Picture of a basic streamgraph made using Reacrt and d3.js

        Basic Streamgraph

        Most basic streamgraph one can build using d3 and react

        GIF of a streamgraph react component that supports hover effect

        Streamgraph with hover effect

        How to add a hover effect on a streamgraph to highlight a group

        GIF of a streamgraph

        Offset and Smoothing transition

        An interactive streamgraph example showing how to animate transition between the chart stacking features.

        GIF of a streamgraph with multiple interactive features

        Streamgraph application

        Streamgraph with a slider to zoom on a time stamp and with interactive inline legends

        Picture of a timeseries chart made with React and D3.js: scatterplot and line chart in use.

        Timeseries with moving average

        A scatterplot used for timeseries, with the moving average shown as a line chart on top.

        Picture of a very basic circle packing chart

        Most basic circular packing chart

        The most basic circular packing chart one can make using d3.js and React.

        Picture of a very basic circle packing chart with 2 levels of hierarchy

        Circular packing: 2 levels of hierarchy

        A simple circular packing chart with 2 levels of hierarchy built with React and d3.

        Picture of a circle packing chart made using the d3-force plugin

        Circle Pack with d3-force

        Another approach to build a circle packing chart using physical forces to compute node positions.

        Picture of a vertical arc diagram

        Vertical arc diagram

        The vertical version of the arc diagram is more convenient to display labels

        Picture of a very simple network chart built with React and D3.js.

        Most basic network chart

        Most basic network chart using the d3-force plugin to apply physical forces.

        Picture of a playground allowing to play with the various d3 forces

        Play with forces

        A playground to discover the effect of the various forces you can apply to your particles

        Picture of a force directed network chart showing character co-occurence in les miserables

        Force directed graph

        A force directed network chart showing character co-occurence in les miserables

        Contact

        👋 Hey, I'm Yan and I'm currently working on this project!

        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

          -
          \ No newline at end of file +
          \ No newline at end of file diff --git a/animation.html b/animation.html index a83d40a1..b2030ba1 100644 --- a/animation.html +++ b/animation.html @@ -1,4 +1,4 @@ -Animation

          Animation

          Dataviz logo representing a Anim chart.

          Animation is both the most challenging and the most exciting part of an interactive chart. Animation is like salt: use the right amount of it and your creation is a delight. Too much of it and it spoils the dish 🤌.

          There are many ways to animate the transition between 2 chart states. Here I suggest to use react-spring in combination with react andd3.js.

          Useful links

          Work in Progress

          This section is a work in progress. 🚧

          For now, it just lists all the charts using react-spring in the gallery.

          But I plan to write some complete tutorials on this passionating and complicated topic. You can subscribe to the project to know when it's ready!


          Subscribe


          GIF of a bubble plot smoothly transitioning data

          Bubble plot data set transition

          How to smoothly animate the transition between dataset

          gif of a violin plot smoothly transitioning to a boxplot using shape morphism

          Violin to Boxplot transition

          Using shape morphism to smoothly transition from a boxplot to a violin and reverse

          GIF showing a violin plot with varying bucket size

          Bucket size effect

          Interactive example showing the bucket size effect on a violin chart

          GIF showing a mirror transition between a boxplot and a violin plot

          Boxplot to Violin plot

          Interactive example showing the difference between a boxplot and a violin

          GIF of a histogram with animated data transition

          Histogram dataset transition

          How to animate the transition between datasets

          GIF of a data update on a React barplot

          Barplot dataset transition

          How to smoothly animate the transition between dataset

          GIF of a line chart that animates between 2 dataset

          Line chart with dataset transition

          How to smoothly animate the transition between 2 dataset on a line chart

          GIF of a streamgraph

          Offset and Smoothing transition

          An interactive streamgraph example showing how to animate transition between the chart stacking features.

          Contact

          👋 Hey, I'm Yan and I'm currently working on this project!

          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

          +Animation

          Animation

          Dataviz logo representing a Anim chart.

          Animation is both the most challenging and the most exciting part of an interactive chart. Animation is like salt: use the right amount of it and your creation is a delight. Too much of it and it spoils the dish 🤌.

          There are many ways to animate the transition between 2 chart states. Here I suggest to use react-spring in combination with react andd3.js.

          Useful links

          Work in Progress

          This section is a work in progress. 🚧

          For now, it just lists all the charts using react-spring in the gallery.

          But I plan to write some complete tutorials on this passionating and complicated topic. You can subscribe to the project to know when it's ready!


          Subscribe


          GIF of a bubble plot smoothly transitioning data

          Bubble plot data set transition

          How to smoothly animate the transition between dataset

          gif of a violin plot smoothly transitioning to a boxplot using shape morphism

          Violin to Boxplot transition

          Using shape morphism to smoothly transition from a boxplot to a violin and reverse

          GIF showing a violin plot with varying bucket size

          Bucket size effect

          Interactive example showing the bucket size effect on a violin chart

          GIF showing a mirror transition between a boxplot and a violin plot

          Boxplot to Violin plot

          Interactive example showing the difference between a boxplot and a violin

          GIF of a histogram with animated data transition

          Histogram dataset transition

          How to animate the transition between datasets

          GIF of a data update on a React barplot

          Barplot dataset transition

          How to smoothly animate the transition between dataset

          GIF of a line chart that animates between 2 dataset

          Line chart with dataset transition

          How to smoothly animate the transition between 2 dataset on a line chart

          GIF of a streamgraph

          Offset and Smoothing transition

          An interactive streamgraph example showing how to animate transition between the chart stacking features.

          Contact

          👋 Hey, I'm Yan and I'm currently working on this project!

          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

            -
            \ No newline at end of file +
            \ No newline at end of file diff --git a/arc-diagram.html b/arc-diagram.html index 0dc1ebbb..6b932f7d 100644 --- a/arc-diagram.html +++ b/arc-diagram.html @@ -1,4 +1,4 @@ -How to build an Arc Diagram with React and D3.

            Arc diagram

            Dataviz logo representing a Arc chart.

            An arc diagram is a special kind of network graph. It is consituted by nodes that represent entities and by links that show relationships between entities. In arc diagrams, nodes are displayed along a single axis and links are represented with arcs.

            This page is a step by step tutorial explaining how to build an Arc diagram component with React and D3.js. It comes with explanations and code sandboxes. It starts by simple concept like how to format the data and how to draw arcs in SVG, and then goes further with hover effect, tooltip and more.

            Useful links

            The Data

            Two layers of information are required to build an arc diagram: a list of nodes to build the circles and a list of links to build the arcs.

            Many different data structures can be used to store such information. In this tutorial I suggest to start with the following:

            export const data = {
            +How to build an Arc Diagram with React and D3.

            Arc diagram

            Dataviz logo representing a Arc chart.

            An arc diagram is a special kind of network graph. It is consituted by nodes that represent entities and by links that show relationships between entities. In arc diagrams, nodes are displayed along a single axis and links are represented with arcs.

            This page is a step by step tutorial explaining how to build an Arc diagram component with React and D3.js. It comes with explanations and code sandboxes. It starts by simple concept like how to format the data and how to draw arcs in SVG, and then goes further with hover effect, tooltip and more.

            Useful links

            The Data

            Two layers of information are required to build an arc diagram: a list of nodes to build the circles and a list of links to build the arcs.

            Many different data structures can be used to store such information. In this tutorial I suggest to start with the following:

            export const data = {
               nodes: [
                   { id: "Myriel", group: 'team1' },
                   { id: "Anne", group: 'team1' },
            @@ -100,4 +100,4 @@
             }

            I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




            Arc Diagram inspiration

            If you're looking for inspiration to create your next Arc Diagram, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

            dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Arc Diagram looks good!

            visit

            Variations

            Once you've understood how to build a basic arc diagram with d3 and react, it opens an infinite world of customization. Here are a few examples highlighting what it is possible to do with arc diagrams.

            Click on the overview below to get details and code.


            Picture of a vertical arc diagram

            Vertical arc diagram

            The vertical version of the arc diagram is more convenient to display labels

            Contact

            👋 Hey, I'm Yan and I'm currently working on this project!

            Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

              -
              \ No newline at end of file +
              \ No newline at end of file diff --git a/area-plot.html b/area-plot.html index d1a01617..6744d565 100644 --- a/area-plot.html +++ b/area-plot.html @@ -1,4 +1,4 @@ -Area charts with React

              Area charts

              Dataviz logo representing a Area chart.

              An area chart displays the evolution of one numeric variables. It is like a line chart, but with the area below the line being filled.

              This section describes how to build area charts on the web with d3.js and react. It starts very basic and then explains how to add more complex features like brushing, adding hover effects and more.

              Useful links

              The Data

              The dataset required to build a line chart is usually an array where each item is an object providing the x and the y values of the data point.


              Here is a minimal example:

              const data = [
              +Area charts with React

              Area charts

              Dataviz logo representing a Area chart.

              An area chart displays the evolution of one numeric variables. It is like a line chart, but with the area below the line being filled.

              This section describes how to build area charts on the web with d3.js and react. It starts very basic and then explains how to add more complex features like brushing, adding hover effects and more.

              Useful links

              The Data

              The dataset required to build a line chart is usually an array where each item is an object providing the x and the y values of the data point.


              Here is a minimal example:

              const data = [
                 {x:1, y: 90},
                 {x: 2, y: 12},
                 {x: 3, y: 34},
              @@ -16,4 +16,4 @@
               const areaPath = areaBuilder(data);

              Both a y0 and a y1 arguments are used. They provide both the bottom and the top position of the shape for each x position.

              The output areaPath can now be passed to a path resulting in the following area chart:

              A very basic area chart made using react and the area() function of d3.js

              Area chart inspiration

              If you're looking for inspiration to create your next Area chart, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

              dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Area chart looks good!

              visit



              Contact

              👋 Hey, I'm Yan and I'm currently working on this project!

              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                -
                \ No newline at end of file +
                \ No newline at end of file diff --git a/articles.html b/articles.html index 85b1651c..e6deaa8c 100644 --- a/articles.html +++ b/articles.html @@ -1,7 +1,7 @@ -How to make react and d3.js work together

                Dataviz Insights with React and D3.js


                While our gallery showcases a myriad of graph examples, this space is dedicated to delving into the intricacies of data visualization using React and D3.js.

                From unraveling the complexities of creating stacked bar plots with negative values to envisioning futuristic visualizations, our articles aim to enlighten, inspire, and guide you through the advanced realms of dataviz.

                Whether you're a seasoned developer or just starting out, these articles offer a wealth of knowledge to elevate your visualization game.

                Let's embark on this enlightening journey together! 🔥

                Responsiveness: a hook that makes your viz fits its container

                Viz components often take a width and a height properties as input. This blogposts explains how to build a wrapper around it that computes the parent's div dimension and pass it as propsRead more

                5 minutes read

                Fundamental
                Responsiveness
                Interaction

                Hover interaction

                Interactivity is an important part of dataviz when working in the browser. Adding a hover effect can improve the user experience by highlighting a series on the chart. Here are a couple way to implement it, always keeping performances in mind.Read more

                6 minutes read

                Fundamental
                Interaction

                🍔 Stacked barplot: how to deal with negative values

                A stacked barchart displays the values of items split in group and subgroups. It's a quite common chart type, but dealing with negative values in the dataset brings some interesting dataviz discussions.Read more

                6 minutes read

                Dataviz

                The next articles are currently in writing mode. ⬇️

                They will be released soon and you can be updated through my newsletter:


                +How to make react and d3.js work together

                Dataviz Insights with React and D3.js


                While our gallery showcases a myriad of graph examples, this space is dedicated to delving into the intricacies of data visualization using React and D3.js.

                From unraveling the complexities of creating stacked bar plots with negative values to envisioning futuristic visualizations, our articles aim to enlighten, inspire, and guide you through the advanced realms of dataviz.

                Whether you're a seasoned developer or just starting out, these articles offer a wealth of knowledge to elevate your visualization game.

                Let's embark on this enlightening journey together! 🔥

                Responsiveness: a hook that makes your viz fits its container

                Viz components often take a width and a height properties as input. This blogposts explains how to build a wrapper around it that computes the parent's div dimension and pass it as propsRead more

                5 minutes read

                Fundamental
                Responsiveness
                Interaction

                Hover interaction

                Interactivity is an important part of dataviz when working in the browser. Adding a hover effect can improve the user experience by highlighting a series on the chart. Here are a couple way to implement it, always keeping performances in mind.Read more

                6 minutes read

                Fundamental
                Interaction

                🍔 Stacked barplot: how to deal with negative values

                A stacked barchart displays the values of items split in group and subgroups. It's a quite common chart type, but dealing with negative values in the dataset brings some interesting dataviz discussions.Read more

                6 minutes read

                Dataviz

                The next articles are currently in writing mode. ⬇️

                They will be released soon and you can be updated through my newsletter:


                  Using react and d3.js: The 2 strategies

                  React modifies the DOM. So does d3.js. It makes it notoriously hard to have them work together. This blog post describes the 2 main strategies to use d3.js in a react app, with their pros and cons.

                  4 minutes read

                  Fundamental

                  Axes: build them with react (and a bit of d3)

                  Most of the viz types need some axes to be insightful. This post explains how to build them from a d3 scale, using the tick() method of d3 to create re-usable react components.

                  8 minutes read

                  Fundamental
                  Axis

                  Graph to graph interaction

                  Let's say you have a choropleth map on a side, a timeseries on the other. How can you add cross-viz interactions, like hovering a country to highlight its trend on the timeseries?

                  10 minutes read

                  Interaction
                  Advanced

                  Spring animations with react spring

                  It's often necessary to transition between 2 ys of a graph. React-spring is here to help, allowing to use spring animations easily.

                  5 minutes read

                  Fundamental
                  Animation

                  Dataset transition

                  Adding a smooth transition between dataset often adds a nice touch to your viz component. Let's see how to implement it with react-spring.

                  5 minutes read

                  Animation

                  Shape morphism: animate the transition between 2 distincts charts

                  How can we build a smooth transition between a pie chart and a barplot? The flubber js library allows to interpolate shapes and react-spring can animate this interpolation.

                  5 minutes read

                  Advanced
                  Animation

                  Improve chart performance with Canvas

                  Rendering a chart using svg is limited in term of performace. The DOM gets to crowded and updating it ends up being slow. Using canvas is the best workaround but you need to be able to draw your svg path using it!

                  5 minutes read

                  Fundamental
                  Canvas

                  Fix the blurry canvas on Retina screens

                  When using canvas for your viz, the result will be blurry on retina screens if you don't scale the canvas properly. Here is why and how to implement it.

                  5 minutes read

                  Canvas
                  Advanced

                  What is a color

                  There are so many ways to define a color when talking with a computer. Let's take a tour and see what's the most appropriate for a dataviz point of view.

                  3 minutes read

                  Fundamental
                  Axis

                  Buiding a futuristic viz

                  What makes a viz look from the future. And how to implement it with d3.js and reac.

                  3 minutes read

                  Fundamental
                  Axis

                  Contact

                  👋 Hey, I'm Yan and I'm currently working on this project!

                  Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                    -
                    \ No newline at end of file +
                    \ No newline at end of file diff --git a/barplot.html b/barplot.html index 896f6264..1fc2d143 100644 --- a/barplot.html +++ b/barplot.html @@ -1,4 +1,4 @@ -Barplot with React

                    Barplot

                    Dataviz logo representing a Bar chart.

                    A barplot displays a numeric value for several groups of a dataset using rectangles. This page is a step-by-step guide on how to build your own barplot for the web, using React and D3.js.

                    It starts with very basic concepts like data structure, scales and svg rectangle rendering. It then shows how to add interactivity to the chart with hover effects. Last but not least it explains how to build variations like the stacked barplot.

                    Useful links

                    The Data

                    The dataset required to build a barplot is usually an array where each item is an object providing the name and the value of the group.


                    Here is a minimal example

                    const data = [
                    +Barplot with React

                    Barplot

                    Dataviz logo representing a Bar chart.

                    A barplot displays a numeric value for several groups of a dataset using rectangles. This page is a step-by-step guide on how to build your own barplot for the web, using React and D3.js.

                    It starts with very basic concepts like data structure, scales and svg rectangle rendering. It then shows how to add interactivity to the chart with hover effects. Last but not least it explains how to build variations like the stacked barplot.

                    Useful links

                    The Data

                    The dataset required to build a barplot is usually an array where each item is an object providing the name and the value of the group.


                    Here is a minimal example

                    const data = [
                       {name:"Mark", value: 90},
                       {name:"Robert", value: 12},
                       {name:"Emily", value: 34},
                    @@ -66,4 +66,4 @@
                     }

                    I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                    Transition

                    When the dataset updates, it adds a nice touch to smoothly animate the transition. In the example below, changing the dataset will update the bar sizes and their positions on the Y axis to keep the ranking accurate.

                    Animation is a complicated topic in dataviz. We have to deal with updates (an element changes its features), enter (a new element appears) and exit (an element is not present anymore) patterns.

                    I suggest to rely on the react-spring library to help here. Please check this dedicated blogpost to get explanations about the code of this example.

                    Most basic barplot built with d3.js for scales, and react for rendering

                    Stacking

                    A stacked barplot is a variation of a barplot where an additional level of grouping is represented. Each bar represent the value of a group, for instance how much each my friend spent in the last month. Each bar is then subdivided, each part representing the value of a subgroup, for instance the category of expense.

                    D3 comes with a very handy stack() function. The 2 tutorials below explain how this function works, and how to use it to render a clean stacked barplot.

                    Picture of a stacked barchart made with react and d3

                    Horizontal Stacked Barplot

                    Represent group and subgroup values by stacking the data

                    Picture of a vertical stacked barchart made with react and d3

                    Vertical Stacked Barplot

                    Represent group and subgroup values by stacking the data

                    Vertical barplot

                    The vertical option is less common since it makes is much harder to read the labels. But if you really need it, it is just a matter of swaping the X and Y axes of the previous example.

                    This example will be publish soon, please subscribe below if you want to be notified.

                    Hover effect

                    This example will be publish soon, please subscribe to the newsletter if you want to be notified.

                    Variations

                    Let's go beyond the basic barcharts. Click on the overview images below to get details and code.


                    GIF of a donut chart switching between to a barplot and reverse

                    Shape morphism

                    Transition between a barplot and a donut chart

                    Contact

                    👋 Hey, I'm Yan and I'm currently working on this project!

                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                      -
                      \ No newline at end of file +
                      \ No newline at end of file diff --git a/boxplot.html b/boxplot.html index 8c1e95a9..a24f482e 100644 --- a/boxplot.html +++ b/boxplot.html @@ -1,4 +1,4 @@ -Boxplot with React

                      Boxplot

                      Dataviz logo representing a Box1 chart.

                      A boxplot summarizes the distribution of a numeric variable, often for several groups of a dataset. This page is a step-by-step guide on how to build a reusable boxplot component for the web using React and D3.js.

                      It starts by describing how to format the dataset and how to initialize the boxplot component. It then explains how to create a Box component that displays a single box. Finally, it shows how to render the boxplot and suggests a few variations. 🙇‍♂️.

                      Useful links

                      The Data 💾

                      The dataset used to build a boxplot is usually an array of objects. For each object, a name property provides the group name, and a value property provides the numeric value. It looks like this:

                      const data = [
                      +Boxplot with React

                      Boxplot

                      Dataviz logo representing a Box1 chart.

                      A boxplot summarizes the distribution of a numeric variable, often for several groups of a dataset. This page is a step-by-step guide on how to build a reusable boxplot component for the web using React and D3.js.

                      It starts by describing how to format the dataset and how to initialize the boxplot component. It then explains how to create a Box component that displays a single box. Finally, it shows how to render the boxplot and suggests a few variations. 🙇‍♂️.

                      Useful links

                      The Data 💾

                      The dataset used to build a boxplot is usually an array of objects. For each object, a name property provides the group name, and a value property provides the numeric value. It looks like this:

                      const data = [
                         { name: "A", value: 10.7577 },
                         { name: "A", value: 19.9273 },
                         { name: "B", value: 13.8917 },
                      @@ -190,4 +190,4 @@
                       }

                      I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                      Boxplot inspiration

                      If you're looking for inspiration to create your next Boxplot, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                      dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Boxplot looks good!

                      visit

                      Boxplot variations

                      Even if powerful to summarize the distribution of a numeric variable, the boxplot has flaws.

                      It indeed hides the underlying distribution. For instance, a low sample size or a bi-modal distribution is impossible to detect by reading the boxes only.

                      Jittering is a good workaround. Add all individual data points with low size, low opacity, and some random shift to the right or the left (jitter). The underlying distribution becomes instantly available.

                      Note that another good alternative is the violin plot, especially for a high sample size.

                      gif of a violin plot smoothly transitioning to a boxplot using shape morphism

                      Violin to Boxplot transition

                      Using shape morphism to smoothly transition from a boxplot to a violin and reverse

                      Picture of a violin plot with variable bucket size

                      Violin with variable bucket size

                      A violin plot with a slider to change the bucket size in use

                      Picture of a boxplot with jitter built using react and d3.js

                      Boxplot with jitter

                      Add individual data points using jitter on top of the boxplot

                      Picture of a horizontal boxplot built with react and d3

                      Horizontal boxplot

                      How to build a horizontal boxplot with react

                      Contact

                      👋 Hey, I'm Yan and I'm currently working on this project!

                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                        -
                        \ No newline at end of file +
                        \ No newline at end of file diff --git a/bubble-map.html b/bubble-map.html index ffea4c46..532eba94 100644 --- a/bubble-map.html +++ b/bubble-map.html @@ -1,4 +1,4 @@ -How to build a bubble map component with React and D3.

                        Bubble Map

                        Dataviz logo representing a BubbleMap chart.

                        A bubble map uses circles of different size to represent a numeric value on a territory. It displays one bubble per geographic coordinate, or one bubble per region.

                        This page explains how to build bubble maps for the web using d3.js and react. Several tools can be used to display the background map as shown in the dedicated section. Circles are then computed with d3 and render using SVG or canvas elements with react.

                        Examples start easy and add layers of complexity progressively. You will always find explanations and code sandboxes for each step.

                        Useful links

                        The Data

                        Two pieces of information are required to build a bubble map:

                        → Geographic information

                        The first thing you need is the 2d coordinates of the boundaries of the regions you want to represent. If you are trying to build a world map, you need to know where the country boundaries are located 🤷‍♀️.

                        Several formats exist to store such a piece of information. When working with d3.js, the expected format is geoJSON. A geoJSON file looks pretty much like this:


                        {
                        +How to build a bubble map component with React and D3.

                        Bubble Map

                        Dataviz logo representing a BubbleMap chart.

                        A bubble map uses circles of different size to represent a numeric value on a territory. It displays one bubble per geographic coordinate, or one bubble per region.

                        This page explains how to build bubble maps for the web using d3.js and react. Several tools can be used to display the background map as shown in the dedicated section. Circles are then computed with d3 and render using SVG or canvas elements with react.

                        Examples start easy and add layers of complexity progressively. You will always find explanations and code sandboxes for each step.

                        Useful links

                        The Data

                        Two pieces of information are required to build a bubble map:

                        → Geographic information

                        The first thing you need is the 2d coordinates of the boundaries of the regions you want to represent. If you are trying to build a world map, you need to know where the country boundaries are located 🤷‍♀️.

                        Several formats exist to store such a piece of information. When working with d3.js, the expected format is geoJSON. A geoJSON file looks pretty much like this:


                        {
                           "type": "FeatureCollection",
                           "features": [
                             {
                        @@ -157,4 +157,4 @@
                         };

                        A bubble chart component that smoothly animates changes between datasets.

                        Animation in dataviz using React is a big topic. It's impossible to go in-depth here! I will publish a dedicated blog post on the topic soon. Please subscribe to the newsletter if you want to be notified.

                        Bubble inspiration

                        If you're looking for inspiration to create your next Bubble, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                        dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Bubble looks good!

                        visit

                        Contact

                        👋 Hey, I'm Yan and I'm currently working on this project!

                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                          -
                          \ No newline at end of file +
                          \ No newline at end of file diff --git a/bubble-plot.html b/bubble-plot.html index abc57b25..5d4d78fb 100644 --- a/bubble-plot.html +++ b/bubble-plot.html @@ -1,4 +1,4 @@ -Bubble plot with React

                          Bubble plot

                          Dataviz logo representing a BubblePlot chart.

                          A bubble plot is an extension of a scatterplot, where each circle has its size proportional to a numeric value. This page is a step-by-step guide on how to build your own bubble chart for the web, using React and D3.js.

                          This page focuses on the implementation of features that are different from the scatterplot that has its dedicated section. It describes how the dataset differs, how the circle size can be mapped to a numeric value, and how to explicit it using a legend. Last but not least it explains how to add interactivity: hover effect, tooltip, and dataset transition. 🙇‍♂️.

                          Useful links

                          The Data

                          The dataset used to build a bubble plot is usually an array of objects where each object is a data point. For each object, at least 3 properties are required.

                          Two properties are used for the X and Y axis, the third one is used for the circle size.

                          Note that you can add more properties to the object. For instance, a name can be displayed in the tooltip, and a group can be used to color the bubbles.

                          const data = [
                          +Bubble plot with React

                          Bubble plot

                          Dataviz logo representing a BubblePlot chart.

                          A bubble plot is an extension of a scatterplot, where each circle has its size proportional to a numeric value. This page is a step-by-step guide on how to build your own bubble chart for the web, using React and D3.js.

                          This page focuses on the implementation of features that are different from the scatterplot that has its dedicated section. It describes how the dataset differs, how the circle size can be mapped to a numeric value, and how to explicit it using a legend. Last but not least it explains how to add interactivity: hover effect, tooltip, and dataset transition. 🙇‍♂️.

                          Useful links

                          The Data

                          The dataset used to build a bubble plot is usually an array of objects where each object is a data point. For each object, at least 3 properties are required.

                          Two properties are used for the X and Y axis, the third one is used for the circle size.

                          Note that you can add more properties to the object. For instance, a name can be displayed in the tooltip, and a group can be used to color the bubbles.

                          const data = [
                             {
                               "x": 43.828,
                               "y": 31889923,
                          @@ -109,4 +109,4 @@
                           };
                          30405060708090

                          A bubble chart component that smoothly animates changes between datasets.

                          Animation in dataviz using React is a big topic. It's impossible to go in-depth here! I will publish a dedicated blog post on the topic soon. Please subscribe to the newsletter if you want to be notified.

                          Real-life application

                          Let's apply the concepts learned above to a real-life example.

                          I like this scatterplot originally published on the data wrapper blog. It shows a strong correlation between vulnerability to climate change and CO2 emissions.


                          The chart has several features that are interesting to reproduce from a technical point of view:

                          • Custom annotation: only a fraction of the country names are written
                          • Hover effect: the hovered country is highlighted with a black stroke. After a short delay, countries of other groups are dimmed. Note that the effect is triggered once the mouse approaches the marker, no need to be perfectly on top.
                          • Tooltip: highly customized and linked to the mouse position

                          The countries with the highest vulnerability to climate change have the lowest CO2 emissions

                          All countries sorted by their vulnerability and readiness to climate change. The size shows the CO2 emission per person in that country.

                          High ReadinessLow ReadinessQatarBahrainU.S.Trinidad and TobagoCzech RepublicSingaporeNorwayIndiaSudanChadSomalia

                          Reproduction of a chart originally published by Data Wrapper using react and d3.js.

                          Variations

                          Once you've understood how to build a basic bubble chart with d3 and react, it opens an infinite world of customization. Here are a few examples using the same concepts.

                          Click on the overview below to get details and code.


                          Picture of a circle packing chart made using the d3-force plugin

                          Circle Pack with d3-force

                          Another approach to build a circle packing chart using physical forces to compute node positions.



                          Contact

                          👋 Hey, I'm Yan and I'm currently working on this project!

                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                            -
                            \ No newline at end of file +
                            \ No newline at end of file diff --git a/build-axis-with-react.html b/build-axis-with-react.html index bcf1e43e..9954d861 100644 --- a/build-axis-with-react.html +++ b/build-axis-with-react.html @@ -1,4 +1,4 @@ -Building graph axes with React (and d3.js)

                            Building graph axes with React (and d3.js)


                            This post explains how to build axes from d3 scales for a chart. It relies on the tick() method to compute the tick positions and use react for the rendering. The code of the BottomAxis and LeftAxiscomponents is provided, together with some reproducible examples.

                            This minimal example uses scaleLinear() to compute the scales, ticks() to compute tick positions and react to render the axes.

                            Bottom Axis

                            The code snippet below builds a AxisBottom component. It is very much inspired from this blogpost by Amelia Wattenberger. I've just changed a few things, notably passing a scale as input instead of a range and a domain.

                            The logic mainly relies on the ticks() method of a d3 scale. It takes a target number of ticks as input, find the most appropriate way to build smart ticks based on this target, and returns an array with all the tick positions.

                            What follows is just some svg drawings based on those tick positions.

                            const TICK_LENGTH = 6;
                            +Building graph axes with React (and d3.js)

                            Building graph axes with React (and d3.js)


                            This post explains how to build axes from d3 scales for a chart. It relies on the tick() method to compute the tick positions and use react for the rendering. The code of the BottomAxis and LeftAxiscomponents is provided, together with some reproducible examples.

                            This minimal example uses scaleLinear() to compute the scales, ticks() to compute tick positions and react to render the axes.

                            Bottom Axis

                            The code snippet below builds a AxisBottom component. It is very much inspired from this blogpost by Amelia Wattenberger. I've just changed a few things, notably passing a scale as input instead of a range and a domain.

                            The logic mainly relies on the ticks() method of a d3 scale. It takes a target number of ticks as input, find the most appropriate way to build smart ticks based on this target, and returns an array with all the tick positions.

                            What follows is just some svg drawings based on those tick positions.

                            const TICK_LENGTH = 6;
                             
                             export const AxisBottom = ({ xScale, pixelsPerTick }) => {
                               const range = xScale.range();
                            @@ -88,4 +88,4 @@
                             

                            Contact

                            👋 Hey, I'm Yan and I'm currently working on this project!

                            Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                              -
                              \ No newline at end of file +
                              \ No newline at end of file diff --git a/cartogram.html b/cartogram.html index b8c26963..2944f1f0 100644 --- a/cartogram.html +++ b/cartogram.html @@ -1,4 +1,4 @@ -How to build a cartogram with React and D3.

                              Cartogram

                              Dataviz logo representing a Cartogram chart.

                              A cartogram is a map in which the geometry of regions is distorted in order to convey the information of an alternate variable.

                              It is possible to build a Cartogram react component thanks to a js library called topogram. This page provides step-by-step explanations on how to use the library based on a geoJson file with the help of d3.js for manipulating such a data source.

                              Useful links

                              The Data

                              Probably uses the same as for a choropleth map or for a bubble map.

                              The Topogram library

                              As far as I can tell the best way to create a cartogram in JS is the topogram library.

                              However it looks like there is no easy way to install it using npm. The easiest way is probably to clone the repo and create the build, or to copy the content of the cartogram.js file.

                              ToDoAdd example of usage of the topogram lib

                              Contact

                              👋 Hey, I'm Yan and I'm currently working on this project!

                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                              +How to build a cartogram with React and D3.

                              Cartogram

                              Dataviz logo representing a Cartogram chart.

                              A cartogram is a map in which the geometry of regions is distorted in order to convey the information of an alternate variable.

                              It is possible to build a Cartogram react component thanks to a js library called topogram. This page provides step-by-step explanations on how to use the library based on a geoJson file with the help of d3.js for manipulating such a data source.

                              Useful links

                              The Data

                              Probably uses the same as for a choropleth map or for a bubble map.

                              The Topogram library

                              As far as I can tell the best way to create a cartogram in JS is the topogram library.

                              However it looks like there is no easy way to install it using npm. The easiest way is probably to clone the repo and create the build, or to copy the content of the cartogram.js file.

                              ToDoAdd example of usage of the topogram lib

                              Contact

                              👋 Hey, I'm Yan and I'm currently working on this project!

                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                -
                                \ No newline at end of file +
                                \ No newline at end of file diff --git a/chord-diagram.html b/chord-diagram.html index d0768948..975adf61 100644 --- a/chord-diagram.html +++ b/chord-diagram.html @@ -1,4 +1,4 @@ -How to build a chord diagram with React and D3.

                                Chord diagram

                                Dataviz logo representing a Chord chart.

                                A chord diagram represents flows between several entities called nodes. Each node is represented by a fragment on the outer part of the circular layout. Then, arcs are drawn between each entities. The size of the arc is proportional to the importance of the flow..

                                Building a chord diagram with React and D3.js relies on the d3-chord module that computes the node and arc positions for us. React can then be used to draw everything in SVG. This page is a step by step tutorial with code sandboxes. It will teach you how to build a ChordDiagram component.

                                Useful links

                                The Data

                                The dataset required to build a chord diagram is a square matrix. It has a dimension of n x n where n is the number of nodes.

                                In javascript, this matrix is represented as an array of n array. Each individual array also has n items. The matrix of flow has a direction: the second item of the third row gives the flow from element 2 to element 3.

                                Usually an additional array is provided, giving the name of each node.


                                Here is a minimal example of the data structure:

                                // matrix of flow
                                +How to build a chord diagram with React and D3.

                                Chord diagram

                                Dataviz logo representing a Chord chart.

                                A chord diagram represents flows between several entities called nodes. Each node is represented by a fragment on the outer part of the circular layout. Then, arcs are drawn between each entities. The size of the arc is proportional to the importance of the flow..

                                Building a chord diagram with React and D3.js relies on the d3-chord module that computes the node and arc positions for us. React can then be used to draw everything in SVG. This page is a step by step tutorial with code sandboxes. It will teach you how to build a ChordDiagram component.

                                Useful links

                                The Data

                                The dataset required to build a chord diagram is a square matrix. It has a dimension of n x n where n is the number of nodes.

                                In javascript, this matrix is represented as an array of n array. Each individual array also has n items. The matrix of flow has a direction: the second item of the third row gives the flow from element 2 to element 3.

                                Usually an additional array is provided, giving the name of each node.


                                Here is a minimal example of the data structure:

                                // matrix of flow
                                 const data = [
                                   [11975,  0, 8916, 2868],
                                   [ 1951, 10048, 2060, 6171],
                                @@ -79,4 +79,4 @@
                                 }

                                I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                Chord Diagram inspiration

                                If you're looking for inspiration to create your next Chord Diagram, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Chord Diagram looks good!

                                visit

                                First chord diagram

                                I suggest 2 improvements to get a descent chord diagram:

                                → Colors

                                Pretty straightforward to implement. You just need to create an array of colors. Then, for each item to draw the index is always available. It can be used to retrieve the color in the color array.

                                → Labels

                                A new prop needs to be passed to the component with a list of names for the nodes. I suggest to position labels as for a donut chart but many other possibilities are available.

                                Connections between nodes are drawn thanks to the ribbon() function of d3.js.

                                ToDoAdd section on hover effect
                                ToDoTalk about chordDirected() and chordTranspose()

                                Contact

                                👋 Hey, I'm Yan and I'm currently working on this project!

                                Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                  -
                                  \ No newline at end of file +
                                  \ No newline at end of file diff --git a/choropleth-map.html b/choropleth-map.html index fa1fbfa8..8bf45d54 100644 --- a/choropleth-map.html +++ b/choropleth-map.html @@ -1,4 +1,4 @@ -Building Choropleth Maps with React and D3.js: A Step-by-Step Tutorial

                                  Choropleth Map

                                  Dataviz logo representing a Choropleth chart.

                                  A choropleth map displays divided geographical areas or regions that are coloured in relation to a numeric variable. It enables the study of how a variable evolves across a geographical area.

                                  Once you understood how to draw a map background from a geoJson file, it is just a matter of coloring each region with the appropriate color. On top of this, it is advised to add a color legend and some interactivity (hover effect and tooltip).

                                  This webpage is a tutorial coming with explanation and code sandboxes. It explains how to build interactive choropleth map with React and D3.js.

                                  Useful links

                                  The Data

                                  Two pieces of information are required to build a choropleth map:

                                  → Geographic information

                                  The first thing you need to build a choropleth map is the 2d coordinates of the boundaries of the regions you want to represent. If you are trying to build a world map, you need to know where the country boundaries are located 🤷‍♀️.

                                  Several formats exist to store such a piece of information. When working with d3.js, the expected format is geoJSON. A geoJSON file looks pretty much like this:


                                  {
                                  +Building Choropleth Maps with React and D3.js: A Step-by-Step Tutorial

                                  Choropleth Map

                                  Dataviz logo representing a Choropleth chart.

                                  A choropleth map displays divided geographical areas or regions that are coloured in relation to a numeric variable. It enables the study of how a variable evolves across a geographical area.

                                  Once you understood how to draw a map background from a geoJson file, it is just a matter of coloring each region with the appropriate color. On top of this, it is advised to add a color legend and some interactivity (hover effect and tooltip).

                                  This webpage is a tutorial coming with explanation and code sandboxes. It explains how to build interactive choropleth map with React and D3.js.

                                  Useful links

                                  The Data

                                  Two pieces of information are required to build a choropleth map:

                                  → Geographic information

                                  The first thing you need to build a choropleth map is the 2d coordinates of the boundaries of the regions you want to represent. If you are trying to build a world map, you need to know where the country boundaries are located 🤷‍♀️.

                                  Several formats exist to store such a piece of information. When working with d3.js, the expected format is geoJSON. A geoJSON file looks pretty much like this:


                                  {
                                     "type": "FeatureCollection",
                                     "features": [
                                       {
                                  @@ -88,4 +88,4 @@
                                   }, [width, height, colorScale]);

                                  Then you probably want to add some ticks on top of the color graduation to make it insightful.

                                  Fortunately, the d3 linearScale comes with a handy tick() function. Basically, calling xScale.ticks(4) will create an array with approximately 4 items, each providing everything you need to draw a smartly located tick.

                                  Color Legend is a big topic. There is much more to say about it and I'll post a complete blog post on the topic soon. Subscribe to the gallery if interested!

                                  ToDoHover effect section
                                  ToDoTalk more about color scale. Hover effect linked with color scale
                                  ToDoCanvas version. Add tooltip.

                                  Contact

                                  👋 Hey, I'm Yan and I'm currently working on this project!

                                  Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                    -
                                    \ No newline at end of file +
                                    \ No newline at end of file diff --git a/circular-barplot.html b/circular-barplot.html index 2f5325cd..5cf5badd 100644 --- a/circular-barplot.html +++ b/circular-barplot.html @@ -1,4 +1,4 @@ -Circular Barplot with React

                                    Circular Barplot

                                    Dataviz logo representing a CircularBarplot chart.

                                    A circular barplot is a variation of a barplot where bars are displayed around a circle using polar coordinates. It is a less accurate representation of the data, but provides a strong eye-catching effect.

                                    This page describes how to deal with radial coordinates with d3.js and react to build a circular barplot. It's a step by step tutorial with several interactive sandboxes.

                                    Useful links

                                    The Data

                                    The dataset required to build a circular barplot is usually an array where each item is an object providing the name and the value of the group.


                                    Here is a minimal example

                                    const data = [
                                    +Circular Barplot with React

                                    Circular Barplot

                                    Dataviz logo representing a CircularBarplot chart.

                                    A circular barplot is a variation of a barplot where bars are displayed around a circle using polar coordinates. It is a less accurate representation of the data, but provides a strong eye-catching effect.

                                    This page describes how to deal with radial coordinates with d3.js and react to build a circular barplot. It's a step by step tutorial with several interactive sandboxes.

                                    Useful links

                                    The Data

                                    The dataset required to build a circular barplot is usually an array where each item is an object providing the name and the value of the group.


                                    Here is a minimal example

                                    const data = [
                                       {name:"Mark", value: 90},
                                       {name:"Robert", value: 12},
                                       {name:"Emily", value: 34},
                                    @@ -41,7 +41,7 @@
                                         startAngle: xScale(group.name),
                                         endAngle: xScale(group.name) + xScale.bandwidth(),
                                       });
                                    -})

                                    → Rendering

                                    Not much to add. Just include the paths in a svg element. Remember that 0,0 is the center of the chart instead of being the top-left corner. So we need to apply a translate at some point.

                                    Most basic circular barplot built with d3.js and react, using radial coordinates and path instead of rect.

                                    That's a good start but it looks pretty much like a snail so far. Let's make it a real chart with labels and values.

                                    Labels

                                    It is necessary to add a text element to show the name of each bar.

                                    We need those labels to be readable (like not written upside down). So a bit of logic is necessary to determine wether or not a label must be flipped, and how to position it properly.

                                    To do so it is necessary to switch from radians (use for the xScale) to degrees (used for the transform property).

                                    Please check the code below for full explanation.

                                    RemiJeanNinaNicolasLucasMarkLeaneMelanieMarionEmilyMelTiboBalkisGabrielSophieRobertPaul

                                    Add some labels to each bar of the circular barchart to make it insightful

                                    Circular Barplot inspiration

                                    If you're looking for inspiration to create your next Circular Barplot, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                    dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Circular Barplot looks good!

                                    visit

                                    Stacking

                                    Stacking is a process where a chart is broken up across more than one categoric variables which make up the whole.

                                    d3 comes with some handy functions for stacking. The process is extensively described in this stacked barplot tutorial. There is nothing really different to make it circular and here is a working sandbox to discover the code.

                                    JuliaEmmaKaylaBrookeRachelGraceMichelleFaithMaryHaleyNicoleKatelynMeganTaylorAlexandraChloeSydneyErinJasmineCarolineMakaylaJacquelineSavannahDanielleIsabellaKaitlynSarahRebeccaSaraAnnaMadelineAndreaPaigeKatherineBaileyJennaAllisonSierraDestinyOliviaJessicaVanessaEmilyKimberlyAmandaMariaHaileyNatalieVictoriaAlyssaJordanMackenzieSophiaBrittanyShelbyAmberJenniferElizabethAlexisMadisonLaurenCourtneyMorganSamanthaBriannaHannahAshleyStephanieAbigailGabrielle

                                    Add some labels to each bar of the circular barchart to make it insightful



                                    Contact

                                    👋 Hey, I'm Yan and I'm currently working on this project!

                                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                    +})

                                    → Rendering

                                    Not much to add. Just include the paths in a svg element. Remember that 0,0 is the center of the chart instead of being the top-left corner. So we need to apply a translate at some point.

                                    Most basic circular barplot built with d3.js and react, using radial coordinates and path instead of rect.

                                    That's a good start but it looks pretty much like a snail so far. Let's make it a real chart with labels and values.

                                    Labels

                                    It is necessary to add a text element to show the name of each bar.

                                    We need those labels to be readable (like not written upside down). So a bit of logic is necessary to determine wether or not a label must be flipped, and how to position it properly.

                                    To do so it is necessary to switch from radians (use for the xScale) to degrees (used for the transform property).

                                    Please check the code below for full explanation.

                                    RemiJeanNinaNicolasLucasMarkLeaneMelanieMarionEmilyMelTiboBalkisGabrielSophieRobertPaul

                                    Add some labels to each bar of the circular barchart to make it insightful

                                    Circular Barplot inspiration

                                    If you're looking for inspiration to create your next Circular Barplot, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                    dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Circular Barplot looks good!

                                    visit

                                    Stacking

                                    Stacking is a process where a chart is broken up across more than one categoric variables which make up the whole.

                                    d3 comes with some handy functions for stacking. The process is extensively described in this stacked barplot tutorial. There is nothing really different to make it circular and here is a working sandbox to discover the code.

                                    HannahLaurenBriannaKatherineMichelleFaithAshleyAndreaBaileyJuliaMackenzieMariaMorganEmilyAbigailCourtneyKimberlyDanielleSarahJenniferEmmaShelbyNicoleOliviaMarySamanthaMakaylaSavannahErinGraceAnnaDestinyTaylorKaitlynPaigeSaraBrittanyMadisonVanessaElizabethJordanChloeKaylaAlexisNatalieJacquelineBrookeSydneyAlyssaRachelVictoriaCarolineHaleySierraAmberAlexandraJennaGabrielleAllisonHaileyKatelynIsabellaAmandaMeganRebeccaStephanieMadelineJasmineJessicaSophia

                                    Add some labels to each bar of the circular barchart to make it insightful



                                    Contact

                                    👋 Hey, I'm Yan and I'm currently working on this project!

                                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                      -
                                      \ No newline at end of file +
                                      \ No newline at end of file diff --git a/circular-packing.html b/circular-packing.html index 53bebc41..be3526fc 100644 --- a/circular-packing.html +++ b/circular-packing.html @@ -1,4 +1,4 @@ -Circular Packing chart with React

                                      Circular Packing

                                      Dataviz logo representing a CircularPacking chart.

                                      A circular packing chart displays a hierarchical dataset as a set of nested circles, each circle representing a node of the data structure. Size is usually proportional to a numeric variable.

                                      This page is a tutorial teaching how to create a circle pack chart with d3.js and React. It starts with a very basic version, adds some levels of nesting and finishes with usual customization like animating the transition between datasets.

                                      Useful links

                                      The Data

                                      The dataset describes a hierarchy using a recursive structure. It is similar to a dendrogram or to a treemap.

                                      Each item in this structure is called a node, the lowest nodes of the hierarchy being called leaves. The dataset is an object that has at least 3 properties: name, value and children. Children is an array of nodes that have this structure too.


                                      Here is a minimal example of the data structure:

                                      const data = {
                                      +Circular Packing chart with React

                                      Circular Packing

                                      Dataviz logo representing a CircularPacking chart.

                                      A circular packing chart displays a hierarchical dataset as a set of nested circles, each circle representing a node of the data structure. Size is usually proportional to a numeric variable.

                                      This page is a tutorial teaching how to create a circle pack chart with d3.js and React. It starts with a very basic version, adds some levels of nesting and finishes with usual customization like animating the transition between datasets.

                                      Useful links

                                      The Data

                                      The dataset describes a hierarchy using a recursive structure. It is similar to a dendrogram or to a treemap.

                                      Each item in this structure is called a node, the lowest nodes of the hierarchy being called leaves. The dataset is an object that has at least 3 properties: name, value and children. Children is an array of nodes that have this structure too.


                                      Here is a minimal example of the data structure:

                                      const data = {
                                         type: 'node',
                                         name: "boss",
                                         value: 2300,
                                      @@ -55,4 +55,4 @@
                                       }

                                      This component uses the useSpring hook of react spring to interpolate the cx, cy and r properties. Those values are passed to a special svg element (animated.circle) that does the animation.

                                      Animating the transition between 2 similar dataset with react and d3.js (for rendering) and react spring (for animation).

                                      Animation in dataviz using React is a big topic. It's impossible to go in depth here! I will publish a dedicated blog post on the topic soon. Please subscribe to the newsletter if you want to be notified.

                                      Subscribe



                                      ToDoZoom on next level of hierarchy
                                      ToDoWrite label along circle with curve
                                      ToDoBetter dataset transition where circle keep position

                                      Variations

                                      Once you've understood how to build a basic circular packing with d3 and react, it opens an infinite world of customization. Here are a few examples using the same concepts.

                                      Click on the overview below to get details and code.


                                      Picture of a circle packing chart made using the d3-force plugin

                                      Circle Pack with d3-force

                                      Another approach to build a circle packing chart using physical forces to compute node positions.



                                      Contact

                                      👋 Hey, I'm Yan and I'm currently working on this project!

                                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                        -
                                        \ No newline at end of file +
                                        \ No newline at end of file diff --git a/connected-scatter-plot.html b/connected-scatter-plot.html index 8dc7fd95..ea8c9621 100644 --- a/connected-scatter-plot.html +++ b/connected-scatter-plot.html @@ -1,4 +1,4 @@ -Connected scatterplot with React and D3.js

                                        Connected Scatterplot

                                        Dataviz logo representing a ScatterConnected chart.

                                        A connected scatterplot displays the evolution of a numeric variable. Data points are represented by a dot and connected with straight line segments. A variation of the connected scatterplot allows to study the evolution of 2 numeric variables together.

                                        This page explains how to build a connected scatterplot using react andd3.js. It is highly connected with the line chart section of the gallery but provides further information concerning connected scatterplot specific features.

                                        Useful links

                                        The Data

                                        The dataset required to build a connected scatterplot is the same as for a line chart. It is usually an array where each item is an object providing the x and the y values of the data point.


                                        Here is a minimal example:

                                        const data = [
                                        +Connected scatterplot with React and D3.js

                                        Connected Scatterplot

                                        Dataviz logo representing a ScatterConnected chart.

                                        A connected scatterplot displays the evolution of a numeric variable. Data points are represented by a dot and connected with straight line segments. A variation of the connected scatterplot allows to study the evolution of 2 numeric variables together.

                                        This page explains how to build a connected scatterplot using react andd3.js. It is highly connected with the line chart section of the gallery but provides further information concerning connected scatterplot specific features.

                                        Useful links

                                        The Data

                                        The dataset required to build a connected scatterplot is the same as for a line chart. It is usually an array where each item is an object providing the x and the y values of the data point.


                                        Here is a minimal example:

                                        const data = [
                                           {x:1, y: 90},
                                           {x: 2, y: 12},
                                           {x: 3, y: 34},
                                        @@ -54,4 +54,4 @@
                                         }

                                        I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                        ToDoadd links to line chart examples
                                        ToDoreproduce the connected scatter from the state of JS survey

                                        Connected Scatter inspiration

                                        If you're looking for inspiration to create your next Connected Scatter, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                        dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Connected Scatter looks good!

                                        visit

                                        Contact

                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                          -
                                          \ No newline at end of file +
                                          \ No newline at end of file diff --git a/connection-map.html b/connection-map.html index 7f4ccc0c..dfc2e9fd 100644 --- a/connection-map.html +++ b/connection-map.html @@ -1,4 +1,4 @@ -How to build a connection map component with React and D3.

                                          Connection Map

                                          Dataviz logo representing a ConnectedMap chart.

                                          A connection map is a map where links between geographical positions are represented using lines or arcs. Most of the time, great circles are used.

                                          This page explains how to build connection maps for the web using d3.js and react. Several tools can be used to display the background map as shown in the dedicated section. The path used to show the connection can then be computed thanks to the geoPath() function of d3.

                                          Useful links

                                          The Data

                                          Two pieces of information are required to build a connection map:

                                          → Geographic information

                                          The first thing you need is the 2d coordinates of the boundaries of the regions you want to represent. If you are trying to build a world map, you need to know where the country boundaries are located 🤷‍♀️.

                                          Several formats exist to store such a piece of information. When working with d3.js, the expected format is geoJSON. A geoJSON file looks pretty much like this:


                                          {
                                          +How to build a connection map component with React and D3.

                                          Connection Map

                                          Dataviz logo representing a ConnectedMap chart.

                                          A connection map is a map where links between geographical positions are represented using lines or arcs. Most of the time, great circles are used.

                                          This page explains how to build connection maps for the web using d3.js and react. Several tools can be used to display the background map as shown in the dedicated section. The path used to show the connection can then be computed thanks to the geoPath() function of d3.

                                          Useful links

                                          The Data

                                          Two pieces of information are required to build a connection map:

                                          → Geographic information

                                          The first thing you need is the 2d coordinates of the boundaries of the regions you want to represent. If you are trying to build a world map, you need to know where the country boundaries are located 🤷‍♀️.

                                          Several formats exist to store such a piece of information. When working with d3.js, the expected format is geoJSON. A geoJSON file looks pretty much like this:


                                          {
                                             "type": "FeatureCollection",
                                             "features": [
                                               {
                                          @@ -100,4 +100,4 @@
                                           }

                                          I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                          Connection inspiration

                                          If you're looking for inspiration to create your next Connection, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                          dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Connection looks good!

                                          visit
                                          ToDodraw with Canvas
                                          ToDoapplication to a real dataset
                                          ToDohover effect: hover over a city to highlight its connections

                                          Contact

                                          👋 Hey, I'm Yan and I'm currently working on this project!

                                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                            -
                                            \ No newline at end of file +
                                            \ No newline at end of file diff --git a/correlogram.html b/correlogram.html index 54860901..521afb7f 100644 --- a/correlogram.html +++ b/correlogram.html @@ -1,4 +1,4 @@ -Correlogram with React

                                            Correlogram

                                            Dataviz logo representing a Correlogram chart.

                                            In this blog post, we will be exploring how to build a correlogram with React and D3.js. A correlogram is a graphical representation of the correlation matrix for a given dataset. It is a useful tool for visualizing the relationships between different variables in a dataset, and can help identify potential correlations that may not be immediately obvious.

                                            Building a correlogram with React and D3.js allows us to create a highly interactive and customizable visualization. We will be able to use React's powerful component-based approach to build our visualization, while leveraging the flexibility and power of D3.js to create a dynamic and engaging visual representation of our data.

                                            Useful links

                                            Correlogram = scatter plot + histogram

                                            A correlogram uses histograms to show the distribution of each numeric variable on the diagonal of the matrix. It uses scatter plots to show the relationship of each pair of variable on every other cells.

                                            As a result, it is required to understand how to build a histogram and a scatter plot component using React and d3.js! In this post, we will just show how to leverage those reusable components to build a correlogram.

                                            Picture of a simple histogram made with react and d3.js

                                            Histogram

                                            Learn how to build a histogram with react and d3.js

                                            Picture of a simple scatter plot made with react and d3.js

                                            Scatter plot

                                            Learn how to build a scatter plot with react and d3.js

                                            Picture of a simple bubble plot with a legend made with react and d3.js

                                            Bubble plot

                                            Learn how to build a bubble plot with react and d3.js

                                            The Data

                                            The dataset provides several numeric values for a set of data points. It can also add some categorical variables that can be added to customize the marker colors.

                                            The suggested data structure is an array of object, where each object is a data point. It can have as many numeric properties as needed.


                                            Here is a minimal example of the data structure:

                                            const data = [
                                            +Correlogram with React

                                            Correlogram

                                            Dataviz logo representing a Correlogram chart.

                                            In this blog post, we will be exploring how to build a correlogram with React and D3.js. A correlogram is a graphical representation of the correlation matrix for a given dataset. It is a useful tool for visualizing the relationships between different variables in a dataset, and can help identify potential correlations that may not be immediately obvious.

                                            Building a correlogram with React and D3.js allows us to create a highly interactive and customizable visualization. We will be able to use React's powerful component-based approach to build our visualization, while leveraging the flexibility and power of D3.js to create a dynamic and engaging visual representation of our data.

                                            Useful links

                                            Correlogram = scatter plot + histogram

                                            A correlogram uses histograms to show the distribution of each numeric variable on the diagonal of the matrix. It uses scatter plots to show the relationship of each pair of variable on every other cells.

                                            As a result, it is required to understand how to build a histogram and a scatter plot component using React and d3.js! In this post, we will just show how to leverage those reusable components to build a correlogram.

                                            Picture of a simple histogram made with react and d3.js

                                            Histogram

                                            Learn how to build a histogram with react and d3.js

                                            Picture of a simple scatter plot made with react and d3.js

                                            Scatter plot

                                            Learn how to build a scatter plot with react and d3.js

                                            Picture of a simple bubble plot with a legend made with react and d3.js

                                            Bubble plot

                                            Learn how to build a bubble plot with react and d3.js

                                            The Data

                                            The dataset provides several numeric values for a set of data points. It can also add some categorical variables that can be added to customize the marker colors.

                                            The suggested data structure is an array of object, where each object is a data point. It can have as many numeric properties as needed.


                                            Here is a minimal example of the data structure:

                                            const data = [
                                               {var1: 5.1, var2: 3.5, ..., group: 'setosa'},
                                               {var1: 4.9, var2: 3.0, ..., group: 'setosa'},
                                               ...
                                            @@ -52,4 +52,4 @@
                                             );

                                            And voilà, a first decent correlogram for your data analysis pipeline 😊. It's not perfect yet. You probably want to give more love to axes and labels, add hover effect and tooltips. But hopefully that's a good template to get started.

                                            44.555.566.577.58
                                            44.555.566.577.58
                                            44.555.566.577.58
                                            22.533.54var2
                                            22.533.54
                                            22.533.54
                                            1234567var3
                                            1234567
                                            1234567
                                            00.511.522.5var4var1
                                            00.511.522.5var2
                                            00.511.522.5var3

                                            A correlogram built with react and d3.js. It shows the relationship between the 4 numeric variables of the famous iris dataset.

                                            Note: You can compare this code with the pure d3 alternative. I find it much more readable.




                                            Contact

                                            👋 Hey, I'm Yan and I'm currently working on this project!

                                            Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                              -
                                              \ No newline at end of file +
                                              \ No newline at end of file diff --git a/course/axis/axis-variations.html b/course/axis/axis-variations.html index 0e73334d..d1a9b50e 100644 --- a/course/axis/axis-variations.html +++ b/course/axis/axis-variations.html @@ -1 +1 @@ -Axis component variations

                                              Axis component variations


                                              In the previous lesson we made a reusable component for the bottom axis.

                                              This lesson suggests many variation: left axis, adding grids, dealing with titles...

                                              Unavail.
                                              4 minutes read

                                              Left axis

                                              Gallery

                                              Show a gallery with the various axis styles available in the gallery.

                                              \ No newline at end of file +Axis component variations

                                              Axis component variations


                                              In the previous lesson we made a reusable component for the bottom axis.

                                              This lesson suggests many variation: left axis, adding grids, dealing with titles...

                                              Wip
                                              4 minutes read

                                              Gallery

                                              Show a gallery with the various axis styles available in the gallery.

                                              I need a first series of button: linear / ordinal / bandwidth / time / any = type of scale

                                              Then a second series: left / bottom

                                              Then it shows all the example in the gallery using this setup with a set of images

                                              When user clicks on an image, it opens the sandbox so user has the code ready to copy paste.

                                              \ No newline at end of file diff --git a/course/axis/axis-with-d3.html b/course/axis/axis-with-d3.html index 93f2a9f1..e036f5a7 100644 --- a/course/axis/axis-with-d3.html +++ b/course/axis/axis-with-d3.html @@ -1 +1,17 @@ -Alternative: use d3 helper

                                              Alternative: use d3 helper


                                              d3 offers some very smart functions when it comes to building axes.

                                              I personnaly prefer to avoid using d3 rendering functions like this. I have more control when using react for rendering. But if you are familiar with d3, it can be very handy to use those functions, and here is how to wrap them in a usEffect

                                              Unavail.
                                              4 minutes read

                                              The d3 axis module

                                              Explain what it is with links and examples

                                              How to use in a react app.

                                              If you're a d3.js afficionados and want to deal with as little react as possible, you can still use the good old axisBottom() and axisLeft() methods of d3 and wrap them in auseEffect() hook.

                                              Here is an example below:

                                              This axis is rendered using d3. The d3 necessary functions are called from a useEffect

                                              Explanation

                                              Everything starts with a ref

                                              const axesRef = useRef(null);
                                              \ No newline at end of file +Alternative: use d3 helper

                                              Alternative: use d3 helper


                                              d3 offers some very smart functions when it comes to building axes.

                                              I personnaly prefer to avoid using d3 rendering functions like this. I have more control when using react for rendering. But if you are familiar with d3, it can be very handy to use those functions, and here is how to wrap them in a usEffect

                                              Wip
                                              4 minutes read

                                              The d3 axis module

                                              Explain what it is with links and examples

                                              How to use in a react app.

                                              If you're a d3.js afficionados and want to deal with as little react as possible, you can still use the good old axisBottom() and axisLeft() methods of d3 and wrap them in auseEffect() hook.

                                              Here is an example below:

                                              This axis is rendered using d3. The d3 necessary functions are called from a useEffect

                                              Explanation

                                              Everything starts with a ref

                                              const axesRef = useRef(null);

                                              This ref is used to target a specific svg element where the axis will be drawn:

                                              <g
                                              +  width={boundsWidth}
                                              +  height={boundsHeight}
                                              +  ref={axesRef}
                                              +  transform={...do the translate}
                                              +/>

                                              And then a useEffect is used to call the d3 functions that render the axis.

                                              useEffect(() => {
                                              +  const svgElement = d3.select(axesRef.current);
                                              +  svgElement.selectAll("*").remove();
                                              +  const xAxisGenerator = d3.axisBottom(xScale);
                                              +  svgElement
                                              +    .append("g")
                                              +    .attr("transform", "translate(0," + boundsHeight + ")")
                                              +    .call(xAxisGenerator);
                                              +
                                              +  const yAxisGenerator = d3.axisLeft(yScale);
                                              +  svgElement.append("g").call(yAxisGenerator);
                                              +}, [xScale, yScale, boundsHeight]);
                                              \ No newline at end of file diff --git a/course/axis/bottom-axis.html b/course/axis/bottom-axis.html index 685425f8..3d0acd08 100644 --- a/course/axis/bottom-axis.html +++ b/course/axis/bottom-axis.html @@ -1,4 +1,4 @@ -Build a bottom axis

                                              Build a bottom axis


                                              In the previous lesson we learnt how to manage margins efficiently on our chart.

                                              Now, let's see how we can actually create a component that draws a bottom axis!

                                              Unavail.
                                              4 minutes read

                                              Re-usable Bottom Axis component

                                              The code snippet below builds a AxisBottom component. It is very much inspired from this blogpost by Amelia Wattenberger. I've just changed a few things, notably passing a scale as input instead of a range and a domain.

                                              The logic mainly relies on the ticks() method of a d3 scale. It takes a target number of ticks as input, find the most appropriate way to build smart ticks based on this target, and returns an array with all the tick positions.

                                              What follows is just some svg drawings based on those tick positions.

                                              const TICK_LENGTH = 6;
                                              +Build a bottom axis

                                              Build a bottom axis


                                              In the previous lesson we learnt how to manage margins efficiently on our chart.

                                              Now, let's see how we can actually create a component that draws a bottom axis!

                                              Wip
                                              4 minutes read

                                              Re-usable Bottom Axis component

                                              The code snippet below builds a AxisBottom component. It is very much inspired from this blogpost by Amelia Wattenberger. I've just changed a few things, notably passing a scale as input instead of a range and a domain.

                                              The logic mainly relies on the ticks() method of a d3 scale. It takes a target number of ticks as input, find the most appropriate way to build smart ticks based on this target, and returns an array with all the tick positions.

                                              What follows is just some svg drawings based on those tick positions.

                                              const TICK_LENGTH = 6;
                                               
                                               export const AxisBottom = ({ xScale, pixelsPerTick }) => {
                                                 const range = xScale.range();
                                              @@ -40,4 +40,4 @@
                                                     ))}
                                                   </>
                                                 );
                                              -};

                                              Using the component

                                              Once you have the bottom and left axis component described above you just need to call them properly. You need to compute the bounds area by substracting the margins to the total svg area.

                                              Don't forget to add an additional translation to the bottom axis to render it... at the bottom.

                                              0246810

                                              This axis is rendered without using d3.js to render.

                                              \ No newline at end of file +};

                                              Using the component

                                              Once you have the bottom and left axis component described above you just need to call them properly. You need to compute the bounds area by substracting the margins to the total svg area.

                                              Don't forget to add an additional translation to the bottom axis to render it... at the bottom.

                                              0246810

                                              This axis is rendered without using d3.js to render.

                                              \ No newline at end of file diff --git a/course/axis/introduction.html b/course/axis/introduction.html index 8f16d628..b1605314 100644 --- a/course/axis/introduction.html +++ b/course/axis/introduction.html @@ -1 +1 @@ -Introduction

                                              Introduction


                                              In the previous module on scales, we learned how to position SVG shapes precisely, adding meaning to the growing graph we're constructing.

                                              Now, it's time to provide context to these shape positions. For most chart types, this is achieved using axes. Axes can be complex elements, so let's explore how to create them effectively.

                                              Wip
                                              4 minutes read

                                              This module explains how to build axes like the one you can see at the bottom and on the left of this chart area.

                                              Terminology

                                              To effectively understand and work with axes in data visualization, it's essential to familiarize yourself with the following key terms:

                                              Here I need a figure that helps understanding the following terms:

                                              • Axis
                                              • Tick
                                              • Tick Label
                                              • Grid Line
                                              • Axis Label
                                              • Title
                                              • Scale
                                              • Domain
                                              • Range
                                              • Orientation
                                              • Axis Line
                                              • Baseline

                                              Margins

                                              We need some space between the chart area and the svg area. Let's see how to build this.

                                              \ No newline at end of file +Introduction

                                              Introduction


                                              In the previous module on scales, we learned how to position SVG shapes precisely, adding meaning to the growing graph we're constructing.

                                              Now, it's time to provide context to these shape positions. For most chart types, this is achieved using axes. Axes can be complex elements, so let's explore how to create them effectively.

                                              Wip
                                              4 minutes read

                                              This module explains how to build axes like the one you can see at the bottom and on the left of this chart area.

                                              Terminology

                                              To effectively understand and work with axes in data visualization, it's essential to familiarize yourself with the following key terms:

                                              Here I need a figure that helps understanding the following terms:

                                              • Axis
                                              • Tick
                                              • Tick Label
                                              • Grid Line
                                              • Axis Label
                                              • Title
                                              • Scale
                                              • Domain
                                              • Range
                                              • Orientation
                                              • Axis Line
                                              • Baseline

                                              Margins

                                              We need some space between the chart area and the svg area. Let's see how to build this.

                                              \ No newline at end of file diff --git a/course/axis/margin-and-translation.html b/course/axis/margin-and-translation.html index b00d4855..a01d1614 100644 --- a/course/axis/margin-and-translation.html +++ b/course/axis/margin-and-translation.html @@ -1,4 +1,4 @@ -Margin and translation

                                              Margin and translation


                                              Most of the chart types use a bottom and a left axis.

                                              In that case, there is a need to leave some space for the tick label and axis titles. Let's see how to implement this.

                                              Wip
                                              4 minutes read

                                              Chart area and Bounds area

                                              The bottom and left axes are not displays at the border of the main chart component. Some margins are computed by the viz component. It is important to understand that a chart is composed by:

                                              • the global chart area, often specified by the width and height properties of the chart components.
                                              • the "bounds" area, i.e. the area located inside the x and y axis. It is calculated by substracting the margins

                                              Implementation

                                              Let's start by defining the margins we want to use, as a const. This can be defined at the top of your file, out of the viz component, or even in a separate file containing all your constants.

                                              const MARGIN = {
                                              +Margin and translation

                                              Margin and translation


                                              Most of the chart types use a bottom and a left axis.

                                              In that case, there is a need to leave some space for the tick label and axis titles. Let's see how to implement this.

                                              Wip
                                              4 minutes read

                                              Chart area and Bounds area

                                              The bottom and left axes are not displays at the border of the main chart component. Some margins are computed by the viz component. It is important to understand that a chart is composed by:

                                              • the global chart area, often specified by the width and height properties of the chart components.
                                              • the "bounds" area, i.e. the area located inside the x and y axis. It is calculated by substracting the margins

                                              Implementation

                                              Let's start by defining the margins we want to use, as a const. This can be defined at the top of your file, out of the viz component, or even in a separate file containing all your constants.

                                              const MARGIN = {
                                                 top: 10,
                                                 right: 30,
                                                 bottom: 50,
                                              @@ -12,4 +12,4 @@
                                                 >
                                                   // ... all shapes go here
                                                 </g>
                                              -</svg>

                                              Explain the translation

                                              Explain that for the bottom axis, an additional translation is required to draw it at the bottom

                                              Draw the axis

                                              Now that we have some space for it, it is time to actually draw the axis. Let's build a reusable component.

                                              \ No newline at end of file +</svg>

                                              Explain the translation

                                              Explain that for the bottom axis, an additional translation is required to draw it at the bottom

                                              Draw the axis

                                              Now that we have some space for it, it is time to actually draw the axis. Let's build a reusable component.

                                              \ No newline at end of file diff --git a/course/hover-effect/css-descendant-selector.html b/course/hover-effect/css-descendant-selector.html index bcbdef95..cb81280c 100644 --- a/course/hover-effect/css-descendant-selector.html +++ b/course/hover-effect/css-descendant-selector.html @@ -1,4 +1,4 @@ -Strategy 2: CSS descendant selector

                                              Strategy 2: CSS descendant selector


                                              In the previous lesson, we learned how to modify a hovered graph item using the :hover CSS pseudo-class.

                                              However, this approach has design limitations. To achieve a more effective highlighting effect, it's better to simultaneously dim the other graph items.

                                              This can be accomplished using CSS alone, with the help of the CSS descendant selector.

                                              Wip
                                              4 minutes read

                                              What is a css descendant selector?

                                              A descendant selector allows to target elements that are children of another element.

                                              Here’s an example:

                                              .rectangle {
                                              +Strategy 2: CSS descendant selector

                                              Strategy 2: CSS descendant selector


                                              In the previous lesson, we learned how to modify a hovered graph item using the :hover CSS pseudo-class.

                                              However, this approach has design limitations. To achieve a more effective highlighting effect, it's better to simultaneously dim the other graph items.

                                              This can be accomplished using CSS alone, with the help of the CSS descendant selector.

                                              Wip
                                              4 minutes read

                                              What is a css descendant selector?

                                              A descendant selector allows to target elements that are children of another element.

                                              Here’s an example:

                                              .rectangle {
                                                 opacity: 1;
                                               }
                                               .container:hover .rectangle {
                                              @@ -6,4 +6,4 @@
                                               }
                                               .container .rectangle:hover {
                                                 opacity: 1;
                                              -}

                                              We assign a class called container to the SVG container and a class called rectangle to each rectangle in the chart.

                                              Then we set the default rectangle opacity to 1. Using the descendant selector, you can reduce the opacity of all rectangles to 0.1 when the container is hovered.

                                              Then, use a hover selector to set the opacity of the hovered rectangle back to 1.

                                              Application: treemap

                                              Mark90Robert12Emily34Marion53Nicolas98Malki22Djé12Mélanie45Einstein76

                                              Strategy 2: use CSS descendant combinator to dim all markers except the one that is hovered.

                                              Pros & Cons

                                              Pros

                                              • Easy to implement
                                              • Improves design by making hover effects more noticeable
                                              • Excellent performance (no JS computation, minimal redrawing)

                                              Cons

                                              • Fades all circles if the mouse enters the chart area without hovering over a specific circle. This technique works for chart where the whole svg area is covered by markers, like a treemap.
                                              • Cannot highlight circles that are obscured by other elements. (Potentially fixed using z-index).

                                              More examples

                                              The examples below all use this strategy to implement their hover effect.

                                              Picture of a lollipop chart with hover effect

                                              Lollipop with hover effect

                                              Learn how to add a hover effect to your lollipop chart

                                              GIF of a streamgraph react component that supports hover effect

                                              Streamgraph with hover effect

                                              How to add a hover effect on a streamgraph to highlight a group

                                              \ No newline at end of file +}

                                              We assign a class called container to the SVG container and a class called rectangle to each rectangle in the chart.

                                              Then we set the default rectangle opacity to 1. Using the descendant selector, you can reduce the opacity of all rectangles to 0.1 when the container is hovered.

                                              Then, use a hover selector to set the opacity of the hovered rectangle back to 1.

                                              Application: treemap

                                              Mark90Robert12Emily34Marion53Nicolas98Malki22Djé12Mélanie45Einstein76

                                              Strategy 2: use CSS descendant combinator to dim all markers except the one that is hovered.

                                              Pros & Cons

                                              Pros

                                              • Easy to implement
                                              • Improves design by making hover effects more noticeable
                                              • Excellent performance (no JS computation, minimal redrawing)

                                              Cons

                                              • Fades all circles if the mouse enters the chart area without hovering over a specific circle. This technique works for chart where the whole svg area is covered by markers, like a treemap.
                                              • Cannot highlight circles that are obscured by other elements. (Potentially fixed using z-index).

                                              More examples

                                              The examples below all use this strategy to implement their hover effect.

                                              Picture of a lollipop chart with hover effect

                                              Lollipop with hover effect

                                              Learn how to add a hover effect to your lollipop chart

                                              GIF of a streamgraph react component that supports hover effect

                                              Streamgraph with hover effect

                                              How to add a hover effect on a streamgraph to highlight a group

                                              \ No newline at end of file diff --git a/course/hover-effect/css-pseudo-class.html b/course/hover-effect/css-pseudo-class.html index b397fdbb..0cc2977a 100644 --- a/course/hover-effect/css-pseudo-class.html +++ b/course/hover-effect/css-pseudo-class.html @@ -1,4 +1,4 @@ -Strategy 1: CSS pseudo element

                                              Strategy 1: CSS pseudo element


                                              The simplest strategy.

                                              Let's explore how to use a CSS pseudo-class to modify only the graph item that is being hovered over.

                                              Free
                                              4 minutes read

                                              What is a pseudo class

                                              A CSS pseudo-class is a keyword added to a CSS selector that specifies a special state of the selected element(s). You can learn more about pseudo-classes in the MDN doc.

                                              Essentially, this means you can assign a class to each shape in a graph and change its appearance when the user hovers over it.

                                              Here is an example:

                                              .scatterplotCircle {
                                              +Strategy 1: CSS pseudo element

                                              Strategy 1: CSS pseudo element


                                              The simplest strategy.

                                              Let's explore how to use a CSS pseudo-class to modify only the graph item that is being hovered over.

                                              Free
                                              4 minutes read

                                              What is a pseudo class

                                              A CSS pseudo-class is a keyword added to a CSS selector that specifies a special state of the selected element(s). You can learn more about pseudo-classes in the MDN doc.

                                              Essentially, this means you can assign a class to each shape in a graph and change its appearance when the user hovers over it.

                                              Here is an example:

                                              .scatterplotCircle {
                                                 cursor: pointer;
                                                 fill-opacity: .3;
                                                 stroke-width: 2px;
                                              @@ -7,4 +7,4 @@
                                               .scatterplotCircle:hover {
                                                 fill-opacity: 1;
                                                 stroke-width: 1px;
                                              -}

                                              Application on a scatterplot

                                              Consider a scatterplot with multiple SVG circle elements, each assigned a .scatterplotCircle class. In the CSS file, you can set the fill-opacity to 0.3 using this class.

                                              To change the appearance on hover, use the .scatterplotCircle:hover selector to increase the opacity to 1.

                                              3540455055606570758085

                                              Strategy 1: use a pseudo-class to change the appearance of the hovered marker

                                              Pros & Cons

                                              Pros

                                              • Easy to implement
                                              • Excellent performance (no JS computation, minimal redrawing)

                                              Cons

                                              • Poor design: non-hovered circles remain prominent, so the highlight effect is weak
                                              • If the highlight information comes as a prop, another solution is needed

                                              More examples

                                              The examples below all use this strategy to implement their hover effect.

                                              Picture of a heatmap showing the effect of vaccination, built with react and d3

                                              Vaccination heatmap

                                              Reproduction of a famous vaccination heatmap using d3 and react

                                              Picture of a simple treemap

                                              Basic treemap

                                              Most simple treemap, with 1 level of hierarchy only

                                              \ No newline at end of file +}

                                              Application on a scatterplot

                                              Consider a scatterplot with multiple SVG circle elements, each assigned a .scatterplotCircle class. In the CSS file, you can set the fill-opacity to 0.3 using this class.

                                              To change the appearance on hover, use the .scatterplotCircle:hover selector to increase the opacity to 1.

                                              3540455055606570758085

                                              Strategy 1: use a pseudo-class to change the appearance of the hovered marker

                                              Pros & Cons

                                              Pros

                                              • Easy to implement
                                              • Excellent performance (no JS computation, minimal redrawing)

                                              Cons

                                              • Poor design: non-hovered circles remain prominent, so the highlight effect is weak
                                              • If the highlight information comes as a prop, another solution is needed

                                              More examples

                                              The examples below all use this strategy to implement their hover effect.

                                              Picture of a heatmap showing the effect of vaccination, built with react and d3

                                              Vaccination heatmap

                                              Reproduction of a famous vaccination heatmap using d3 and react

                                              Picture of a simple treemap

                                              Basic treemap

                                              Most simple treemap, with 1 level of hierarchy only

                                              \ No newline at end of file diff --git a/course/hover-effect/internal-state.html b/course/hover-effect/internal-state.html index 93cf5fcd..07b40dab 100644 --- a/course/hover-effect/internal-state.html +++ b/course/hover-effect/internal-state.html @@ -1,4 +1,4 @@ -Strategy 4: react internal state

                                              Strategy 4: react internal state


                                              In the previous lesson, we learned how to modify a hovered graph item using the :hover CSS pseudo-class.

                                              However, this approach has design limitations. To achieve a more effective highlighting effect, it's better to simultaneously dim the other graph items.

                                              This can be accomplished using CSS alone, with the help of the CSS descendant selector.

                                              Wip
                                              4 minutes read

                                              Internal state & event listener

                                              Add onMouseEnter event listener to all circle

                                              Set an internal state

                                              Trigger a redraw of all circles with conditional state.

                                              As for the tooltip example above, everything starts with an internal state (called hoveredGroup) that stores which circle is hovered hover.

                                              const [hoveredGroup, setHoveredGroup] = useState<string | null>(null);

                                              Now, this state needs to be updated when a user hovers over the circle. setHoveredGroup can be passed as a callback to the onMouseOver attribute of each circle.

                                              On top of this, some specific css classes can be attributed to circles depending on the circle that is hovered hover. In the example above, a class called dimmed is added to circles that must disappear.

                                              To put it in a nutshell, the circles are created as follows:

                                              const allShapes = data.map((d, i) => {
                                              +Strategy 4: react internal state

                                              Strategy 4: react internal state


                                              In the previous lesson, we learned how to modify a hovered graph item using the :hover CSS pseudo-class.

                                              However, this approach has design limitations. To achieve a more effective highlighting effect, it's better to simultaneously dim the other graph items.

                                              This can be accomplished using CSS alone, with the help of the CSS descendant selector.

                                              Wip
                                              4 minutes read

                                              Internal state & event listener

                                              Add onMouseEnter event listener to all circle

                                              Set an internal state

                                              Trigger a redraw of all circles with conditional state.

                                              As for the tooltip example above, everything starts with an internal state (called hoveredGroup) that stores which circle is hovered hover.

                                              const [hoveredGroup, setHoveredGroup] = useState<string | null>(null);

                                              Now, this state needs to be updated when a user hovers over the circle. setHoveredGroup can be passed as a callback to the onMouseOver attribute of each circle.

                                              On top of this, some specific css classes can be attributed to circles depending on the circle that is hovered hover. In the example above, a class called dimmed is added to circles that must disappear.

                                              To put it in a nutshell, the circles are created as follows:

                                              const allShapes = data.map((d, i) => {
                                                 const className = // class if the circle depends on the hover state
                                                   hoveredGroup && d.group !== hoveredGroup
                                                     ? styles.scatterplotCircle + " " + styles.dimmed
                                              @@ -17,4 +17,4 @@
                                                     onMouseLeave={() => setHoveredGroup(null)} // and to set it back to null
                                                   />
                                                 );
                                              -});

                                              Last but not least, some css needs to be added to customize the circle depending on if they are in default, .dimmed or :hover mode.

                                              Note that the filter: saturate(0) is a good way to dim unwanted circles. Also, playing with transition-delay and transition-duration adds to animate the transition is a nice touch you should consider. Check the code below the example to see the full css.

                                              4050607080

                                              TODO.

                                              Pros & Cons

                                              Pros

                                              • Allows to sync the hover effect with other UI updates. The hovered state can be used to update any other react components in the application. Like tooltip or another graph.
                                              • Using javascript to trigger the animation can give more flexibility to customize the hover effect, using react-spring for instance.

                                              Cons

                                              • Performance 🚨. Here we are redrawing all the circles each time a hover effect is hovered. This can be dramatic if you have thousands of circles!

                                              More examples

                                              The examples below all use this strategy to implement their hover effect.

                                              line charts with synchronized cursors

                                              Synchronized cursors

                                              Add a cursor synchronized on all your charts

                                              GIF of a streamgraph with multiple interactive features

                                              Streamgraph application

                                              Streamgraph with a slider to zoom on a time stamp and with interactive inline legends

                                              \ No newline at end of file +});

                                              Last but not least, some css needs to be added to customize the circle depending on if they are in default, .dimmed or :hover mode.

                                              Note that the filter: saturate(0) is a good way to dim unwanted circles. Also, playing with transition-delay and transition-duration adds to animate the transition is a nice touch you should consider. Check the code below the example to see the full css.

                                              4050607080

                                              TODO.

                                              Pros & Cons

                                              Pros

                                              • Allows to sync the hover effect with other UI updates. The hovered state can be used to update any other react components in the application. Like tooltip or another graph.
                                              • Using javascript to trigger the animation can give more flexibility to customize the hover effect, using react-spring for instance.

                                              Cons

                                              • Performance 🚨. Here we are redrawing all the circles each time a hover effect is hovered. This can be dramatic if you have thousands of circles!

                                              More examples

                                              The examples below all use this strategy to implement their hover effect.

                                              line charts with synchronized cursors

                                              Synchronized cursors

                                              Add a cursor synchronized on all your charts

                                              GIF of a streamgraph with multiple interactive features

                                              Streamgraph application

                                              Streamgraph with a slider to zoom on a time stamp and with interactive inline legends

                                              \ No newline at end of file diff --git a/course/hover-effect/introduction.html b/course/hover-effect/introduction.html index 7c5fa495..fe18ea47 100644 --- a/course/hover-effect/introduction.html +++ b/course/hover-effect/introduction.html @@ -1 +1 @@ -What is it?

                                              What is it?


                                              In the previous modules, you learned how to create a wide variety of static charts. 👏

                                              However, interactivity is essential web applications. Adding hover effects significantly enhances the user experience by highlighting specific series on the chart.

                                              In this module, we'll explore several strategies for implementing hover effects using both CSS and React. Before diving into the code, let's ensure we have a clear understanding of what hover effects are.

                                              Free
                                              3 minutes read

                                              Definition

                                              A hover effect is a visual change that occurs when a user moves their cursor over a specific element on a webpage.

                                              When implementing a hover effect, you should be careful about:

                                              • Design: hover effect is visually appealing and enhances the user experience. It is consistent with the overall design of your application and does not distract or confuse the user.
                                              • Performance: hover effect is fast: no lag or delay. It does not significantly impact the performance of your application, especially when dealing with large datasets or complex viz.

                                              Three Types of Hover Effects

                                              In my opinion, there are three main types of hover effects: those that only modify the hovered graph item, those that modify other graph markers, and those that affect other related elements in the user interface.

                                              Click the button below to see examples of all three types:


                                              405060708001000020000300004000050000

                                              Observe this graph: when you hover over a circle, its style changes slightly!

                                              While this isn't the most dramatic visual effect, it is very easy to implement using a single CSS pseudo-element.

                                              We'll learn how to implement this in the next lesson.

                                              Let's code

                                              Enough theory.

                                              Let's dive into the simplest hover effect you can create: just a few lines of CSS using pseudo-elements.

                                              \ No newline at end of file +What is it?

                                              What is it?


                                              In the previous modules, you learned how to create a wide variety of static charts. 👏

                                              However, interactivity is essential web applications. Adding hover effects significantly enhances the user experience by highlighting specific series on the chart.

                                              In this module, we'll explore several strategies for implementing hover effects using both CSS and React. Before diving into the code, let's ensure we have a clear understanding of what hover effects are.

                                              Free
                                              3 minutes read

                                              Definition

                                              A hover effect is a visual change that occurs when a user moves their cursor over a specific element on a webpage.

                                              When implementing a hover effect, you should be careful about:

                                              • Design: hover effect is visually appealing and enhances the user experience. It is consistent with the overall design of your application and does not distract or confuse the user.
                                              • Performance: hover effect is fast: no lag or delay. It does not significantly impact the performance of your application, especially when dealing with large datasets or complex viz.

                                              Three Types of Hover Effects

                                              In my opinion, there are three main types of hover effects: those that only modify the hovered graph item, those that modify other graph markers, and those that affect other related elements in the user interface.

                                              Click the button below to see examples of all three types:


                                              405060708001000020000300004000050000

                                              Observe this graph: when you hover over a circle, its style changes slightly!

                                              While this isn't the most dramatic visual effect, it is very easy to implement using a single CSS pseudo-element.

                                              We'll learn how to implement this in the next lesson.

                                              Let's code

                                              Enough theory.

                                              Let's dive into the simplest hover effect you can create: just a few lines of CSS using pseudo-elements.

                                              \ No newline at end of file diff --git a/course/hover-effect/link-two-graphs.html b/course/hover-effect/link-two-graphs.html index ac8f6ae8..f1fccb52 100644 --- a/course/hover-effect/link-two-graphs.html +++ b/course/hover-effect/link-two-graphs.html @@ -1,4 +1,4 @@ -Hover interaction on a chart with React

                                              Hover interaction on a chart with React


                                              Interactivity is crucial in data visualization, especially for web applications. Adding hover effects enhances user experience by highlighting specific series on the chart.

                                              This post suggests a few strategies to implement hover effects using css and react.

                                              Note: this article does not talk about tooltips that has its dedicated section.

                                              4️⃣ Internal state & event listener

                                              Add onMouseEnter event listener to all circle

                                              Set an internal state

                                              Trigger a redraw of all circles with conditional state.

                                              As for the tooltip example above, everything starts with an internal state (called hoveredGroup) that stores which circle is hovered hover.

                                              const [hoveredGroup, setHoveredGroup] = useState<string | null>(null);

                                              Now, this state needs to be updated when a user hovers over the circle. setHoveredGroup can be passed as a callback to the onMouseOver attribute of each circle.

                                              On top of this, some specific css classes can be attributed to circles depending on the circle that is hovered hover. In the example above, a class called dimmed is added to circles that must disappear.

                                              To put it in a nutshell, the circles are created as follows:

                                              const allShapes = data.map((d, i) => {
                                              +Hover interaction on a chart with React

                                              Hover interaction on a chart with React


                                              Interactivity is crucial in data visualization, especially for web applications. Adding hover effects enhances user experience by highlighting specific series on the chart.

                                              This post suggests a few strategies to implement hover effects using css and react.

                                              Note: this article does not talk about tooltips that has its dedicated section.

                                              4️⃣ Internal state & event listener

                                              Add onMouseEnter event listener to all circle

                                              Set an internal state

                                              Trigger a redraw of all circles with conditional state.

                                              As for the tooltip example above, everything starts with an internal state (called hoveredGroup) that stores which circle is hovered hover.

                                              const [hoveredGroup, setHoveredGroup] = useState<string | null>(null);

                                              Now, this state needs to be updated when a user hovers over the circle. setHoveredGroup can be passed as a callback to the onMouseOver attribute of each circle.

                                              On top of this, some specific css classes can be attributed to circles depending on the circle that is hovered hover. In the example above, a class called dimmed is added to circles that must disappear.

                                              To put it in a nutshell, the circles are created as follows:

                                              const allShapes = data.map((d, i) => {
                                                 const className = // class if the circle depends on the hover state
                                                   hoveredGroup && d.group !== hoveredGroup
                                                     ? styles.scatterplotCircle + " " + styles.dimmed
                                              @@ -20,4 +20,4 @@
                                               });

                                              Last but not least, some css needs to be added to customize the circle depending on if they are in default, .dimmed or :hover mode.

                                              Note that the filter: saturate(0) is a good way to dim unwanted circles. Also, playing with transition-delay and transition-duration adds to animate the transition is a nice touch you should consider. Check the code below the example to see the full css.

                                              4050607080

                                              TODO.

                                              Pros

                                              • Allows to sync the hover effect with other UI updates. The hovered state can be used to update any other react components in the application. Like tooltip or another graph.
                                              • Using javascript to trigger the animation can give more flexibility to customize the hover effect, using react-spring for instance.

                                              Cons

                                              • Performance 🚨. Here we are redrawing all the circles each time a hover effect is hovered. This can be dramatic if you have thousands of circles!
                                              line charts with synchronized cursors

                                              Synchronized cursors

                                              Add a cursor synchronized on all your charts

                                              GIF of a streamgraph with multiple interactive features

                                              Streamgraph application

                                              Streamgraph with a slider to zoom on a time stamp and with interactive inline legends

                                              4️⃣ Canvas

                                              Using the useDimensions hook described above is pretty straight-forward. You first need to create a ref using the react useRef()function:

                                              Use dimming to highlight a specific point





                                              Contact

                                              👋 Hey, I'm Yan and I'm currently working on this project!

                                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                -
                                                \ No newline at end of file +
                                                \ No newline at end of file diff --git a/course/hover-effect/toggle-class-in-js.html b/course/hover-effect/toggle-class-in-js.html index 3dcc147c..593c7764 100644 --- a/course/hover-effect/toggle-class-in-js.html +++ b/course/hover-effect/toggle-class-in-js.html @@ -1,4 +1,4 @@ -Strategy 3: toggle css classes

                                                Strategy 3: toggle css classes


                                                In the previous lesson, we learned how to modify a hovered graph item using the :hover CSS pseudo-class.

                                                However, this approach has design limitations. To achieve a more effective highlighting effect, it's better to simultaneously dim the other graph items.

                                                This can be accomplished using CSS alone, with the help of the CSS descendant selector.

                                                Wip
                                                4 minutes read

                                                Toggle class in JS

                                                Problem above: when mouse enter the chart area, triggers effect even if no marker hovered over.

                                                Solution: CSS compound class selecter (MDN doc)

                                                In CSS, a compound class selector combines multiple class names to target elements that match all of the specified classes.

                                                We can use the same css as the above example, but add the highlight class using javascript:

                                                onMouseEnter={() => {
                                                +Strategy 3: toggle css classes

                                                Strategy 3: toggle css classes


                                                In the previous lesson, we learned how to modify a hovered graph item using the :hover CSS pseudo-class.

                                                However, this approach has design limitations. To achieve a more effective highlighting effect, it's better to simultaneously dim the other graph items.

                                                This can be accomplished using CSS alone, with the help of the CSS descendant selector.

                                                Wip
                                                4 minutes read

                                                Toggle class in JS

                                                Problem above: when mouse enter the chart area, triggers effect even if no marker hovered over.

                                                Solution: CSS compound class selecter (MDN doc)

                                                In CSS, a compound class selector combines multiple class names to target elements that match all of the specified classes.

                                                We can use the same css as the above example, but add the highlight class using javascript:

                                                onMouseEnter={() => {
                                                   if (ref.current) {
                                                     ref.current.classList.add(styles.hasHighlight);
                                                   }
                                                @@ -7,4 +7,4 @@
                                                   if (ref.current) {
                                                     ref.current.classList.remove(styles.hasHighlight);
                                                   }
                                                -}}
                                                Mark (90)Robert (12)Emily (34)Marion (53)Nicolas (58)

                                                A donut chart with clean inline legends, built thanks to the centroid function of d3.js.

                                                Pros & Cons

                                                More examples

                                                The examples below all use this strategy to implement their hover effect.

                                                \ No newline at end of file +}}
                                                Mark (90)Robert (12)Emily (34)Marion (53)Nicolas (58)

                                                A donut chart with clean inline legends, built thanks to the centroid function of d3.js.

                                                Pros & Cons

                                                More examples

                                                The examples below all use this strategy to implement their hover effect.

                                                \ No newline at end of file diff --git a/course/introduction/initial-setup.html b/course/introduction/initial-setup.html index 00ec0636..7b1746f0 100644 --- a/course/introduction/initial-setup.html +++ b/course/introduction/initial-setup.html @@ -1 +1 @@ -Initial setup

                                                Initial setup


                                                Let's create a confortable working environment: let's use Next.js.

                                                Wip
                                                4 minutes read

                                                Why Next.js?

                                                Explain why react is great?

                                                Talk about the setup I recommend: next.js + Typescript

                                                Talk about style management in next.

                                                Say I like shadCn UI and tailwind, but won't be used in the course.

                                                Talk about my boiler plate.

                                                \ No newline at end of file +Initial setup

                                                Initial setup


                                                Let's create a confortable working environment: let's use Next.js.

                                                Wip
                                                4 minutes read

                                                Why Next.js?

                                                Explain why react is great?

                                                Talk about the setup I recommend: next.js + Typescript

                                                Talk about style management in next.

                                                Say I like shadCn UI and tailwind, but won't be used in the course.

                                                Talk about my boiler plate.

                                                \ No newline at end of file diff --git a/course/introduction/introduction-to-d3.html b/course/introduction/introduction-to-d3.html index 69557fab..ff68bfc6 100644 --- a/course/introduction/introduction-to-d3.html +++ b/course/introduction/introduction-to-d3.html @@ -1 +1 @@ -What is d3

                                                What is d3


                                                d3 is THE reference when it comes to build viz on the web

                                                But we will use only a fraction of what it offers.

                                                Wip
                                                4 minutes read

                                                What is d3

                                                Explain what d3 is in a nutshell.

                                                Link to d3 graph gallery.

                                                Why is d3 so useful?

                                                Give the example of an awesome d3 function. May be the treemap function?

                                                Only a fraction

                                                Create circle pack of all the modules. Explain that we will use only a fraction of this.

                                                \ No newline at end of file +What is d3

                                                What is d3


                                                d3 is THE reference when it comes to build viz on the web

                                                But we will use only a fraction of what it offers.

                                                Wip
                                                4 minutes read

                                                What is d3

                                                Explain what d3 is in a nutshell.

                                                Link to d3 graph gallery.

                                                Why is d3 so useful?

                                                Give the example of an awesome d3 function. May be the treemap function?

                                                Only a fraction

                                                Create circle pack of all the modules. Explain that we will use only a fraction of this.

                                                \ No newline at end of file diff --git a/course/introduction/introduction-to-react.html b/course/introduction/introduction-to-react.html index 93c0efa5..694921ed 100644 --- a/course/introduction/introduction-to-react.html +++ b/course/introduction/introduction-to-react.html @@ -1 +1 @@ -What is react

                                                What is react


                                                React is a JavaScript library used for creating dynamic and interactive user interfaces through reusable components. Developed by Facebook, it simplifies the process of managing application state and updating the user interface efficiently.

                                                This lesson will offer a concise overview of React and its key features.

                                                Wip
                                                4 minutes read

                                                Why React?

                                                Explain why react is great?

                                                • Widespread, full of doc. Show a graph that compares with others.
                                                • Great state management: exactly what we need
                                                • Based on the concept of component: exactly what we need for dataviz

                                                Expected knowledge

                                                Explain that this is not a react course. If you know nothing about react, you gonna struggle here. So learn somewhere first.

                                                Explain that building viz is a very specific need, thus this course.

                                                \ No newline at end of file +What is react

                                                What is react


                                                React is a JavaScript library used for creating dynamic and interactive user interfaces through reusable components. Developed by Facebook, it simplifies the process of managing application state and updating the user interface efficiently.

                                                This lesson will offer a concise overview of React and its key features.

                                                Wip
                                                4 minutes read

                                                Why React?

                                                React was introduced in 2013, transforming the landscape of web development.

                                                Prior to its component-based architecture, building web applications was complex and cumbersome.

                                                Screenshot of the React website front page

                                                If you make charts for the web and don't know react, you're missing out!

                                                This is particularly evident in applications that involve data visualization. The ability to create reusable components, like a Scatterplot component, that can be utilized throughout your app, is a game-changer for your development process.


                                                If you're building a data visualization application, React offers everything you need:

                                                • Robust state management, perfectly suited for dynamic data.
                                                • A component-driven approach, ideal for creating interactive visualizations.
                                                • Extensive community support and comprehensive documentation.

                                                Expected knowledge

                                                This course focuses on Data Visualization using React.

                                                We won’t cover the basics of React, as that’s a vast topic deserving its own dedicated course! For a solid introduction, check out this intro by Codecademy.

                                                Basically, you should just be able to understand what's happening in this sandbox:

                                                However, you don’t need to be a React expert to take this course. Even seasoned developers will find valuable insights here: creating visualizations with React and D3 involves specialized knowledge that differs significantly from typical UI development.

                                                Lastly, you don’t need prior experience with D3 to get started! We’ll use it sparingly and provide a thorough explanation of how it works.

                                                Alternatives

                                                Talk about Vue and

                                                Link: https://gist.github.com/tkrotoff/b1caa4c3a185629299ec234d2314e190

                                                schema showing the number of download evolution of the main JS libraries

                                                React is big

                                                \ No newline at end of file diff --git a/course/introduction/js-dataviz-libraries.html b/course/introduction/js-dataviz-libraries.html index 7bb2fdc0..97ffa1ff 100644 --- a/course/introduction/js-dataviz-libraries.html +++ b/course/introduction/js-dataviz-libraries.html @@ -1 +1 @@ -Chart libraries: don't

                                                Chart libraries: don't


                                                When you want to create a chart, using a js library is usually the first thing that comes to your mind.

                                                While it is definitely a good idea to start with, it often ends with making your life complicated. Let's see why.

                                                Wip
                                                4 minutes read

                                                In a hurry

                                                Explain the usual story

                                                You start with a lib with NIVO. In a few minutes you have your chart. Great!

                                                Now your boss ask for X, Y, Z. Doable.

                                                Now he asks for something new. That's doable but hard. Your code starts to be hard to read.

                                                And it ends by not being doable.

                                                → Better to use d3 directly and understand what you do!

                                                \ No newline at end of file +Chart libraries: don't

                                                Chart libraries: don't


                                                When you want to create a chart, using a js library is usually the first thing that comes to your mind.

                                                While it is definitely a good idea to start with, it often ends with making your life complicated. Let's see why.

                                                Wip
                                                4 minutes read

                                                In a hurry

                                                Explain the usual story

                                                You start with a lib with NIVO. In a few minutes you have your chart. Great!

                                                Now your boss ask for X, Y, Z. Doable.

                                                Now he asks for something new. That's doable but hard. Your code starts to be hard to read.

                                                And it ends by not being doable.

                                                → Better to use d3 directly and understand what you do!

                                                \ No newline at end of file diff --git a/course/responsiveness/code-organization.html b/course/responsiveness/code-organization.html index 35f2cd81..a6a687cc 100644 --- a/course/responsiveness/code-organization.html +++ b/course/responsiveness/code-organization.html @@ -1,4 +1,4 @@ -Best Practices for Code Organization

                                                Best Practices for Code Organization


                                                Let's create a confortable working environment: let's use Next.js.

                                                Wip
                                                4 minutes read

                                                🎁 Wrapper component

                                                I like to create a "wrapper" component that manages the responsiveness and pass all the other props to the viz component, plus width and height.

                                                If you already have a dataviz component and just want to make it responsive, this template should be useful to you:

                                                type ResponsiveDensityChartProps = {
                                                +Best Practices for Code Organization

                                                Best Practices for Code Organization


                                                Let's create a confortable working environment: let's use Next.js.

                                                Wip
                                                4 minutes read

                                                🎁 Wrapper component

                                                I like to create a "wrapper" component that manages the responsiveness and pass all the other props to the viz component, plus width and height.

                                                If you already have a dataviz component and just want to make it responsive, this template should be useful to you:

                                                type ResponsiveDensityChartProps = {
                                                   data: number[];
                                                 };
                                                 
                                                @@ -28,4 +28,4 @@
                                                 // Non responsive component
                                                 const DensityChart = ({ width, height, data }: DensityChartProps) => {
                                                   //... dataviz code goes here
                                                -}
                                                \ No newline at end of file +}
                                                \ No newline at end of file diff --git a/course/responsiveness/common-pitfalls.html b/course/responsiveness/common-pitfalls.html index d8b96c22..ae3c70d2 100644 --- a/course/responsiveness/common-pitfalls.html +++ b/course/responsiveness/common-pitfalls.html @@ -1 +1 @@ -Common Pitfalls and How to Avoid Them

                                                Common Pitfalls and How to Avoid Them


                                                Let's create a confortable working environment: let's use Next.js.

                                                Wip
                                                4 minutes read

                                                🐞 Caveats

                                                Here are some potential caveats to consider when using the useDimensions hook:

                                                1️⃣ Container Needs Dimensions

                                                In HTML, not all <div> elements have dimensions by default. If a <div> lacks dimensions, the useDimensions hook won't be able to measure it!

                                                • An inline <div> cannot have width and height.
                                                • By default, a <div> has no height. Its width is 100%, but its height is determined by its content. This means that without content, the <div> will have no height.

                                                2️⃣ Performance

                                                When the graph dimensions change, ensure that you only recompute what is necessary within the visualization component. useMemo and useCallback are valuable tools for optimizing performance.

                                                3️⃣ Design

                                                A graph is not merely a piece of text; its aspect ratio significantly affects its appearance. A wide graph might look great, while a narrower version may not. Sometimes, adapting the chart type based on window size is the best approach.

                                                4️⃣ Zero Dimensions

                                                Be cautious with the useDimensions hook. When your app first loads, the reference dimensions might be null or zero. Ensure your code handles this scenario properly to avoid errors.

                                                \ No newline at end of file +Common Pitfalls and How to Avoid Them

                                                Common Pitfalls and How to Avoid Them


                                                Let's create a confortable working environment: let's use Next.js.

                                                Wip
                                                4 minutes read

                                                🐞 Caveats

                                                Here are some potential caveats to consider when using the useDimensions hook:

                                                1️⃣ Container Needs Dimensions

                                                In HTML, not all <div> elements have dimensions by default. If a <div> lacks dimensions, the useDimensions hook won't be able to measure it!

                                                • An inline <div> cannot have width and height.
                                                • By default, a <div> has no height. Its width is 100%, but its height is determined by its content. This means that without content, the <div> will have no height.

                                                2️⃣ Performance

                                                When the graph dimensions change, ensure that you only recompute what is necessary within the visualization component. useMemo and useCallback are valuable tools for optimizing performance.

                                                3️⃣ Design

                                                A graph is not merely a piece of text; its aspect ratio significantly affects its appearance. A wide graph might look great, while a narrower version may not. Sometimes, adapting the chart type based on window size is the best approach.

                                                4️⃣ Zero Dimensions

                                                Be cautious with the useDimensions hook. When your app first loads, the reference dimensions might be null or zero. Ensure your code handles this scenario properly to avoid errors.

                                                \ No newline at end of file diff --git a/course/responsiveness/introduction.html b/course/responsiveness/introduction.html index 656ca243..72ff3179 100644 --- a/course/responsiveness/introduction.html +++ b/course/responsiveness/introduction.html @@ -1,4 +1,4 @@ -Introduction to responsiveness

                                                Introduction to responsiveness


                                                Most of the visualization components in this gallery accept width and height properties.

                                                However, we often don't know the exact dimensions we need for our visualizations; we just want them to fit their container.

                                                This module explains how to make a chart responsive. It provides the code for a hook that detects changes in a div's dimensions and explains how to inject its returned values into a visualization component.

                                                Free
                                                4 minutes read

                                                What is responsiveness?

                                                Responsiveness refers to the ability of a data visualization (such as charts, graphs, or dashboards) to adapt and display correctly across different devices and screen sizes.

                                                This ensures that users have an optimal viewing experience whether they are accessing the visualizations on a desktop, tablet, or mobile device

                                                This density chart is responsive! Resize your window to see how the graph fits its container.

                                                Responsiveness is a key aspect of web development. This module specifically focuses on making charts responsive. It won't cover general topics like CSS, Flexbox, Grid, or other concepts related to overall website responsiveness.

                                                Design Considerations

                                                A graph can appear visually appealing when its width exceeds its height, but it may lose its effectiveness if shrunk too much. In some cases, using a completely different chart type on smaller screens, removing a chart, or flipping it may be necessary.

                                                This course offers technical guidelines on making graphs responsive. It focuses on the "how" rather than the "what," providing you with the tools to achieve your desired outcomes.

                                                😢 Unresponsive chart

                                                When building a chart with JavaScript, knowing its dimensions — width and height — is essential. These dimensions are needed to compute scales, draw axes, and determine where to place shapes.

                                                Consequently, a visualization component always expects width and heightproperties.

                                                Consider a simple density plot, for example. The code looks like this:

                                                import * as d3 from "d3";
                                                +Introduction to responsiveness

                                                Introduction to responsiveness


                                                Most of the visualization components in this gallery accept width and height properties.

                                                However, we often don't know the exact dimensions we need for our visualizations; we just want them to fit their container.

                                                This module explains how to make a chart responsive. It provides the code for a hook that detects changes in a div's dimensions and explains how to inject its returned values into a visualization component.

                                                Free
                                                4 minutes read

                                                What is responsiveness?

                                                Responsiveness refers to the ability of a data visualization (such as charts, graphs, or dashboards) to adapt and display correctly across different devices and screen sizes.

                                                This ensures that users have an optimal viewing experience whether they are accessing the visualizations on a desktop, tablet, or mobile device

                                                This density chart is responsive! Resize your window to see how the graph fits its container.

                                                Responsiveness is a key aspect of web development. This module specifically focuses on making charts responsive. It won't cover general topics like CSS, Flexbox, Grid, or other concepts related to overall website responsiveness.

                                                Design Considerations

                                                A graph can appear visually appealing when its width exceeds its height, but it may lose its effectiveness if shrunk too much. In some cases, using a completely different chart type on smaller screens, removing a chart, or flipping it may be necessary.

                                                This course offers technical guidelines on making graphs responsive. It focuses on the "how" rather than the "what," providing you with the tools to achieve your desired outcomes.

                                                😢 Unresponsive chart

                                                When building a chart with JavaScript, knowing its dimensions — width and height — is essential. These dimensions are needed to compute scales, draw axes, and determine where to place shapes.

                                                Consequently, a visualization component always expects width and heightproperties.

                                                Consider a simple density plot, for example. The code looks like this:

                                                import * as d3 from "d3";
                                                 
                                                 type DensityProps = {
                                                   width: number; // 🙁 not responsive!
                                                @@ -17,4 +17,4 @@
                                                       </svg>
                                                     </div>
                                                   );
                                                -};

                                                Let's Code

                                                Let's assume we have a div that is responsive and takes the full width of an app.

                                                How can we draw a chart inside this div that also takes up the entire space and remains responsive?

                                                Let's find out! 🙇

                                                \ No newline at end of file +};

                                                Let's Code

                                                Let's assume we have a div that is responsive and takes the full width of an app.

                                                How can we draw a chart inside this div that also takes up the entire space and remains responsive?

                                                Let's find out! 🙇

                                                \ No newline at end of file diff --git a/course/responsiveness/use-dimension-hook.html b/course/responsiveness/use-dimension-hook.html index 2a399423..dc376081 100644 --- a/course/responsiveness/use-dimension-hook.html +++ b/course/responsiveness/use-dimension-hook.html @@ -1,4 +1,4 @@ -Creating a useDimensions Hook

                                                Creating a useDimensions Hook


                                                The visualization component is going to be wrapped in a responsive div. We need a way to retrieve this container's dimensions.

                                                To achieve this, let's create a hook called useDimensions.

                                                Wip
                                                4 minutes read

                                                What is a hook

                                                A hook is a special function that lets you use state and other React features in functional components, as explained in the documentation.

                                                Explain more why a hook is what we need.

                                                🎣 Hook to get the container dimensions

                                                That's how the hook looks like:

                                                import { useEffect, useLayoutEffect, useState } from "react";
                                                +Creating a useDimensions Hook

                                                Creating a useDimensions Hook


                                                The visualization component is going to be wrapped in a responsive div. We need a way to retrieve this container's dimensions.

                                                To achieve this, let's create a hook called useDimensions.

                                                Wip
                                                4 minutes read

                                                What is a hook

                                                A hook is a special function that lets you use state and other React features in functional components, as explained in the documentation.

                                                Explain more why a hook is what we need.

                                                🎣 Hook to get the container dimensions

                                                That's how the hook looks like:

                                                import { useEffect, useLayoutEffect, useState } from "react";
                                                 
                                                 // Hook to retrieve the dimensions of a div.
                                                 // react-graph-gallery.com
                                                @@ -27,4 +27,4 @@
                                                   }, []);
                                                 
                                                   return dimensions;
                                                -}

                                                This hook is essentially a function that checks the offsetWidth and offsetHeight of a provided ref.


                                                An event listener for the resize event is added to the window to ensure the dimensions are updated when the window size changes.

                                                Why do I have the useLayoutEffect in there?

                                                Explain more in depth how it works.

                                                \ No newline at end of file +}

                                                This hook is essentially a function that checks the offsetWidth and offsetHeight of a provided ref.


                                                An event listener for the resize event is added to the window to ensure the dimensions are updated when the window size changes.

                                                Why do I have the useLayoutEffect in there?

                                                Explain more in depth how it works.

                                                \ No newline at end of file diff --git a/course/responsiveness/using-the-hook.html b/course/responsiveness/using-the-hook.html index fa6cb52a..39465128 100644 --- a/course/responsiveness/using-the-hook.html +++ b/course/responsiveness/using-the-hook.html @@ -1,7 +1,7 @@ -Integrating the Hook with Your Graph

                                                Integrating the Hook with Your Graph


                                                We have a hook that listens for changes in a div's dimensions and returns those dimensions.

                                                Now, it's time to use this hook to inject the dimensions into our graph!

                                                Wip
                                                4 minutes read

                                                Create a ref

                                                Start by creating a ref using the React useRef() function.

                                                A ref allows you to target and interact with a specific HTML element in the DOM of your application.

                                                const chartRef = useRef(null);

                                                Finally, pass the chartRef to the container you want to monitor.

                                                return(
                                                +Integrating the Hook with Your Graph

                                                Integrating the Hook with Your Graph


                                                We have a hook that listens for changes in a div's dimensions and returns those dimensions.

                                                Now, it's time to use this hook to inject the dimensions into our graph!

                                                Wip
                                                4 minutes read

                                                Create a ref

                                                Start by creating a ref using the React useRef() function.

                                                A ref allows you to target and interact with a specific HTML element in the DOM of your application.

                                                const chartRef = useRef(null);

                                                Finally, pass the chartRef to the container you want to monitor.

                                                return(
                                                   <div ref={chartRef}>
                                                     <MyChartComponent
                                                       height={chartSize.height}
                                                       width={chartSize.width}
                                                   </div>
                                                -)

                                                Use the hook

                                                Then, pass this newly created chartRef to the hook:

                                                const chartSize = useDimensions(chartRef);

                                                You now have an object called chartSize with two properties: height and width. These properties can be used in your chart component. 🔥

                                                Pro tip: Before building a responsive visualization, use console.log() to check the chartSize object and ensure everything is working correctly.

                                                📊 Application

                                                You’re all set! Just pass the values from chartSize to the visualization component, and it will become responsive.

                                                Here is a full example with code:


                                                \ No newline at end of file +)

                                                Use the hook

                                                Then, pass this newly created chartRef to the hook:

                                                const chartSize = useDimensions(chartRef);

                                                You now have an object called chartSize with two properties: height and width. These properties can be used in your chart component. 🔥

                                                Pro tip: Before building a responsive visualization, use console.log() to check the chartSize object and ensure everything is working correctly.

                                                📊 Application

                                                You’re all set! Just pass the values from chartSize to the visualization component, and it will become responsive.

                                                Here is a full example with code:


                                                \ No newline at end of file diff --git a/course/scales/introduction.html b/course/scales/introduction.html index f737d19f..b06c33b5 100644 --- a/course/scales/introduction.html +++ b/course/scales/introduction.html @@ -1,5 +1,5 @@ -Introduction to scales

                                                Introduction to scales


                                                Building a graph requires to transform a dimension (a numeric variable in your dataset) in a position in pixels. This is done using a fundamental dataviz concept called scale.

                                                Before implementing it in the next lesson, let's describe a bit what this crucial concept of dataviz is.

                                                Wip
                                                4 minutes read

                                                Test your intuition

                                                Let's test your intuition with the following exercise.

                                                • 1️⃣ You have a SVG area with a width of 500px.
                                                • 2️⃣ You can place circles anywhere along this area horizontally.
                                                • 3️⃣ You have a dataset with 5 values: 0, 50, 60, 82, 100

                                                How do you position your circles to represent this dataset? Drag the circles below following your intuition:

                                                Note: the number in each circle represents its value in the dataset.

                                                05060821000 px250 px500 px

                                                How it actually works

                                                The obvious part:

                                                → For a value of 0, the circle should be placed at the extreme left of the SVG. This corresponds to cx = 0px.

                                                → For the highest value in the dataset, 100, the circle should be positioned at the extreme right of the SVG. This corresponds to cx = width (i.e., 500px).

                                                → For a value of 50, which is the midpoint of our dataset, the circle should be positioned at the center of the SVG. This corresponds to cx = width / 2 (i.e., 250px).

                                                The math part:

                                                For a value of 82, which is not an exact midpoint, you need to calculate the position proportionally.

                                                The position can be calculated as:

                                                // Linear scale equation
                                                +Introduction to scales

                                                Introduction to scales


                                                Building a graph requires to transform a dimension (a numeric variable in your dataset) in a position in pixels. This is done using a fundamental dataviz concept called scale.

                                                Before implementing it in the next lesson, let's describe a bit what this crucial concept of dataviz is.

                                                Wip
                                                4 minutes read

                                                Test your intuition

                                                Let's test your intuition with the following exercise.

                                                • 1️⃣ You have a SVG area with a width of 500px.
                                                • 2️⃣ You can place circles anywhere along this area horizontally.
                                                • 3️⃣ You have a dataset with 5 values: 0, 50, 60, 82, 100

                                                How do you position your circles to represent this dataset? Drag the circles below following your intuition:

                                                Note: the number in each circle represents its value in the dataset.

                                                05060821000 px250 px500 px

                                                How it actually works

                                                The obvious part:

                                                → For a value of 0, the circle should be placed at the extreme left of the SVG. This corresponds to cx = 0px.

                                                → For the highest value in the dataset, 100, the circle should be positioned at the extreme right of the SVG. This corresponds to cx = width (i.e., 500px).

                                                → For a value of 50, which is the midpoint of our dataset, the circle should be positioned at the center of the SVG. This corresponds to cx = width / 2 (i.e., 250px).

                                                The math part:

                                                For a value of 82, which is not an exact midpoint, you need to calculate the position proportionally.

                                                The position can be calculated as:

                                                // Linear scale equation
                                                 cx = (value / maxValue) * width
                                                 
                                                 // cx = (82 / 100) * 500
                                                -// cx = 410px

                                                The Great News 🎁

                                                Manually calculating positions for each data point would be incredibly tedious for every graph you create.

                                                Fortunately, d3.js provides a function called scaleLinear() that handles this task for you. In the next lesson, we'll explore how it works and simplifies your data visualization process.

                                                \ No newline at end of file +// cx = 410px

                                                The Great News 🎁

                                                Manually calculating positions for each data point would be incredibly tedious for every graph you create.

                                                Fortunately, d3.js provides a function called scaleLinear() that handles this task for you. In the next lesson, we'll explore how it works and simplifies your data visualization process.

                                                \ No newline at end of file diff --git a/course/svg/introduction.html b/course/svg/introduction.html index 4857d804..4a65fe3a 100644 --- a/course/svg/introduction.html +++ b/course/svg/introduction.html @@ -1 +1 @@ -Introduction to svg

                                                Introduction to svg


                                                At its core, a graph is just a bunch of shapes such as circles, rectangles, and lines displayed on a screen. Using standard HTML elements to draw these shapes would be cumbersome and limiting.

                                                Fortunately, there's a more efficient solution: SVG. SVG is a versatile and widely-used technology that allows us to draw shapes in the browser with precision and ease.

                                                In this module, we'll explore how SVG works and how it can be harnessed to create dynamic and insightful data visualizations.

                                                Free
                                                4 minutes read

                                                What is SVG

                                                Scalable Vector Graphics (SVG) is an XML-based format for vector graphics. Unlike raster graphics which are made up of pixels, SVG uses vector data (points, lines, and curves) to create images. This means SVG images are resolution-independent and can scale up or down without losing quality.

                                                Most simple example

                                                Here is a very simple react app that uses SVG to render a circle:

                                                • A react component called SvgCircle is defined in a file called SvgCircle.tsx.
                                                • It renders an SVG area thank to a <svg> HTML element. It has some width and height
                                                • In this SVG area, a <circle> is drawn. cx and cy set the position of the circle. r its radius.

                                                Awesome! 🔆

                                                With just a few more circles like this, we'll have a complete scatterplot!

                                                Note: The coordinate system of SVG starts at the top-left corner, where the origin point (0,0) is located.

                                                You can style SVG

                                                SHow that yu can add a css file and it works. But it has some specificity.

                                                Benefits
                                                Pros

                                                • Scalability: SVG images maintain their quality at any size, making them ideal for responsive design. Whether viewed on a small mobile screen or a large desktop monitor, SVG graphics look crisp and clear.
                                                • Interactivity: SVG elements can be styled and animated using CSS and JavaScript, allowing for dynamic and interactive graphics. This makes SVG a powerful tool for creating engaging data visualizations.
                                                • Accessibility: Text within SVG is searchable and accessible by screen readers. This enhances the accessibility of web content, making it more usable for people with disabilities.
                                                • Performance: SVG files are often smaller in size compared to raster images, especially for complex graphics. This can lead to faster load times and improved performance of web pages.

                                                Limitations
                                                Cons

                                                While SVG is a powerful tool for creating high-quality, scalable graphics, it does have performance limitations, especially when used for data visualization.

                                                As SVG graphs are defined in the DOM, each shape or element added to an SVG increases the number of DOM nodes. For complex visualizations with a large number of elements, such as detailed scatterplots or large datasets, this can make the DOM very heavy.

                                                As a result, the browser may become slow and unresponsive due to the increased workload of rendering and managing numerous SVG elements. This can lead to performance bottlenecks, particularly on devices with limited processing power or memory.

                                                \ No newline at end of file +Introduction to svg

                                                Introduction to svg


                                                At its core, a graph is just a bunch of shapes such as circles, rectangles, and lines displayed on a screen. Using standard HTML elements to draw these shapes would be cumbersome and limiting.

                                                Fortunately, there's a more efficient solution: SVG. SVG is a versatile and widely-used technology that allows us to draw shapes in the browser with precision and ease.

                                                In this module, we'll explore how SVG works and how it can be harnessed to create dynamic and insightful data visualizations.

                                                Free
                                                4 minutes read

                                                What is SVG

                                                Scalable Vector Graphics (SVG) is an XML-based format for vector graphics. Unlike raster graphics which are made up of pixels, SVG uses vector data (points, lines, and curves) to create images. This means SVG images are resolution-independent and can scale up or down without losing quality.

                                                Most simple example

                                                Here is a very simple react app that uses SVG to render a circle:

                                                • A react component called SvgCircle is defined in a file called SvgCircle.tsx.
                                                • It renders an SVG area thank to a <svg> HTML element. It has some width and height
                                                • In this SVG area, a <circle> is drawn. cx and cy set the position of the circle. r its radius.

                                                Awesome! 🔆

                                                With just a few more circles like this, we'll have a complete scatterplot!

                                                Note: The coordinate system of SVG starts at the top-left corner, where the origin point (0,0) is located.

                                                You can style SVG

                                                SHow that yu can add a css file and it works. But it has some specificity.

                                                Benefits
                                                Pros

                                                • Scalability: SVG images maintain their quality at any size, making them ideal for responsive design. Whether viewed on a small mobile screen or a large desktop monitor, SVG graphics look crisp and clear.
                                                • Interactivity: SVG elements can be styled and animated using CSS and JavaScript, allowing for dynamic and interactive graphics. This makes SVG a powerful tool for creating engaging data visualizations.
                                                • Accessibility: Text within SVG is searchable and accessible by screen readers. This enhances the accessibility of web content, making it more usable for people with disabilities.
                                                • Performance: SVG files are often smaller in size compared to raster images, especially for complex graphics. This can lead to faster load times and improved performance of web pages.

                                                Limitations
                                                Cons

                                                While SVG is a powerful tool for creating high-quality, scalable graphics, it does have performance limitations, especially when used for data visualization.

                                                As SVG graphs are defined in the DOM, each shape or element added to an SVG increases the number of DOM nodes. For complex visualizations with a large number of elements, such as detailed scatterplots or large datasets, this can make the DOM very heavy.

                                                As a result, the browser may become slow and unresponsive due to the increased workload of rendering and managing numerous SVG elements. This can lead to performance bottlenecks, particularly on devices with limited processing power or memory.

                                                \ No newline at end of file diff --git a/course/svg/main-svg-elements.html b/course/svg/main-svg-elements.html index ad77d77c..36e48321 100644 --- a/course/svg/main-svg-elements.html +++ b/course/svg/main-svg-elements.html @@ -1 +1 @@ -Main SVG elements

                                                Main SVG elements


                                                In the previous lesson, we learned about SVG and how to draw a circle with it.

                                                To create comprehensive graphs, we'll also need other shapes such as rectangles, text, and lines. Let's explore how to create these as well.

                                                Free
                                                4 minutes read

                                                Rectangle

                                                SVG rectangles are created using the <rect> element, which requires the position and size attributes. The x and y attributes specify the coordinates of the top-left corner, while width and height determine the size of the rectangle.

                                                For example, this code will draw a blue rectangle with the top-left corner at (10,10) and dimensions of 80x50.

                                                <rect x="10" y="10" width="80" height="50" fill="blue" />

                                                Here is an interactive example so that you can experiment with rectangles and understand how they work.

                                                Line

                                                SVG lines are created using the <line> element, which requires the starting (x1, y1) and ending (x2, y2) coordinates as attributes.

                                                For example, this code will draw a black line from the point (0,0) to the point (100,100).

                                                <line x1="0" y1="0" x2="100" y2="100" stroke="black"/>

                                                Here is an interactive example so that you can play a bit with lines and understand how they work.

                                                Text

                                                SVG text is created using the <text> element, which requires coordinates to specify where the text should be placed. The x and y attributes define the position of the starting point of the text.

                                                For example, this code will display the text "Hello, SVG!" at the coordinates (50,50).

                                                <text x="50" y="50" fill="black">Hello, SVG!</text>

                                                Here is an interactive example so that you can experiment with text and understand how it works.

                                                Circle

                                                We talked about them already, but remember that SVG circles are created using the <circle> element, which requires the center coordinates and radius as attributes.

                                                The cx and cy attributes specify the center point, while the r attribute determines the radius of the circle.

                                                For example, this code will draw a red circle with a center at (50,50) and a radius of 40.

                                                <circle cx="50" cy="50" r="40" fill="red" />

                                                Here is an interactive example so that you can experiment with circles and understand how they work.

                                                Exercices

                                                \ No newline at end of file +Main SVG elements

                                                Main SVG elements


                                                In the previous lesson, we learned about SVG and how to draw a circle with it.

                                                To create comprehensive graphs, we'll also need other shapes such as rectangles, text, and lines. Let's explore how to create these as well.

                                                Free
                                                4 minutes read

                                                Rectangle

                                                SVG rectangles are created using the <rect> element, which requires the position and size attributes. The x and y attributes specify the coordinates of the top-left corner, while width and height determine the size of the rectangle.

                                                For example, this code will draw a blue rectangle with the top-left corner at (10,10) and dimensions of 80x50.

                                                <rect x="10" y="10" width="80" height="50" fill="blue" />

                                                Here is an interactive example so that you can experiment with rectangles and understand how they work.

                                                Line

                                                SVG lines are created using the <line> element, which requires the starting (x1, y1) and ending (x2, y2) coordinates as attributes.

                                                For example, this code will draw a black line from the point (0,0) to the point (100,100).

                                                <line x1="0" y1="0" x2="100" y2="100" stroke="black"/>

                                                Here is an interactive example so that you can play a bit with lines and understand how they work.

                                                Text

                                                SVG text is created using the <text> element, which requires coordinates to specify where the text should be placed. The x and y attributes define the position of the starting point of the text.

                                                For example, this code will display the text "Hello, SVG!" at the coordinates (50,50).

                                                <text x="50" y="50" fill="black">Hello, SVG!</text>

                                                Here is an interactive example so that you can experiment with text and understand how it works.

                                                Circle

                                                We talked about them already, but remember that SVG circles are created using the <circle> element, which requires the center coordinates and radius as attributes.

                                                The cx and cy attributes specify the center point, while the r attribute determines the radius of the circle.

                                                For example, this code will draw a red circle with a center at (50,50) and a radius of 40.

                                                <circle cx="50" cy="50" r="40" fill="red" />

                                                Here is an interactive example so that you can experiment with circles and understand how they work.

                                                Exercices

                                                \ No newline at end of file diff --git a/course/svg/path-element.html b/course/svg/path-element.html index 9409f2dd..f3c1dac5 100644 --- a/course/svg/path-element.html +++ b/course/svg/path-element.html @@ -1,7 +1,7 @@ -The path element

                                                The path element


                                                In this lesson, we'll dive into one of the most versatile and powerful elements in SVG: the <path> element.

                                                The <path> element allows you to create complex shapes and lines that go beyond the basic geometric shapes. It is essential to build some graph types like an area chart or a line chart.

                                                Free
                                                4 minutes read

                                                Most basic example

                                                The <path> element allows to draw literally any shape in the SVG area.

                                                You provide it with a series of drawing commands that will make straight or curved lines, resulting in your final shape.

                                                Let's check a basic example:

                                                <svg height="300" width="400">
                                                +The path element

                                                The path element


                                                In this lesson, we'll dive into one of the most versatile and powerful elements in SVG: the <path> element.

                                                The <path> element allows you to create complex shapes and lines that go beyond the basic geometric shapes. It is essential to build some graph types like an area chart or a line chart.

                                                Free
                                                4 minutes read

                                                Most basic example

                                                The <path> element allows to draw literally any shape in the SVG area.

                                                You provide it with a series of drawing commands that will make straight or curved lines, resulting in your final shape.

                                                Let's check a basic example:

                                                <svg height="300" width="400">
                                                   <path
                                                     d="M0 105 L100 200 L200 200 L300 20 L350 120"
                                                     fill="none"
                                                     stroke="#69b3a2"
                                                   />
                                                -</svg>

                                                This will result in the following shape:

                                                Nice! This almost look like a line chart already!

                                                As you can see the <path> element expect a required d attribute. This attribute defines the shape of the path. Let's discover its syntax.

                                                Understanding the d Attribute

                                                The d attribute defines the shape and outline of the path by specifying a series of drawing commands.

                                                Each command consists of a letter that represents the type of drawing action (such as M for Move To) followed by one or more numbers that define the coordinates or control points.

                                                Here is a breakdown of the svg path above:

                                                • M0 105: moves the starting point of the path to coordinates 0, 105. (M stands for move to)
                                                • L100 200: draws a straight line from the current point (0, 105) to the point (100, 200). (L stands for line to)
                                                • 200 200: draws a new straight line from the current point to the point (200, 200).

                                                Now, experiment with some changes in the sandbox below to get a better understanding of how it works:

                                                The good news 🎁

                                                You won’t need to manually write the d attribute yourself. Understanding its role is helpful, but in practice, you'll rely on d3.js helper functions to generate paths for you.

                                                These functions take your data and automatically convert it into the appropriate path data.

                                                This is one of the reasons why d3.js is so powerful and beloved for data visualization! 💙

                                                Exercises

                                                \ No newline at end of file +</svg>

                                                This will result in the following shape:

                                                Nice! This almost look like a line chart already!

                                                As you can see the <path> element expect a required d attribute. This attribute defines the shape of the path. Let's discover its syntax.

                                                Understanding the d Attribute

                                                The d attribute defines the shape and outline of the path by specifying a series of drawing commands.

                                                Each command consists of a letter that represents the type of drawing action (such as M for Move To) followed by one or more numbers that define the coordinates or control points.

                                                Here is a breakdown of the svg path above:

                                                • M0 105: moves the starting point of the path to coordinates 0, 105. (M stands for move to)
                                                • L100 200: draws a straight line from the current point (0, 105) to the point (100, 200). (L stands for line to)
                                                • 200 200: draws a new straight line from the current point to the point (200, 200).

                                                Now, experiment with some changes in the sandbox below to get a better understanding of how it works:

                                                The good news 🎁

                                                You won’t need to manually write the d attribute yourself. Understanding its role is helpful, but in practice, you'll rely on d3.js helper functions to generate paths for you.

                                                These functions take your data and automatically convert it into the appropriate path data.

                                                This is one of the reasons why d3.js is so powerful and beloved for data visualization! 💙

                                                Exercises

                                                \ No newline at end of file diff --git a/course/svg/tips-and-tricks.html b/course/svg/tips-and-tricks.html index d736c635..1f42673d 100644 --- a/course/svg/tips-and-tricks.html +++ b/course/svg/tips-and-tricks.html @@ -1 +1 @@ -SVG tips & tricks

                                                SVG tips & tricks


                                                By now, SVG might seem straightforward, but trust me, it has its quirks that can make your data visualization journey challenging.

                                                In this lesson, I'll share some tips and tricks that can save yo hours of frustration — lessons I learned the hard way.

                                                Wip
                                                4 minutes read

                                                1️⃣ SVG Elements Don’t Have a Background Color

                                                Unlike HTML elements, SVG elements do not support background colors directly. They also do not support borders.

                                                If you want to create a background or add a border to your SVG, you need to draw a rectangle that covers the desired area. CSS properties like background-color or fill or border on the SVG element itself are not recognized and will be ignored.

                                                Example:

                                                2️⃣ Text Alignment in SVG

                                                Text alignment in SVG works differently compared to HTML. You can control both horizontal and vertical alignment using the text-anchor and alignment-baseline properties, which are unique to SVG.


                                                Here’s a summary of how they work:

                                                text-anchor controls the horizontal alignment →
                                                alignment-baseline controls the vertical alignment →
                                                This is some text

                                                3️⃣ Grouping Elements with <g>

                                                The <g> element in SVG is used to group multiple elements together.

                                                This is especially useful for applying transformations, styles, or events to a collection of elements as a single unit.

                                                4️⃣ Stroke, Fill, and Color: Different from HTML

                                                In SVG, the concepts of stroke, fill, and color work differently than in standard HTML. The fill property controls the interior color of shapes, while stroke affects the outline. Unlike div elements, SVG shapes don’t have separate properties for borders and backgrounds; instead, you use stroke and fill to control these aspects.

                                                For text elements, avoid using stroke to outline text, as it can result in poor readability. Instead, focus on using fill for color and text-anchor for alignment.

                                                5️⃣ CSS Specificity in SVG

                                                CSS specificity in SVG can be a bit more complex than in HTML. Styles applied to SVG elements can come from inline styles, internal stylesheets, or external stylesheets, and the rules of specificity still apply. However, because SVG elements are often nested and grouped, understanding which styles take precedence requires a good grasp of CSS specificity rules.

                                                6️⃣ Text Specificity in SVG vs. HTML

                                                In SVG, there is no built-in functionality for automatic text wrapping like you would find in HTML or CSS. You have to manage text wrapping manually or use JavaScript libraries to handle it. You need to calculate where to break the text and create multiple

                                                This is very super annoying. We will talk about workarounds in this course.

                                                7️⃣ SVG Dimensions: The Impact of “100%”

                                                Setting SVG dimensions to "100%" can lead to unexpected results, especially in responsive designs. SVGs can scale based on their container, but how they scale depends on the viewBox and preserveAspectRatio attributes. Understanding these attributes is key to ensuring your SVGs display correctly across different screen sizes. For more details, refer to our module on responsiveness.

                                                8️⃣ Filters, Blur Effects, and Gradients

                                                SVG offers powerful capabilities for applying visual effects, such as filters and gradients. Filters like blur, drop-shadow, and grayscale can add depth and dimension to your graphics. Gradients allow for smooth transitions between colors, which can be applied to fills or strokes, adding richness to your visualizations.

                                                9️⃣ Stacking Order Matters

                                                In SVG, elements are rendered in the order they appear in the markup, creating a natural stacking order. This means that the order of elements in your SVG code affects their visual layering. Elements later in the code will appear on top of earlier ones, so careful planning is needed when layering elements to achieve the desired visual effect.

                                                🔟 Dealing with Blurry SVG Elements

                                                SVG elements can sometimes appear blurry, especially when scaled. This is often due to anti-aliasing, which can smooth edges but also cause them to lose sharpness. To fix this, you can use the shape-rendering="crispEdges" property to make edges appear sharper, especially for pixel-perfect designs.

                                                \ No newline at end of file +SVG tips & tricks

                                                SVG tips & tricks


                                                By now, SVG might seem straightforward, but trust me, it has its quirks that can make your data visualization journey challenging.

                                                In this lesson, I'll share some tips and tricks that can save yo hours of frustration — lessons I learned the hard way.

                                                Wip
                                                4 minutes read

                                                1️⃣ SVG Elements Don’t Have a Background Color

                                                Unlike HTML elements, SVG elements do not support background colors directly. They also do not support borders.

                                                If you want to create a background or add a border to your SVG, you need to draw a rectangle that covers the desired area. CSS properties like background-color or fill or border on the SVG element itself are not recognized and will be ignored.

                                                Example:

                                                2️⃣ Text Alignment in SVG

                                                Text alignment in SVG works differently compared to HTML. You can control both horizontal and vertical alignment using the text-anchor and alignment-baseline properties, which are unique to SVG.


                                                Here’s a summary of how they work:

                                                text-anchor controls the horizontal alignment →
                                                alignment-baseline controls the vertical alignment →
                                                This is some text

                                                3️⃣ Grouping Elements with <g>

                                                The <g> element in SVG is used to group multiple elements together.

                                                This is especially useful for applying transformations, styles, or events to a collection of elements as a single unit.

                                                4️⃣ Stroke, Fill, and Color: Different from HTML

                                                In SVG, the concepts of stroke, fill, and color work differently than in standard HTML. The fill property controls the interior color of shapes, while stroke affects the outline. Unlike div elements, SVG shapes don’t have separate properties for borders and backgrounds; instead, you use stroke and fill to control these aspects.

                                                For text elements, avoid using stroke to outline text, as it can result in poor readability. Instead, focus on using fill for color and text-anchor for alignment.

                                                5️⃣ CSS Specificity in SVG

                                                CSS specificity in SVG can be a bit more complex than in HTML. Styles applied to SVG elements can come from inline styles, internal stylesheets, or external stylesheets, and the rules of specificity still apply. However, because SVG elements are often nested and grouped, understanding which styles take precedence requires a good grasp of CSS specificity rules.

                                                6️⃣ Text Specificity in SVG vs. HTML

                                                In SVG, there is no built-in functionality for automatic text wrapping like you would find in HTML or CSS. You have to manage text wrapping manually or use JavaScript libraries to handle it. You need to calculate where to break the text and create multiple

                                                This is very super annoying. We will talk about workarounds in this course.

                                                7️⃣ SVG Dimensions: The Impact of “100%”

                                                Setting SVG dimensions to "100%" can lead to unexpected results, especially in responsive designs. SVGs can scale based on their container, but how they scale depends on the viewBox and preserveAspectRatio attributes. Understanding these attributes is key to ensuring your SVGs display correctly across different screen sizes. For more details, refer to our module on responsiveness.

                                                8️⃣ Filters, Blur Effects, and Gradients

                                                SVG offers powerful capabilities for applying visual effects, such as filters and gradients. Filters like blur, drop-shadow, and grayscale can add depth and dimension to your graphics. Gradients allow for smooth transitions between colors, which can be applied to fills or strokes, adding richness to your visualizations.

                                                9️⃣ Stacking Order Matters

                                                In SVG, elements are rendered in the order they appear in the markup, creating a natural stacking order. This means that the order of elements in your SVG code affects their visual layering. Elements later in the code will appear on top of earlier ones, so careful planning is needed when layering elements to achieve the desired visual effect.

                                                🔟 Dealing with Blurry SVG Elements

                                                SVG elements can sometimes appear blurry, especially when scaled. This is often due to anti-aliasing, which can smooth edges but also cause them to lose sharpness. To fix this, you can use the shape-rendering="crispEdges" property to make edges appear sharper, especially for pixel-perfect designs.

                                                \ No newline at end of file diff --git a/cross-graph-highlight-interaction.html b/cross-graph-highlight-interaction.html index 5d2d1e75..823bf1ab 100644 --- a/cross-graph-highlight-interaction.html +++ b/cross-graph-highlight-interaction.html @@ -1,4 +1,4 @@ -Cross graph highlight interaction

                                                Cross graph highlight interaction


                                                This post explains how to add cross graph interactions in a react app. It focus on performance, showing how a naive approach with a shared state leads to a disappointing result and how a react context can solve the problem.

                                                Disclaimer: the concepts explained here where showed to me by my colleague Gabriel Vergnaud.

                                                What is cross graph interaction

                                                What it is.

                                                working example

                                                Why do we care?

                                                Focus on performance

                                                Naive solution: shared state

                                                A first solution: a shared state. You defined a react state at the level of the component that wraps all your viz with useState:

                                                const [group, setGroup] = useState<number | null>(null);

                                                You then pass the state and the setter function to each viz. Something like:

                                                <Barplot
                                                +Cross graph highlight interaction

                                                Cross graph highlight interaction


                                                This post explains how to add cross graph interactions in a react app. It focus on performance, showing how a naive approach with a shared state leads to a disappointing result and how a react context can solve the problem.

                                                Disclaimer: the concepts explained here where showed to me by my colleague Gabriel Vergnaud.

                                                What is cross graph interaction

                                                What it is.

                                                working example

                                                Why do we care?

                                                Focus on performance

                                                Naive solution: shared state

                                                A first solution: a shared state. You defined a react state at the level of the component that wraps all your viz with useState:

                                                const [group, setGroup] = useState<number | null>(null);

                                                You then pass the state and the setter function to each viz. Something like:

                                                <Barplot
                                                   width={300}
                                                   height={220}
                                                   group={group}
                                                @@ -11,4 +11,4 @@
                                                 

                                                Contact

                                                👋 Hey, I'm Yan and I'm currently working on this project!

                                                Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                  -
                                                  \ No newline at end of file +
                                                  \ No newline at end of file diff --git a/dataset-transition.html b/dataset-transition.html index 7ab47974..721d8abb 100644 --- a/dataset-transition.html +++ b/dataset-transition.html @@ -1,4 +1,4 @@ -Smooth dataset transition

                                                  Animated dataset transition


                                                  How to smoothly transition from a dataset to the other. Use the react-spring library. Several examples with explanation. Start simple. Then focus on tricky things like enter, exit, axis, path.

                                                  A minimal react-spring dataviz example. A viz component expect a position and a color prop. But it smoothly animates the transition.

                                                  Most basic

                                                  Consider a change where dataset has the same structure, just the values change. Same number of items.

                                                  Also, just animating a prop of a shape

                                                  Very simple, just animate the bar width

                                                  Spring looks like this

                                                  const springProps = useSpring({
                                                  +Smooth dataset transition

                                                  Animated dataset transition


                                                  How to smoothly transition from a dataset to the other. Use the react-spring library. Several examples with explanation. Start simple. Then focus on tricky things like enter, exit, axis, path.

                                                  A minimal react-spring dataviz example. A viz component expect a position and a color prop. But it smoothly animates the transition.

                                                  Most basic

                                                  Consider a change where dataset has the same structure, just the values change. Same number of items.

                                                  Also, just animating a prop of a shape

                                                  Very simple, just animate the bar width

                                                  Spring looks like this

                                                  const springProps = useSpring({
                                                     to: {
                                                       barWidth,
                                                     }
                                                  @@ -14,4 +14,4 @@
                                                   

                                                  Contact

                                                  👋 Hey, I'm Yan and I'm currently working on this project!

                                                  Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                    -
                                                    \ No newline at end of file +
                                                    \ No newline at end of file diff --git a/dendrogram.html b/dendrogram.html index c754272b..a3fda979 100644 --- a/dendrogram.html +++ b/dendrogram.html @@ -1,4 +1,4 @@ -Dendrogram | The React Graph Gallery

                                                    Dendrogram

                                                    Dataviz logo representing a Dendrogram chart.

                                                    A dendrogram is a network structure. It is constituted of a root node that gives birth to several nodes connected by edges or branches. The last nodes of the hierarchy are called leaves.

                                                    This page explains how to build a dendrogram using d3.js to compute the node position, and React to render the nodes and edges. It starts by describing the required data format, explains how to build a very basicdendrogram and then shows how to customize it.

                                                    Useful links

                                                    The Data

                                                    The dataset describes a hierarchy using a recursive structure.

                                                    Each item in this structure is called a node. The lowest nodes of the hierarchy being called leaves. The dataset is an object that has at least 3 properties: name, value and children. Children is an array of nodes that have this structure too.

                                                    Here is a minimal example of the data structure:

                                                    const data = {
                                                    +Dendrogram | The React Graph Gallery

                                                    Dendrogram

                                                    Dataviz logo representing a Dendrogram chart.

                                                    A dendrogram is a network structure. It is constituted of a root node that gives birth to several nodes connected by edges or branches. The last nodes of the hierarchy are called leaves.

                                                    This page explains how to build a dendrogram using d3.js to compute the node position, and React to render the nodes and edges. It starts by describing the required data format, explains how to build a very basicdendrogram and then shows how to customize it.

                                                    Useful links

                                                    The Data

                                                    The dataset describes a hierarchy using a recursive structure.

                                                    Each item in this structure is called a node. The lowest nodes of the hierarchy being called leaves. The dataset is an object that has at least 3 properties: name, value and children. Children is an array of nodes that have this structure too.

                                                    Here is a minimal example of the data structure:

                                                    const data = {
                                                       type: 'node',
                                                       name: "boss",
                                                       value: 2300,
                                                    @@ -52,4 +52,4 @@
                                                     const dendrogram = dendrogramGenerator(hierarchy);

                                                    Since x and y are now describing an angle and a distance to the center, we can position a node using the following transform property:

                                                    transform={"rotate(" + (node.x - 90) + ")translate(" + node.y + ")"}

                                                    → Smooth edges with linkRadial

                                                    Edges are not horizontal anymore, so the linkHorizontal won't be helpful this time. But instead, the d3.linkRadial function does the job based on an angle and a distance.

                                                    → Smart labels

                                                    Please make sure your labels are properly oriented. It always give a bit of a headhache to pivot them correctly, and to control the anchoring appropriately. I talked about it extensively in the circular barplot section so please take a look for this matter.

                                                    ;;;MarkRobertEmilyMarionNicolasMalkiDjéMélanieEinstein

                                                    A minimalist radial dendrogram built using d3 and react.

                                                    Note: please check of the first level edges are straight lines. IMO it does not make sense to use linkRadial for the first level.

                                                    Coming next

                                                    There is much more that needs to be added to this tutorial.

                                                    Using canvas for rendering is often a requirement when the number of nodes gets big. Interactivity is often necessary, for hover effect or to collapse a part of the tree. It also possible to map the node circle size to a numeric variable.

                                                    This will come soon! I have a newsletter called the dataviz universe where I share my latest updates.

                                                    Subscribe

                                                    Contact

                                                    👋 Hey, I'm Yan and I'm currently working on this project!

                                                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                      -
                                                      \ No newline at end of file +
                                                      \ No newline at end of file diff --git a/density-plot.html b/density-plot.html index b47187b1..8028450c 100644 --- a/density-plot.html +++ b/density-plot.html @@ -1,4 +1,4 @@ -Density chart with React

                                                      Density chart

                                                      Dataviz logo representing a Density chart.

                                                      A density plot is a chart type that shows the distribution of a numeric variable. This page is a step-by-step guide on how to build your own density plot for the web, using React and D3.js.

                                                      It starts by describing how the data should be organized and how to initialize the density component. It then explains how to compute a kernel density. Once this is done, it shows how to render the density shape and suggests a few variations. 🙇‍♂️.

                                                      Useful links

                                                      The Data

                                                      Building a density chart only requires a set of numeric values.

                                                      As a result, the dataset is pretty simple: just an array of number.


                                                      Here is a minimal example of the data structure:

                                                      export const data = [
                                                      +Density chart with React

                                                      Density chart

                                                      Dataviz logo representing a Density chart.

                                                      A density plot is a chart type that shows the distribution of a numeric variable. This page is a step-by-step guide on how to build your own density plot for the web, using React and D3.js.

                                                      It starts by describing how the data should be organized and how to initialize the density component. It then explains how to compute a kernel density. Once this is done, it shows how to render the density shape and suggests a few variations. 🙇‍♂️.

                                                      Useful links

                                                      The Data

                                                      Building a density chart only requires a set of numeric values.

                                                      As a result, the dataset is pretty simple: just an array of number.


                                                      Here is a minimal example of the data structure:

                                                      export const data = [
                                                         75.0,
                                                         104.0,
                                                         369.0,
                                                      @@ -86,4 +86,4 @@
                                                       }

                                                      I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                      Density inspiration

                                                      If you're looking for inspiration to create your next Density, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                      dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Density looks good!

                                                      visit

                                                      Variations

                                                      Once you've understood how to build a basic density chart with d3 and React, it opens an infinite world of customization.

                                                      Here is an example showing how to plot several distributions on the same figure, allowing to compare several groups.

                                                      Using small multiple to visualize the distribution of several groups in 1 figure, avoiding overlapping.

                                                      Note that an alternative could be to use small multiple. See this histogram example that you should be able to adapt quickly.

                                                      Contact

                                                      👋 Hey, I'm Yan and I'm currently working on this project!

                                                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                        -
                                                        \ No newline at end of file +
                                                        \ No newline at end of file diff --git a/donut.html b/donut.html index 0adc1c90..028321af 100644 --- a/donut.html +++ b/donut.html @@ -1,4 +1,4 @@ -Donut chart | The React Graph Gallery

                                                        Donut chart

                                                        Dataviz logo representing a Doughnut chart.

                                                        The donut chart is a very common yet criticized way to represent the value of a few groups in a dataset. It is very close to the pie chart and thus suffers the same downsides.

                                                        This page explains how to build a donut chart using d3.js and React. It starts with a basic example and then focus on customization like legends, hover effect and dataset transition.

                                                        Useful links

                                                        The Data

                                                        The dataset required to build a donut chart is an array where each item represents a group. Each item is an object with 2 properties. They provide the group name (name) and its value (value).


                                                        For instance, here is the dataset used for the simple donut chart below:

                                                        const data = [
                                                        +Donut chart | The React Graph Gallery

                                                        Donut chart

                                                        Dataviz logo representing a Doughnut chart.

                                                        The donut chart is a very common yet criticized way to represent the value of a few groups in a dataset. It is very close to the pie chart and thus suffers the same downsides.

                                                        This page explains how to build a donut chart using d3.js and React. It starts with a basic example and then focus on customization like legends, hover effect and dataset transition.

                                                        Useful links

                                                        The Data

                                                        The dataset required to build a donut chart is an array where each item represents a group. Each item is an object with 2 properties. They provide the group name (name) and its value (value).


                                                        For instance, here is the dataset used for the simple donut chart below:

                                                        const data = [
                                                           {name:"Mark", value: 90},
                                                           {name:"Robert", value: 12},
                                                           {name:"Emily", value: 34},
                                                        @@ -48,4 +48,4 @@
                                                         }

                                                        I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                        Donut inspiration

                                                        If you're looking for inspiration to create your next Donut, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                        dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Donut looks good!

                                                        visit

                                                        Hover effect

                                                        On the graph below, hovering over a slice will smoothly highlight it, giving a nice polish touch to the widget.

                                                        The process is quickly described on the pie chart hover effect section. But hover effect is a topic on itself. As a result, I plan to write a full tutorial targeting this topic only. You can subscribe to know when it's ready!

                                                        Tell me when the Hover effect post is ready!

                                                        Meanwhile, here is a donut chart with a hover effect, together with its React code:

                                                        Mark (90)Robert (12)Emily (34)Marion (53)Nicolas (58)

                                                        A donut chart with clean inline legends, built thanks to the centroid function of d3.js.

                                                        Data transition

                                                        The Pie component expects a data prop. What should we do when this data changes?

                                                        By default, the chart will update instantly, with no transition. Adding a smooth transition gives a nice polish touch to the graph. Try to switch between the 2 datasets below to see the animation in action.

                                                        The code below relies on the react-spring library. Instead of rendering a path for each slice, it uses a animated.path component that handles the spring animation for us.

                                                        The implementation is not trivial. I plan to publish a full tutorial on react-spring for data visualization soon. You can subscribe here to be notified when it is ready.

                                                        A donut chart with clean inline legends, built thanks to the centroid function of d3.js.

                                                        Note: check the blue group that appears / disappears between dataset. This kind of enter/exit pattern is something to keep in mind when building animations.

                                                        Pie chart to barplot

                                                        Pie charts are often criticized since angles are hard to read. Let's represent the same data using a pie chart or a barplot, to see what's the most insightful 🤷‍♂️.

                                                        Note that here we animate the transition between different shape types: each arc becomes a rectangle and reciprocally. This is made possible thanks to the flubber library, used in coordination with react-spring.

                                                        Once more, a full tutorial is needed here. You can subscribe here to be notified when it is ready. In the meanwhile, the code of this specific example is provided below.

                                                        Transition from a pie chart to a barplot with a smooth animation using the buttons on top.

                                                        Contact

                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                          -
                                                          \ No newline at end of file +
                                                          \ No newline at end of file diff --git a/example/arc-diagram-vertical.html b/example/arc-diagram-vertical.html index d1f66e0d..a3977c6b 100644 --- a/example/arc-diagram-vertical.html +++ b/example/arc-diagram-vertical.html @@ -1,4 +1,4 @@ -How to build a vertical arc diagram with React and D3.js.

                                                          Vertical arc diagram

                                                          Dataviz logo representing a Arc chart.

                                                          This tutorial is a variation around the general introduction to arc diagram with react and d3.js. You should probably understand the concepts described there before reading here.

                                                          This example explains how to make a vertical version of the arc diagram. The vertical version is sometimes prefered as it makes it easier to read the node labels.

                                                          A code sandbox is provided for the final result, but explanations target what's different compared to a classic horizontal arc diagram.

                                                          Useful links

                                                          Plot and code

                                                          If you are in a hurry, here is the final plot we're trying to achieve here, together with its code:🙇‍♂️

                                                          It is a very simple vertical arc diagram, a variation of thehorizontal version deeply described in the arc diagram section of the gallery

                                                          Arc section

                                                          A vertical arc diagram made with d3.js and react.

                                                          Vertical arcs

                                                          The main difficulty when it comes to make an arc diagram is to draw arcs in SVG.

                                                          The function allowing to draw arcs between 2 data points is a bit complicated since it requires to use elliptical arc curves.

                                                          You can read more explanation about the syntax in the official doc. But in the meantime here is the function I suggest to draw an arc connecting 2 points vertically:

                                                          const verticalArcGenerator = (
                                                          +How to build a vertical arc diagram with React and D3.js.

                                                          Vertical arc diagram

                                                          Dataviz logo representing a Arc chart.

                                                          This tutorial is a variation around the general introduction to arc diagram with react and d3.js. You should probably understand the concepts described there before reading here.

                                                          This example explains how to make a vertical version of the arc diagram. The vertical version is sometimes prefered as it makes it easier to read the node labels.

                                                          A code sandbox is provided for the final result, but explanations target what's different compared to a classic horizontal arc diagram.

                                                          Useful links

                                                          Plot and code

                                                          If you are in a hurry, here is the final plot we're trying to achieve here, together with its code:🙇‍♂️

                                                          It is a very simple vertical arc diagram, a variation of thehorizontal version deeply described in the arc diagram section of the gallery

                                                          Arc section

                                                          A vertical arc diagram made with d3.js and react.

                                                          Vertical arcs

                                                          The main difficulty when it comes to make an arc diagram is to draw arcs in SVG.

                                                          The function allowing to draw arcs between 2 data points is a bit complicated since it requires to use elliptical arc curves.

                                                          You can read more explanation about the syntax in the official doc. But in the meantime here is the function I suggest to draw an arc connecting 2 points vertically:

                                                          const verticalArcGenerator = (
                                                             xStart: number,
                                                             yStart: number,
                                                             xEnd: number,
                                                          @@ -25,4 +25,4 @@
                                                           };

                                                          Labels

                                                          Note that some labels have been added here compared to the vertical version.

                                                          This is the main advantage of choosing the horizontal layout!

                                                          Contact

                                                          👋 Hey, I'm Yan and I'm currently working on this project!

                                                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                            -
                                                            \ No newline at end of file +
                                                            \ No newline at end of file diff --git a/example/barplot-data-transition-animation.html b/example/barplot-data-transition-animation.html index 5cbf30f4..743eeb15 100644 --- a/example/barplot-data-transition-animation.html +++ b/example/barplot-data-transition-animation.html @@ -1,4 +1,4 @@ -Barplot with smooth dataset transition.

                                                            Barplot

                                                            Dataviz logo representing a Bar chart.

                                                            This tutorial is a variation around the general introduction to barplot with react and d3.js. You should probably understand the concepts described there before digging into animation.

                                                            This example focus on how to transition between datasets. It explains how to animate the change thanks to the react-spring library.

                                                            A code sandbox is provided for the final result, but explanations target what's different compared to an usual barplot.

                                                            Useful links

                                                            Plot and code

                                                            If you are in a hurry, this is what we're trying to achieve here 🙇‍♂️. The value of several individuals is represented, with one bar per individual. It's just a horizontal barplot.

                                                            It is possible to switch from one dataset to another using the buttons above the chart. A few notes on the 3 usual animation patterns:

                                                            • update: bars smoothly update their rank and size when the data changes. So does their label.
                                                            • enter: when the chart first loads, bar starts from 0 and grows to its real size. This is also true for items that are available in the new dataset but not in the previous. Check Christophe when you switch to data 2.
                                                            • exit: when an item is not available in the next dataset, it disappears with no animation (see Paul when switching to data2).

                                                            Barplot with smooth transition between dataset

                                                            The Data

                                                            The dataset used here is exactly the same as the one used for the simple barplot. Note that 2 similar datasets are used: data1 and data2.

                                                            Animation

                                                            Most of the code is similar to the basic barplot component. But instead of building one rect per item in the dataset, a BarItem component is called to render a rectangle that supports animation.

                                                            The react-spring library is used to create a spring animation. The rectangle properties are passed to a useSpring hook that will build the animation for us.

                                                            This is how the BarItem component looks like:

                                                            import { useSpring, animated } from "@react-spring/web";
                                                            +Barplot with smooth dataset transition.

                                                            Barplot

                                                            Dataviz logo representing a Bar chart.

                                                            This tutorial is a variation around the general introduction to barplot with react and d3.js. You should probably understand the concepts described there before digging into animation.

                                                            This example focus on how to transition between datasets. It explains how to animate the change thanks to the react-spring library.

                                                            A code sandbox is provided for the final result, but explanations target what's different compared to an usual barplot.

                                                            Useful links

                                                            Plot and code

                                                            If you are in a hurry, this is what we're trying to achieve here 🙇‍♂️. The value of several individuals is represented, with one bar per individual. It's just a horizontal barplot.

                                                            It is possible to switch from one dataset to another using the buttons above the chart. A few notes on the 3 usual animation patterns:

                                                            • update: bars smoothly update their rank and size when the data changes. So does their label.
                                                            • enter: when the chart first loads, bar starts from 0 and grows to its real size. This is also true for items that are available in the new dataset but not in the previous. Check Christophe when you switch to data 2.
                                                            • exit: when an item is not available in the next dataset, it disappears with no animation (see Paul when switching to data2).

                                                            Barplot with smooth transition between dataset

                                                            The Data

                                                            The dataset used here is exactly the same as the one used for the simple barplot. Note that 2 similar datasets are used: data1 and data2.

                                                            Animation

                                                            Most of the code is similar to the basic barplot component. But instead of building one rect per item in the dataset, a BarItem component is called to render a rectangle that supports animation.

                                                            The react-spring library is used to create a spring animation. The rectangle properties are passed to a useSpring hook that will build the animation for us.

                                                            This is how the BarItem component looks like:

                                                            import { useSpring, animated } from "@react-spring/web";
                                                             
                                                             type BarItemProps = {
                                                               name: string;
                                                            @@ -76,4 +76,4 @@
                                                             };

                                                            Contact

                                                            👋 Hey, I'm Yan and I'm currently working on this project!

                                                            Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                              -
                                                              \ No newline at end of file +
                                                              \ No newline at end of file diff --git a/example/barplot-stacked-horizontal.html b/example/barplot-stacked-horizontal.html index 034ba729..c252bbb4 100644 --- a/example/barplot-stacked-horizontal.html +++ b/example/barplot-stacked-horizontal.html @@ -1,4 +1,4 @@ -Horizontal stacked barplot.

                                                              Horizontal Stacked Barplot

                                                              Dataviz logo representing a Bar chart.

                                                              This tutorial is a variation around the general introduction to barplot with react and d3.js. You should probably understand the concepts described there before digging into stacking.

                                                              This example shows how to represent 2 levels of grouping in a barplot, resulting in a stacked barplot. The items of the dataset are divided in groups (reprented as bars) and subgroups (represented as sections in each bar).

                                                              A code sandbox is provided for the final result, but explanations target what's different compared to an usual barplot.

                                                              Useful links

                                                              Plot and code

                                                              This is a stacked barplot built using React and d3.js. The dummy dataset provides information about how much my friends spent the last month. The people are the group here. Each bar represents a group.

                                                              A second level of grouping is available. We know if the money was spent on travel, food or beer. It is possible to represent this additional amount of info using a process called stacking.

                                                              How much my friends spend on travel, food and beer.
                                                              50100150200250300312Jean294Nicolas270Mark159Marion102Emily69Mélanie54Gabriel36Robert6Paul

                                                              A horizontal stacked barplot built with d3.js for scales, and react for rendering

                                                              Now, let's see how to implement such a graph.

                                                              The Data

                                                              There are several ways to store this information in javascript. I suggest an array of object where each object provides the valueof 1 specific expense, with the group (friend name) and the subgroup (category of expense).

                                                              export const data = [
                                                              +Horizontal stacked barplot.

                                                              Horizontal Stacked Barplot

                                                              Dataviz logo representing a Bar chart.

                                                              This tutorial is a variation around the general introduction to barplot with react and d3.js. You should probably understand the concepts described there before digging into stacking.

                                                              This example shows how to represent 2 levels of grouping in a barplot, resulting in a stacked barplot. The items of the dataset are divided in groups (reprented as bars) and subgroups (represented as sections in each bar).

                                                              A code sandbox is provided for the final result, but explanations target what's different compared to an usual barplot.

                                                              Useful links

                                                              Plot and code

                                                              This is a stacked barplot built using React and d3.js. The dummy dataset provides information about how much my friends spent the last month. The people are the group here. Each bar represents a group.

                                                              A second level of grouping is available. We know if the money was spent on travel, food or beer. It is possible to represent this additional amount of info using a process called stacking.

                                                              How much my friends spend on travel, food and beer.
                                                              50100150200250300312Jean294Nicolas270Mark159Marion102Emily69Mélanie54Gabriel36Robert6Paul

                                                              A horizontal stacked barplot built with d3.js for scales, and react for rendering

                                                              Now, let's see how to implement such a graph.

                                                              The Data

                                                              There are several ways to store this information in javascript. I suggest an array of object where each object provides the valueof 1 specific expense, with the group (friend name) and the subgroup (category of expense).

                                                              export const data = [
                                                                 {group:"Mark", subgroup: "travel",  value: 90},
                                                                 {group:"Mark", subgroup: "food",  value: 23},
                                                                 {group:"Mark", subgroup: "beer",  value: 14},
                                                              @@ -29,4 +29,4 @@
                                                               ]

                                                              Rendering

                                                              Once you get the stacked data above, rendering the chart is business as usual. You can loop through the object and plot a rect for each item.

                                                              How much my friends spend on travel, food and beer.
                                                              50100150200250300312Jean294Nicolas270Mark159Marion102Emily69Mélanie54Gabriel36Robert6Paul

                                                              A horizontal stacked barplot built with d3.js for scales, and react for rendering

                                                              Variation

                                                              Check those other barplot and stacked barplot that can interest you:

                                                              Picture of a horizontal barplot made with React and d3

                                                              Basic barplot

                                                              Most basic barplot built with React and d3

                                                              GIF of a data update on a React barplot

                                                              Barplot dataset transition

                                                              How to smoothly animate the transition between dataset

                                                              Picture of a vertical stacked barchart made with react and d3

                                                              Vertical Stacked Barplot

                                                              Represent group and subgroup values by stacking the data

                                                              Contact

                                                              👋 Hey, I'm Yan and I'm currently working on this project!

                                                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                -
                                                                \ No newline at end of file +
                                                                \ No newline at end of file diff --git a/example/barplot-stacked-vertical.html b/example/barplot-stacked-vertical.html index 4f1abdac..9550d92f 100644 --- a/example/barplot-stacked-vertical.html +++ b/example/barplot-stacked-vertical.html @@ -1,4 +1,4 @@ -Vertical stacked barplot.

                                                                Vertical Stacked Barplot

                                                                Dataviz logo representing a Bar chart.

                                                                This tutorial is a variation around the general introduction to barplot with react and d3.js. You should probably understand the concepts described there before digging into stacking.

                                                                This example shows how to represent 2 levels of grouping in a barplot, resulting in a stacked barplot. The items of the dataset are divided in groups (reprented as bars) and subgroups (represented as sections in each bar).

                                                                A code sandbox is provided for the final result, but explanations target what's different compared to an usual barplot.

                                                                Useful links

                                                                Plot and code

                                                                This is a vertical stacked barplot built using React and d3.js. It is very similar to the horizontal version. So very little explanation is provided here. Enjoy the sandbox!

                                                                Most basic barplot built with d3.js for scales, and react for rendering

                                                                Variation

                                                                Check those other barplot and stacked barplot that can interest you:

                                                                Picture of a horizontal barplot made with React and d3

                                                                Basic barplot

                                                                Most basic barplot built with React and d3

                                                                GIF of a data update on a React barplot

                                                                Barplot dataset transition

                                                                How to smoothly animate the transition between dataset

                                                                Picture of a stacked barchart made with react and d3

                                                                Horizontal Stacked Barplot

                                                                Represent group and subgroup values by stacking the data

                                                                Contact

                                                                👋 Hey, I'm Yan and I'm currently working on this project!

                                                                Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                +Vertical stacked barplot.

                                                                Vertical Stacked Barplot

                                                                Dataviz logo representing a Bar chart.

                                                                This tutorial is a variation around the general introduction to barplot with react and d3.js. You should probably understand the concepts described there before digging into stacking.

                                                                This example shows how to represent 2 levels of grouping in a barplot, resulting in a stacked barplot. The items of the dataset are divided in groups (reprented as bars) and subgroups (represented as sections in each bar).

                                                                A code sandbox is provided for the final result, but explanations target what's different compared to an usual barplot.

                                                                Useful links

                                                                Plot and code

                                                                This is a vertical stacked barplot built using React and d3.js. It is very similar to the horizontal version. So very little explanation is provided here. Enjoy the sandbox!

                                                                Most basic barplot built with d3.js for scales, and react for rendering

                                                                Variation

                                                                Check those other barplot and stacked barplot that can interest you:

                                                                Picture of a horizontal barplot made with React and d3

                                                                Basic barplot

                                                                Most basic barplot built with React and d3

                                                                GIF of a data update on a React barplot

                                                                Barplot dataset transition

                                                                How to smoothly animate the transition between dataset

                                                                Picture of a stacked barchart made with react and d3

                                                                Horizontal Stacked Barplot

                                                                Represent group and subgroup values by stacking the data

                                                                Contact

                                                                👋 Hey, I'm Yan and I'm currently working on this project!

                                                                Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                  -
                                                                  \ No newline at end of file +
                                                                  \ No newline at end of file diff --git a/example/boxplot-horizontal.html b/example/boxplot-horizontal.html index 8f5f25eb..b9f1dd79 100644 --- a/example/boxplot-horizontal.html +++ b/example/boxplot-horizontal.html @@ -1,4 +1,4 @@ -Horizontal Boxplot

                                                                  Horizontal Boxplot

                                                                  Dataviz logo representing a Box1 chart.

                                                                  This tutorial is a variation around the general introduction to boxplot with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                  The general introduction relies on a VerticalBox function that draws a.. vertical box 🙃. The main difference here is that we are now building a HorizontalBox function and swap the X and Y axes.

                                                                  As usual, this post comes with explanation, a code sandbox and a template that you can reuse instantly in your web application.

                                                                  Useful links

                                                                  Horizontal Boxplot implementation

                                                                  Here is a proposal of implementation for a horizontal boxplot with react and d3.js.

                                                                  D3 actually has a very minor role here. It is only used to compute the xand y scales. The x scale is a linear scale made with the scaleLinear() function. The Y scale shows groups thanks to the scaleBand() function.

                                                                  ABCD

                                                                  A horizontal boxplot made with React and D3.js.

                                                                  Horizontal box drawing

                                                                  We need a function that draws a horizontal box in SVG based on the quartiles position in pixels.

                                                                  The function looks like this:

                                                                  export const HorizontalBox = ({
                                                                  +Horizontal Boxplot

                                                                  Horizontal Boxplot

                                                                  Dataviz logo representing a Box1 chart.

                                                                  This tutorial is a variation around the general introduction to boxplot with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                  The general introduction relies on a VerticalBox function that draws a.. vertical box 🙃. The main difference here is that we are now building a HorizontalBox function and swap the X and Y axes.

                                                                  As usual, this post comes with explanation, a code sandbox and a template that you can reuse instantly in your web application.

                                                                  Useful links

                                                                  Horizontal Boxplot implementation

                                                                  Here is a proposal of implementation for a horizontal boxplot with react and d3.js.

                                                                  D3 actually has a very minor role here. It is only used to compute the xand y scales. The x scale is a linear scale made with the scaleLinear() function. The Y scale shows groups thanks to the scaleBand() function.

                                                                  ABCD

                                                                  A horizontal boxplot made with React and D3.js.

                                                                  Horizontal box drawing

                                                                  We need a function that draws a horizontal box in SVG based on the quartiles position in pixels.

                                                                  The function looks like this:

                                                                  export const HorizontalBox = ({
                                                                     min,
                                                                     q1,
                                                                     median,
                                                                  @@ -39,4 +39,4 @@
                                                                   };

                                                                  Next steps

                                                                  This post is a translation of the basic boxplot example, switching from vertical to horizontal mode.

                                                                  Now that this basic horizontal boxplot is available, it should be straightforward to add interesting features like showing individual data points or switching to a violin plot.

                                                                  Contact

                                                                  👋 Hey, I'm Yan and I'm currently working on this project!

                                                                  Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                    -
                                                                    \ No newline at end of file +
                                                                    \ No newline at end of file diff --git a/example/boxplot-jitter.html b/example/boxplot-jitter.html index 5f9c51e3..887e8f6b 100644 --- a/example/boxplot-jitter.html +++ b/example/boxplot-jitter.html @@ -1,4 +1,4 @@ -How to build a boxplot with individual data points displayed on top using jittering.

                                                                    Boxplot

                                                                    Dataviz logo representing a Box1 chart.

                                                                    This tutorial is a variation around the general introduction to boxplot with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                    This example explains how to display all individual data points of the dataset on top of each box, using jittering to avoid overlaps.

                                                                    A code sandbox is provided for the final result, but explanations target what's different compared to an usual boxplot.

                                                                    Useful links

                                                                    Plot and code

                                                                    If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                    The distribution of several groups is represented, with one box for each group. This kind of viz is called a boxplot and has its own boxplot section.

                                                                    Even if powerful to summarize the distribution of a numeric variable, the boxplot has flaws.

                                                                    It basically hides the underlying distribution. For instance, a low sample size or a bi-modal distribution are impossible to detect reading the boxes only.

                                                                    Jittering is a good workaround. Add all individual data points with low size, low opacity, and some random shift to the right or to the left (jitter). The underlying distribution becomes instantly available.

                                                                    -5051015202530ABCD

                                                                    Showing individual data points using jittering on top of your boxplot adds trust. Reader now knows you're not hiding anything.

                                                                    The Data

                                                                    The dataset used here is exactly the same as the one used for the simple boxplot.

                                                                    Jittering

                                                                    We want to show each individual data point on top of each box for accuracy. If the dataset is big, this would result in a cluttered figure with a lot of overlap.

                                                                    Jittering is a process that shifts each circle by a random value. It avoids the overlap, and allows to make the circle layer insightful.

                                                                    Here is a suggestion to implement it:

                                                                    const allCircles = groupData.map((value, i) => (
                                                                    +How to build a boxplot with individual data points displayed on top using jittering.

                                                                    Boxplot

                                                                    Dataviz logo representing a Box1 chart.

                                                                    This tutorial is a variation around the general introduction to boxplot with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                    This example explains how to display all individual data points of the dataset on top of each box, using jittering to avoid overlaps.

                                                                    A code sandbox is provided for the final result, but explanations target what's different compared to an usual boxplot.

                                                                    Useful links

                                                                    Plot and code

                                                                    If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                    The distribution of several groups is represented, with one box for each group. This kind of viz is called a boxplot and has its own boxplot section.

                                                                    Even if powerful to summarize the distribution of a numeric variable, the boxplot has flaws.

                                                                    It basically hides the underlying distribution. For instance, a low sample size or a bi-modal distribution are impossible to detect reading the boxes only.

                                                                    Jittering is a good workaround. Add all individual data points with low size, low opacity, and some random shift to the right or to the left (jitter). The underlying distribution becomes instantly available.

                                                                    -5051015202530ABCD

                                                                    Showing individual data points using jittering on top of your boxplot adds trust. Reader now knows you're not hiding anything.

                                                                    The Data

                                                                    The dataset used here is exactly the same as the one used for the simple boxplot.

                                                                    Jittering

                                                                    We want to show each individual data point on top of each box for accuracy. If the dataset is big, this would result in a cluttered figure with a lot of overlap.

                                                                    Jittering is a process that shifts each circle by a random value. It avoids the overlap, and allows to make the circle layer insightful.

                                                                    Here is a suggestion to implement it:

                                                                    const allCircles = groupData.map((value, i) => (
                                                                       <circle
                                                                         key={i}
                                                                         cx={
                                                                    @@ -14,4 +14,4 @@
                                                                     ));

                                                                    Contact

                                                                    👋 Hey, I'm Yan and I'm currently working on this project!

                                                                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                      -
                                                                      \ No newline at end of file +
                                                                      \ No newline at end of file diff --git a/example/circle-packing-with-d3-force.html b/example/circle-packing-with-d3-force.html index d0ab223b..c9c755cd 100644 --- a/example/circle-packing-with-d3-force.html +++ b/example/circle-packing-with-d3-force.html @@ -1,4 +1,4 @@ -Circle Packing with d3-force.

                                                                      Circle Packing with d3-force

                                                                      Dataviz logo representing a CircularPacking chart.

                                                                      This tutorial is a variation around the general introduction to circle packing with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                      Instead of relying on the pack() function of d3.js to compute the best node positions, this example suggests to rely on the d3-force plugin to apply physical forces on each node.

                                                                      A code sandbox is provided for the final result, but explanations target what's different compared to a classic circular packing based on some concepts described in the network diagram section.

                                                                      Useful links

                                                                      Plot and code

                                                                      Here is the final plot we're trying to achieve here, together with its code:🙇‍♂️

                                                                      It is a circular packing chart where all circles represent an item of the dataset.

                                                                      • The circle area is proportional to the value property of the data item.
                                                                      • All circles are close to each other but do not collide. They are also attracted by the y=0 horizontal axis, what aligns them horizontally

                                                                      To understand how this chart works, you need the concepts described in the Network diagram and Circle pack sections.

                                                                      A circle packing chart made using the d3-force plugin, with bubbles being attracted by the y=0 baseline.

                                                                      Using d3-force

                                                                      This example is actually a variation of a network diagram, but with no links between nodes.

                                                                      Some physical forces are applied to each node to compute their position through an iterative simulation:

                                                                      d3.forceSimulation(nodes)
                                                                      +Circle Packing with d3-force.

                                                                      Circle Packing with d3-force

                                                                      Dataviz logo representing a CircularPacking chart.

                                                                      This tutorial is a variation around the general introduction to circle packing with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                      Instead of relying on the pack() function of d3.js to compute the best node positions, this example suggests to rely on the d3-force plugin to apply physical forces on each node.

                                                                      A code sandbox is provided for the final result, but explanations target what's different compared to a classic circular packing based on some concepts described in the network diagram section.

                                                                      Useful links

                                                                      Plot and code

                                                                      Here is the final plot we're trying to achieve here, together with its code:🙇‍♂️

                                                                      It is a circular packing chart where all circles represent an item of the dataset.

                                                                      • The circle area is proportional to the value property of the data item.
                                                                      • All circles are close to each other but do not collide. They are also attracted by the y=0 horizontal axis, what aligns them horizontally

                                                                      To understand how this chart works, you need the concepts described in the Network diagram and Circle pack sections.

                                                                      A circle packing chart made using the d3-force plugin, with bubbles being attracted by the y=0 baseline.

                                                                      Using d3-force

                                                                      This example is actually a variation of a network diagram, but with no links between nodes.

                                                                      Some physical forces are applied to each node to compute their position through an iterative simulation:

                                                                      d3.forceSimulation(nodes)
                                                                         .force(
                                                                           'collide',
                                                                           d3.forceCollide().radius((node) => sizeScale(node.value) + 1)
                                                                      @@ -10,4 +10,4 @@
                                                                         .range([BUBBLE_MIN_SIZE, BUBBLE_MAX_SIZE]);

                                                                      Contact

                                                                      👋 Hey, I'm Yan and I'm currently working on this project!

                                                                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                        -
                                                                        \ No newline at end of file +
                                                                        \ No newline at end of file diff --git a/example/histogram-mirror.html b/example/histogram-mirror.html index 78b4d8e4..a1fa5bf2 100644 --- a/example/histogram-mirror.html +++ b/example/histogram-mirror.html @@ -1,4 +1,4 @@ -How to build a mirror histogram with React and D3.

                                                                        Mirror histogram

                                                                        Dataviz logo representing a Histogram chart.

                                                                        This tutorial is a variation around the general introduction to histogram with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                        This example explains how to compare the distribution of 2 groups using amirror histogram. One group is displayed above the X axis, the other onebelow. It allows a direct comparison without having any overlap.

                                                                        A code sandbox is provided for the final result, but explanations target what's different compared to an usual histogram.

                                                                        Useful links

                                                                        Plot and code

                                                                        If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                        The distributions of 2 groups are displayed on the same figure, 1 group being on top and the other being below the X axis. It allows to compare them efficiently, with no overlap. .

                                                                        02468101202468

                                                                        A mirror histogram made with react and d3.js to compare the distribution of 2 groups in a dataset

                                                                        The Data

                                                                        The dataset used here is slightly different as the one used for the simple 1 group histogram.

                                                                        An array is used, with each object in it providing the name (group property here) and the values of a group. Note that if more than 2 items are available in the array, only the 2 first will be used by the component.

                                                                        Here is a minimal example of the data structure:

                                                                        const data = [
                                                                        +How to build a mirror histogram with React and D3.

                                                                        Mirror histogram

                                                                        Dataviz logo representing a Histogram chart.

                                                                        This tutorial is a variation around the general introduction to histogram with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                        This example explains how to compare the distribution of 2 groups using amirror histogram. One group is displayed above the X axis, the other onebelow. It allows a direct comparison without having any overlap.

                                                                        A code sandbox is provided for the final result, but explanations target what's different compared to an usual histogram.

                                                                        Useful links

                                                                        Plot and code

                                                                        If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                        The distributions of 2 groups are displayed on the same figure, 1 group being on top and the other being below the X axis. It allows to compare them efficiently, with no overlap. .

                                                                        02468101202468

                                                                        A mirror histogram made with react and d3.js to compare the distribution of 2 groups in a dataset

                                                                        The Data

                                                                        The dataset used here is slightly different as the one used for the simple 1 group histogram.

                                                                        An array is used, with each object in it providing the name (group property here) and the values of a group. Note that if more than 2 items are available in the array, only the 2 first will be used by the component.

                                                                        Here is a minimal example of the data structure:

                                                                        const data = [
                                                                           {
                                                                             group: "A",
                                                                             values: [0, 0, 2, 2, 2, 0]
                                                                        @@ -20,4 +20,4 @@
                                                                         const bucketsBottom = bucketGenerator(data[1].values);

                                                                        Contact

                                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                          -
                                                                          \ No newline at end of file +
                                                                          \ No newline at end of file diff --git a/example/histogram-small-multiple.html b/example/histogram-small-multiple.html index 22006066..c7cd9f74 100644 --- a/example/histogram-small-multiple.html +++ b/example/histogram-small-multiple.html @@ -1,4 +1,4 @@ -How to build a small multiple histogram with React and D3 to show the distribution of several groups.

                                                                          Histogram

                                                                          Dataviz logo representing a Histogram chart.

                                                                          This tutorial is a variation around the general introduction to histogram with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                          This example explains how to plot the distribution of several groups, each distribution being drawn on its own pannel. This dataviz technique is called small multiples. It can be useful to compare the distribution of several items in a dataset.

                                                                          A code sandbox is provided for the final result, but explanations target what's different compared to an usual histogram.

                                                                          Useful links

                                                                          Plot and code

                                                                          If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                          The distribution of several groups are displayed, one on each panel of the graphing window. It allows to compare the distributions.

                                                                          Note that this works even if groups have very similar distributions as the bars won't overlap each other. It is thus a very good alternative to the histogram with multiple groups that would get unreadable in this condition.

                                                                          Histogram representing the distribution of 4 groups in a dataset using the small multiple display. Made with react (rendering) and d3.js (scales)

                                                                          The Data

                                                                          The dataset used here is slightly different as the one used for the simple 1 group histogram.

                                                                          An array is used, with each object in it providing the name (group property here) and the values of a group.

                                                                          Here is a minimal example of the data structure:

                                                                          const data = [
                                                                          +How to build a small multiple histogram with React and D3 to show the distribution of several groups.

                                                                          Histogram

                                                                          Dataviz logo representing a Histogram chart.

                                                                          This tutorial is a variation around the general introduction to histogram with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                          This example explains how to plot the distribution of several groups, each distribution being drawn on its own pannel. This dataviz technique is called small multiples. It can be useful to compare the distribution of several items in a dataset.

                                                                          A code sandbox is provided for the final result, but explanations target what's different compared to an usual histogram.

                                                                          Useful links

                                                                          Plot and code

                                                                          If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                          The distribution of several groups are displayed, one on each panel of the graphing window. It allows to compare the distributions.

                                                                          Note that this works even if groups have very similar distributions as the bars won't overlap each other. It is thus a very good alternative to the histogram with multiple groups that would get unreadable in this condition.

                                                                          Histogram representing the distribution of 4 groups in a dataset using the small multiple display. Made with react (rendering) and d3.js (scales)

                                                                          The Data

                                                                          The dataset used here is slightly different as the one used for the simple 1 group histogram.

                                                                          An array is used, with each object in it providing the name (group property here) and the values of a group.

                                                                          Here is a minimal example of the data structure:

                                                                          const data = [
                                                                             {
                                                                               group: "A",
                                                                               values: [0, 0, 2, 2, 2, 0]
                                                                          @@ -51,4 +51,4 @@
                                                                           };

                                                                          Contact

                                                                          👋 Hey, I'm Yan and I'm currently working on this project!

                                                                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                            -
                                                                            \ No newline at end of file +
                                                                            \ No newline at end of file diff --git a/example/histogram-with-several-groups.html b/example/histogram-with-several-groups.html index 844054fa..f06b5f91 100644 --- a/example/histogram-with-several-groups.html +++ b/example/histogram-with-several-groups.html @@ -1,4 +1,4 @@ -How to build a histogram with React and D3.

                                                                            Histogram

                                                                            Dataviz logo representing a Histogram chart.

                                                                            This tutorial is a variation around the general introduction to histogram with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                            This example explains how to plot several groups on the same histogram, by overlapping them on the same X axis. It can be useful to compare the distribution of several items in a dataset.

                                                                            A code sandbox is provided for the final result, but explanations target what's different compared to an usual histogram.

                                                                            Useful links

                                                                            Plot and code

                                                                            If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                            The distribution of several groups are displayed on the same figure, allowing to easily compare them. Please note that this kind of visual works well when there is a clear distinction between groups. Otherwise, bars will overlap each other resulting in an unreadable chart.

                                                                            Histogram representing the distribution of 3 groups in a dataset. Made with react (rendering) and d3.js (scales)

                                                                            The Data

                                                                            The dataset used here is slightly different as the one used for the simple 1 group histogram.

                                                                            An array is used, with each object in it providing the name (group property here) and the values of a group.

                                                                            Here is a minimal example of the data structure:

                                                                            const data = [
                                                                            +How to build a histogram with React and D3.

                                                                            Histogram

                                                                            Dataviz logo representing a Histogram chart.

                                                                            This tutorial is a variation around the general introduction to histogram with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                            This example explains how to plot several groups on the same histogram, by overlapping them on the same X axis. It can be useful to compare the distribution of several items in a dataset.

                                                                            A code sandbox is provided for the final result, but explanations target what's different compared to an usual histogram.

                                                                            Useful links

                                                                            Plot and code

                                                                            If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                            The distribution of several groups are displayed on the same figure, allowing to easily compare them. Please note that this kind of visual works well when there is a clear distinction between groups. Otherwise, bars will overlap each other resulting in an unreadable chart.

                                                                            Histogram representing the distribution of 3 groups in a dataset. Made with react (rendering) and d3.js (scales)

                                                                            The Data

                                                                            The dataset used here is slightly different as the one used for the simple 1 group histogram.

                                                                            An array is used, with each object in it providing the name (group property here) and the values of a group.

                                                                            Here is a minimal example of the data structure:

                                                                            const data = [
                                                                               {
                                                                                 group: "A",
                                                                                 values: [0, 0, 2, 2, 2, 0]
                                                                            @@ -50,4 +50,4 @@
                                                                             );

                                                                            Contact

                                                                            👋 Hey, I'm Yan and I'm currently working on this project!

                                                                            Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                              -
                                                                              \ No newline at end of file +
                                                                              \ No newline at end of file diff --git a/example/line-chart-synchronized-cursors.html b/example/line-chart-synchronized-cursors.html index 5641a40c..2fc0db23 100644 --- a/example/line-chart-synchronized-cursors.html +++ b/example/line-chart-synchronized-cursors.html @@ -1,4 +1,4 @@ -Line charts with synchronized cursors.

                                                                              Line charts

                                                                              Dataviz logo representing a Line chart.

                                                                              This tutorial is a variation around the general introduction to line chart with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                              This example explains how to create several line charts and add asynchronized cursor on all of them. Hovering over one graph will display a cursor on all of them, easing the understanding of synchronized patterns.

                                                                              A code sandbox is provided for the final result, but explanations target what's different compared to an usual line chart.

                                                                              Useful links

                                                                              Plot and code

                                                                              If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                              Two line charts are displayed one next to each other. It shows the evolution of 2 numeric valriables.

                                                                              Hovering over a chart will display a cursor that is synced with the other chart. This helps finding a relationship between them.

                                                                              Hover over a chart to see a cursor on both of them, easing the time comparison.

                                                                              The Data

                                                                              Two dataset are used here. Both with the same format as described in theline chart section of the gallery.

                                                                              Here is a minimal example of the data structure:

                                                                              const data = [
                                                                              +Line charts with synchronized cursors.

                                                                              Line charts

                                                                              Dataviz logo representing a Line chart.

                                                                              This tutorial is a variation around the general introduction to line chart with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                              This example explains how to create several line charts and add asynchronized cursor on all of them. Hovering over one graph will display a cursor on all of them, easing the understanding of synchronized patterns.

                                                                              A code sandbox is provided for the final result, but explanations target what's different compared to an usual line chart.

                                                                              Useful links

                                                                              Plot and code

                                                                              If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                              Two line charts are displayed one next to each other. It shows the evolution of 2 numeric valriables.

                                                                              Hovering over a chart will display a cursor that is synced with the other chart. This helps finding a relationship between them.

                                                                              Hover over a chart to see a cursor on both of them, easing the time comparison.

                                                                              The Data

                                                                              Two dataset are used here. Both with the same format as described in theline chart section of the gallery.

                                                                              Here is a minimal example of the data structure:

                                                                              const data = [
                                                                                 {x:1, y: 90},
                                                                                 {x: 2, y: 12},
                                                                                 {x: 3, , y: 34},
                                                                              @@ -23,4 +23,4 @@
                                                                               };

                                                                              Animated cursor

                                                                              I used react spring to animate the cursor transition. When the mouse moves, the cursor position does not change instantly but moves smoothly to the new position.

                                                                              Animation in dataviz using React is a big topic. It's impossible to go in-depth here! I will publish a dedicated blog post on the topic soon. Please subscribe to the newsletter if you want to be notified.

                                                                              Hover over a chart to see a cursor on both of them, easing the time comparison.

                                                                              Contact

                                                                              👋 Hey, I'm Yan and I'm currently working on this project!

                                                                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                -
                                                                                \ No newline at end of file +
                                                                                \ No newline at end of file diff --git a/example/network-diagram-with-colored-groups.html b/example/network-diagram-with-colored-groups.html index 481428a1..813ed75c 100644 --- a/example/network-diagram-with-colored-groups.html +++ b/example/network-diagram-with-colored-groups.html @@ -1,4 +1,4 @@ -Force-directed Network diagram with React and D3.js.

                                                                                Force-directed Network diagram with React and D3.js

                                                                                Dataviz logo representing a Network chart.

                                                                                This tutorial is a variation around the general introduction to network diagram with react and d3.js. You should probably understand the concepts described there before reading here, notably everything related to the d3-force plugin.

                                                                                This example shows how to apply the concepts of the general tutorial to a real dataset. It creates a force-directed graph that describes the network of character co-occurrence in Les Misérables.

                                                                                A code sandbox is provided for the final result, but explanations target what's different compared to a classic network diagram.

                                                                                Useful links

                                                                                Plot and code

                                                                                If you are in a hurry, here is the final plot we're trying to achieve here, together with its code:🙇‍♂️

                                                                                In this network diagram, each node is a character of the book Les Misérables. The network chart tries to localise characters who often appear together close to each other.

                                                                                The dataset comes from this Observable version that uses d3.js only.

                                                                                Network section

                                                                                A network diagram made with d3.js and react. It shows the character co-occurence in Les Misérables.

                                                                                Color Palette

                                                                                The only difference with the very simple network chart of the mainnetwork tutorial is the presence of a color palette used to color the nodes.

                                                                                Each node of the dataset is attributed to a group. It is thus possible to create a color scale using a scaleOrdinal:

                                                                                // List of Groups
                                                                                +Force-directed Network diagram with React and D3.js.

                                                                                Force-directed Network diagram with React and D3.js

                                                                                Dataviz logo representing a Network chart.

                                                                                This tutorial is a variation around the general introduction to network diagram with react and d3.js. You should probably understand the concepts described there before reading here, notably everything related to the d3-force plugin.

                                                                                This example shows how to apply the concepts of the general tutorial to a real dataset. It creates a force-directed graph that describes the network of character co-occurrence in Les Misérables.

                                                                                A code sandbox is provided for the final result, but explanations target what's different compared to a classic network diagram.

                                                                                Useful links

                                                                                Plot and code

                                                                                If you are in a hurry, here is the final plot we're trying to achieve here, together with its code:🙇‍♂️

                                                                                In this network diagram, each node is a character of the book Les Misérables. The network chart tries to localise characters who often appear together close to each other.

                                                                                The dataset comes from this Observable version that uses d3.js only.

                                                                                Network section

                                                                                A network diagram made with d3.js and react. It shows the character co-occurence in Les Misérables.

                                                                                Color Palette

                                                                                The only difference with the very simple network chart of the mainnetwork tutorial is the presence of a color palette used to color the nodes.

                                                                                Each node of the dataset is attributed to a group. It is thus possible to create a color scale using a scaleOrdinal:

                                                                                // List of Groups
                                                                                 const allGroups = [...new Set(nodes.map((d) => d.group))];
                                                                                 
                                                                                 // Color scale
                                                                                @@ -7,4 +7,4 @@
                                                                                   .range(schemeCategory10);

                                                                                Here I am using the schemeCategory10 color scale to avoid defining those color by hand.

                                                                                Once the color scale is ready, it is straightforward to call it for each node in the drawNetwork() function.

                                                                                Contact

                                                                                👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                  -
                                                                                  \ No newline at end of file +
                                                                                  \ No newline at end of file diff --git a/example/population-pyramid.html b/example/population-pyramid.html index 9ddc2344..c1577281 100644 --- a/example/population-pyramid.html +++ b/example/population-pyramid.html @@ -1 +1 @@ -

                                                                                  A work by Yan Holtz for the React Graph Gallery

                                                                                  Watch the world...

                                                                                  Getting older

                                                                                  Some countries are experiencing an aging population, while others are in the midst of a baby boom. Some face unusual demographic shifts when some others are surprisingly stable. Dive into the intriguing patterns of global population dynamics with this captivating set of lines.


                                                                                  1950
                                                                                  1965
                                                                                  1980
                                                                                  1995
                                                                                  2010
                                                                                  2025
                                                                                  2040
                                                                                  2055
                                                                                  2070
                                                                                  2085
                                                                                  2100

                                                                                  Looks good but

                                                                                  What's this?

                                                                                  These organic shapes look quite appealing. But do they actually mean anything? 🤔

                                                                                  They do!

                                                                                  They're a creative way to represent the evolution of the population pyramid of a country over time.


                                                                                  Let me walk you through it step by step:



                                                                                  How I made this

                                                                                  Material & Method

                                                                                  This project is inspired by the work of Jorge Camoes. His approach resonated with me, especially since I'm not fond of getting older. So I decided it was a great time to dive into some D3.jswork.

                                                                                  If you're curious about how this is made, most of the concepts are explained in my React Graph Gallery, and the code is available on GitHub.

                                                                                  Essentially, it's a substantial amount of React code for rendering, with a bit of D3.js to calculate the shape positions. React Spring is used for all the animations. That's it!

                                                                                  Oh, and the data comes from the United Nations. Thanks to them for providing it!

                                                                                  \ No newline at end of file +

                                                                                  A work by Yan Holtz for the React Graph Gallery

                                                                                  Watch the world...

                                                                                  Getting older

                                                                                  Some countries are experiencing an aging population, while others are in the midst of a baby boom. Some face unusual demographic shifts when some others are surprisingly stable. Dive into the intriguing patterns of global population dynamics with this captivating set of lines.


                                                                                  1950
                                                                                  1965
                                                                                  1980
                                                                                  1995
                                                                                  2010
                                                                                  2025
                                                                                  2040
                                                                                  2055
                                                                                  2070
                                                                                  2085
                                                                                  2100

                                                                                  Looks good but

                                                                                  What's this?

                                                                                  These organic shapes look quite appealing. But do they actually mean anything? 🤔

                                                                                  They do!

                                                                                  They're a creative way to represent the evolution of the population pyramid of a country over time.


                                                                                  Let me walk you through it step by step:



                                                                                  How I made this

                                                                                  Material & Method

                                                                                  This project is inspired by the work of Jorge Camoes. His approach resonated with me, especially since I'm not fond of getting older. So I decided it was a great time to dive into some D3.jswork.

                                                                                  If you're curious about how this is made, most of the concepts are explained in my React Graph Gallery, and the code is available on GitHub.

                                                                                  Essentially, it's a substantial amount of React code for rendering, with a bit of D3.js to calculate the shape positions. React Spring is used for all the animations. That's it!

                                                                                  Oh, and the data comes from the United Nations. Thanks to them for providing it!

                                                                                  \ No newline at end of file diff --git a/example/radar-chart-animation.html b/example/radar-chart-animation.html index d84d3fe6..ce804aac 100644 --- a/example/radar-chart-animation.html +++ b/example/radar-chart-animation.html @@ -1,4 +1,4 @@ -Types of Data Professionals

                                                                                  Types of Data Professionals

                                                                                  Dataviz logo representing a Spider chart.

                                                                                  The field of data offers a diverse array of job titles, making it challenging to navigate without getting lost in the jargon and uncertainty about which roles to pursue.

                                                                                  The charts below offer deeper insights into the competencies needed, salary ranges, and popularity trends for the four primary job titles.

                                                                                  It's a good opportunity to learn how to make a little application with React and D3.js, featuring 3 inter-connected chart types with smooth animated transition: radar chart, line chart and lollipop.

                                                                                  Useful links

                                                                                  The plot

                                                                                  Here is what we want to build. It is highly inspired by a work from Kevin Rosamont Prombo.

                                                                                  Four buttons are provided, one for each type of data professional. Clicking on it will update the 3 following charts.


                                                                                  Types of Data Professionals

                                                                                  The field of data offers a diverse array of job titles, making it challenging to navigate without getting lost in the jargon and uncertainty about which roles to pursue. The charts below offer deeper insights into the competencies needed, salary ranges, and popularity trends for the four primary job titles.

                                                                                  ML OpsData PipelinesDatabaseData VizStorytellingBusiness InsightsReportingExperimentationStatsML ModelingDeployment
                                                                                  00

                                                                                  Dive deep into the 4 main types of Data Professionals. Understand their main required competencies, their salary ranges and their popularity.

                                                                                  Data

                                                                                  The radar chart explains what competencies are required to be a Data Engineer, a Machine Learning Engineer, a Data Scientist or a Data Analyst. The data and the representation have been first suggested by Kevin Rosamont Prombo.

                                                                                  The little lollipop plot provides the estimated salary range for the job. Data from review n prep and glassdoor.

                                                                                  The line chart gives an estimate of the job popularity based on its google trend score in the last ~10 years.

                                                                                  Click the Show code button above to get a sandbox with the 3 datasets at json format.

                                                                                  Global state

                                                                                  The first thing that is required here is a global state.

                                                                                  The root file of the application computes all the available groups in the dataset (allGroups) and use the first group to state the initial state of the application.

                                                                                  const allGroups = data.map((d) => d.name);
                                                                                  +Types of Data Professionals

                                                                                  Types of Data Professionals

                                                                                  Dataviz logo representing a Spider chart.

                                                                                  The field of data offers a diverse array of job titles, making it challenging to navigate without getting lost in the jargon and uncertainty about which roles to pursue.

                                                                                  The charts below offer deeper insights into the competencies needed, salary ranges, and popularity trends for the four primary job titles.

                                                                                  It's a good opportunity to learn how to make a little application with React and D3.js, featuring 3 inter-connected chart types with smooth animated transition: radar chart, line chart and lollipop.

                                                                                  Useful links

                                                                                  The plot

                                                                                  Here is what we want to build. It is highly inspired by a work from Kevin Rosamont Prombo.

                                                                                  Four buttons are provided, one for each type of data professional. Clicking on it will update the 3 following charts.


                                                                                  Types of Data Professionals

                                                                                  The field of data offers a diverse array of job titles, making it challenging to navigate without getting lost in the jargon and uncertainty about which roles to pursue. The charts below offer deeper insights into the competencies needed, salary ranges, and popularity trends for the four primary job titles.

                                                                                  ML OpsData PipelinesDatabaseData VizStorytellingBusiness InsightsReportingExperimentationStatsML ModelingDeployment
                                                                                  00

                                                                                  Dive deep into the 4 main types of Data Professionals. Understand their main required competencies, their salary ranges and their popularity.

                                                                                  Data

                                                                                  The radar chart explains what competencies are required to be a Data Engineer, a Machine Learning Engineer, a Data Scientist or a Data Analyst. The data and the representation have been first suggested by Kevin Rosamont Prombo.

                                                                                  The little lollipop plot provides the estimated salary range for the job. Data from review n prep and glassdoor.

                                                                                  The line chart gives an estimate of the job popularity based on its google trend score in the last ~10 years.

                                                                                  Click the Show code button above to get a sandbox with the 3 datasets at json format.

                                                                                  Global state

                                                                                  The first thing that is required here is a global state.

                                                                                  The root file of the application computes all the available groups in the dataset (allGroups) and use the first group to state the initial state of the application.

                                                                                  const allGroups = data.map((d) => d.name);
                                                                                   const [selectedGroup, setSelectedGroup] = useState(allGroups[0]);

                                                                                  When the user clicks a button, the state is updated thanks to the setSelectedGroup() function. The newly selected group (selectedGroup) is then passed to the graphing component as a prop.

                                                                                  Charts

                                                                                  Then we need to build 3 charts based on the 3 filtered dataset.

                                                                                  The React graph gallery already provides in-depth tutorials for those 3 chart types. So please refer to the radar chart, line chart and lollipop sections to learn how to build them.


                                                                                  Animation

                                                                                  Most of the fun here comes from the smooth, animated transition between groups. It is also the trickiest part to implement.

                                                                                  As always in this gallery, the animation is computed thanks to react-spring, a javascript library for spring animation in React.

                                                                                  It would be way too long to explain how to implement it properly in this page. But to put it in a nutshell, you need to render animated elements instead of usual SVG elements. Here is how the line is rendered for instance:

                                                                                  const LineItem = ({ path, color }: LineItemProps) => {
                                                                                     const springProps = useSpring({
                                                                                       to: {
                                                                                  @@ -21,4 +21,4 @@
                                                                                   };

                                                                                  I plan to write some complete tutorials on this passionating and complicated topic. You can subscribe to the project to know when it's ready!

                                                                                  Subscribe

                                                                                  Contact

                                                                                  👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                  Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                    -
                                                                                    \ No newline at end of file +
                                                                                    \ No newline at end of file diff --git a/example/scatterplot-basic-canvas.html b/example/scatterplot-basic-canvas.html index 77e4467f..b7529c88 100644 --- a/example/scatterplot-basic-canvas.html +++ b/example/scatterplot-basic-canvas.html @@ -1,4 +1,4 @@ -Scatterplot with Canvas

                                                                                    Scatterplot with Canvas

                                                                                    Dataviz logo representing a ScatterPlot chart.

                                                                                    This tutorial is a variation around the general introduction to scatterplot with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                                    Rendering a scatterplot using SVG can arm the performance of your webpage if the number of data points is high. A common workaround is to draw the circles in canvas instead.

                                                                                    This post explains how to combine SVG for the axes and canvas for the scatterplot markers in React.

                                                                                    Useful links

                                                                                    Why using canvas? 🤔

                                                                                    A scatterplot is a chart type that is commonly used to display a high amount of data points.

                                                                                    When you draw it in SVG, it means adding a bunch of circle elements. As a result, your DOM will quickly become really heavy. It can result in poor performances. If you want to add some animation on top of it, you are pretty sure to freeze the page.

                                                                                    When using canvas, you add only 1 node in your DOM, and benefit the very high speed of it. It is game changer for any viz type that requires good performances.

                                                                                    Scatterplot canvas implementation

                                                                                    The trick here is to use 2 layers of drawing:

                                                                                    • The first layer is for the axes. It is an SVG element that will add the X and Y axes using some usual AxisLeft and AxisBottom components.
                                                                                    • The second layer is for the markers, it is the canvas element. It has a ref. We can then call a function in a useEffect hook to draw inside this canvas element.

                                                                                    This is how the useEffect hook looks like, drawing our circles:

                                                                                    useEffect(() => {
                                                                                    +Scatterplot with Canvas

                                                                                    Scatterplot with Canvas

                                                                                    Dataviz logo representing a ScatterPlot chart.

                                                                                    This tutorial is a variation around the general introduction to scatterplot with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                                    Rendering a scatterplot using SVG can arm the performance of your webpage if the number of data points is high. A common workaround is to draw the circles in canvas instead.

                                                                                    This post explains how to combine SVG for the axes and canvas for the scatterplot markers in React.

                                                                                    Useful links

                                                                                    Why using canvas? 🤔

                                                                                    A scatterplot is a chart type that is commonly used to display a high amount of data points.

                                                                                    When you draw it in SVG, it means adding a bunch of circle elements. As a result, your DOM will quickly become really heavy. It can result in poor performances. If you want to add some animation on top of it, you are pretty sure to freeze the page.

                                                                                    When using canvas, you add only 1 node in your DOM, and benefit the very high speed of it. It is game changer for any viz type that requires good performances.

                                                                                    Scatterplot canvas implementation

                                                                                    The trick here is to use 2 layers of drawing:

                                                                                    • The first layer is for the axes. It is an SVG element that will add the X and Y axes using some usual AxisLeft and AxisBottom components.
                                                                                    • The second layer is for the markers, it is the canvas element. It has a ref. We can then call a function in a useEffect hook to draw inside this canvas element.

                                                                                    This is how the useEffect hook looks like, drawing our circles:

                                                                                    useEffect(() => {
                                                                                       const canvas = canvasRef.current;
                                                                                     
                                                                                       if (!canvas) {
                                                                                    @@ -20,4 +20,4 @@
                                                                                     }, [data, xScale, yScale, width, height]);

                                                                                    Here is a complete implementation of the scatterplot using this technique with 10000 data points:

                                                                                    0246810121416

                                                                                    A scatterplot made with React, using SVG for the axes and Canvas for the markers to improve performance.



                                                                                    Canvas is an important topic in data visualization for the web. I plan to write complete articles on the topic. You can know when it's ready by subscribing to the project.

                                                                                    Tell me when the canvas post is ready!

                                                                                    Contact

                                                                                    👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                      -
                                                                                      \ No newline at end of file +
                                                                                      \ No newline at end of file diff --git a/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection.html b/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection.html index 848c1a7e..b1590c93 100644 --- a/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection.html +++ b/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection.html @@ -1,8 +1,8 @@ -Scatterplot tooltip with React and D3: use Voronoi to detect closest point.

                                                                                      Scatterplot tooltip: use Voronoi for closest point detection

                                                                                      Dataviz logo representing a ScatterPlot chart.

                                                                                      This tutorial is a variation around the general introduction to scatterplot with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                                      This example explains how to use an invisible Voronoi diagram in the background to detect the mouse closest point of the scatterplot.

                                                                                      A code sandbox is provided for the final result, but explanations target what's different compared to an usual scatter plot.

                                                                                      Useful links

                                                                                      Plot and code

                                                                                      If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                                      This is a scatterplot with voronoi detection. When you enter the chart area with your mouse, the closest point is found using a Delaunay triangulation. The corresponding circle is highlighted on the chart.

                                                                                      Same concept could easily be used to add a tooltip with great performance.

                                                                                      A scatterplot with tooltip. The closest point is detected using Voronoi to trigger the tooltip apparition.

                                                                                      The Data

                                                                                      The dataset used here is the same as for an usual scatterplot.

                                                                                      It is an array of objects where each object is a data point. The object can have many properties, but at least a x and a y prop are needed to provide the 2d coordinates.

                                                                                      Here is a minimal example of the data structure:

                                                                                      const data = [
                                                                                      +Scatterplot tooltip with React and D3: use Voronoi to detect closest point.

                                                                                      Scatterplot tooltip: use Voronoi for closest point detection

                                                                                      Dataviz logo representing a ScatterPlot chart.

                                                                                      This tutorial is a variation around the general introduction to scatterplot with react and d3.js. You should probably understand the concepts described there before reading here.

                                                                                      This example explains how to use an invisible Voronoi diagram in the background to detect the mouse closest point of the scatterplot.

                                                                                      A code sandbox is provided for the final result, but explanations target what's different compared to an usual scatter plot.

                                                                                      Useful links

                                                                                      Plot and code

                                                                                      If you are in a hurry, this is what we're trying to achieve here.🙇‍♂️

                                                                                      This is a scatterplot with voronoi detection. When you enter the chart area with your mouse, the closest point is found using a Delaunay triangulation. The corresponding circle is highlighted on the chart.

                                                                                      Same concept could easily be used to add a tooltip with great performance.

                                                                                      A scatterplot with tooltip. The closest point is detected using Voronoi to trigger the tooltip apparition.

                                                                                      The Data

                                                                                      The dataset used here is the same as for an usual scatterplot.

                                                                                      It is an array of objects where each object is a data point. The object can have many properties, but at least a x and a y prop are needed to provide the 2d coordinates.

                                                                                      Here is a minimal example of the data structure:

                                                                                      const data = [
                                                                                         { x: 10, y: 10 },
                                                                                         { x: 4, y: 4 },
                                                                                         ...
                                                                                       ];

                                                                                      Building the Voronoi diagram

                                                                                      The shapes drawn in the background are called a Voronoi diagram.

                                                                                      A voronoi diagram is a is a partition of a plane into regions called voronoi cells. A voronoi cell consists of every point in the plane whose distance to its linked data point is less than or equal to its distance to any other data point.

                                                                                      This is very handy to detect the mouse closest point on a scatterplot! 🔥

                                                                                      The react graph gallery has a dedicated section on the topic. Once you understood how Voronoi works with d3, it is just a matter of adding axes to get a scatterplot with point detection.

                                                                                      Voronoi section

                                                                                      Contact

                                                                                      👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                        -
                                                                                        \ No newline at end of file +
                                                                                        \ No newline at end of file diff --git a/example/timeseries-moving-average.html b/example/timeseries-moving-average.html index 5cb44726..69eb498d 100644 --- a/example/timeseries-moving-average.html +++ b/example/timeseries-moving-average.html @@ -1,4 +1,4 @@ -Timeseries with moving average

                                                                                        Timeseries with moving average

                                                                                        Dataviz logo representing a Time chart.

                                                                                        In this tutorial, we'll explore the art of plotting time series data, incorporating a dynamic moving average line chart overlaid on the primary plot.

                                                                                        Inspired by a visualization featured in the renowned French newspaper Le Monde, depicting the blooming patterns of cherry trees over time, we'll recreate this compelling chart.

                                                                                        With readily available code and straightforward explanations, you'll witness the prowess of React in seamlessly stacking multiple layers of rendering – from scatterplots to line charts and annotations.

                                                                                        Useful links

                                                                                        🇯🇵 Poetry in Data

                                                                                        Amidst the myriad visualizations of global warming, one stands out for its poetic resonance – an unexpected gem found within the pages of a French newspaper: the flourishing timelines of cherry trees in Japan.

                                                                                        Intriguingly, Yasuyuki Aono delved into ancient texts dating back to the 800s to unearth this data. Thanks to the meticulous efforts of Our World in Data in cleaning and refining the dataset, we're now presented with a captivating portrayal of our changing world.


                                                                                        Here is the chart we're learning to build today:

                                                                                        Plein floraison annuelleMoyenne de la floraison (20 ans)
                                                                                        1950 - 202316 Mars21 Mars26 Mars31 Mars5 Avril10 Avril15 Avril20 Avril25 Avril30 Avril5 Mai90010001100120013001400150016001700180019002000

                                                                                        Prerequisite

                                                                                        This graph combines elements of both a scatterplot and a line chart, making it essential to grasp the fundamentals of each chart type before diving in.

                                                                                        Good news, the react graph gallery has some very basic examples to illustrate those concepts!

                                                                                        Most basic scatterplot made with react and d3

                                                                                        Basic scatter plot

                                                                                        Add circles to get a basic scatter plot

                                                                                        Picture of a very simple line chart made with react and d3

                                                                                        Most basic line chart

                                                                                        The most basic line chart one can make using d3 and react

                                                                                        Annotation

                                                                                        The deepest layer of this chart is the annotation that says 1950 - 2023. It uses stripes in the background. Stripes can be build in SVG as follow:

                                                                                        <defs>
                                                                                        +Timeseries with moving average

                                                                                        Timeseries with moving average

                                                                                        Dataviz logo representing a Time chart.

                                                                                        In this tutorial, we'll explore the art of plotting time series data, incorporating a dynamic moving average line chart overlaid on the primary plot.

                                                                                        Inspired by a visualization featured in the renowned French newspaper Le Monde, depicting the blooming patterns of cherry trees over time, we'll recreate this compelling chart.

                                                                                        With readily available code and straightforward explanations, you'll witness the prowess of React in seamlessly stacking multiple layers of rendering – from scatterplots to line charts and annotations.

                                                                                        Useful links

                                                                                        🇯🇵 Poetry in Data

                                                                                        Amidst the myriad visualizations of global warming, one stands out for its poetic resonance – an unexpected gem found within the pages of a French newspaper: the flourishing timelines of cherry trees in Japan.

                                                                                        Intriguingly, Yasuyuki Aono delved into ancient texts dating back to the 800s to unearth this data. Thanks to the meticulous efforts of Our World in Data in cleaning and refining the dataset, we're now presented with a captivating portrayal of our changing world.


                                                                                        Here is the chart we're learning to build today:

                                                                                        Plein floraison annuelleMoyenne de la floraison (20 ans)
                                                                                        1950 - 202316 Mars21 Mars26 Mars31 Mars5 Avril10 Avril15 Avril20 Avril25 Avril30 Avril5 Mai90010001100120013001400150016001700180019002000

                                                                                        Prerequisite

                                                                                        This graph combines elements of both a scatterplot and a line chart, making it essential to grasp the fundamentals of each chart type before diving in.

                                                                                        Good news, the react graph gallery has some very basic examples to illustrate those concepts!

                                                                                        Most basic scatterplot made with react and d3

                                                                                        Basic scatter plot

                                                                                        Add circles to get a basic scatter plot

                                                                                        Picture of a very simple line chart made with react and d3

                                                                                        Most basic line chart

                                                                                        The most basic line chart one can make using d3 and react

                                                                                        Annotation

                                                                                        The deepest layer of this chart is the annotation that says 1950 - 2023. It uses stripes in the background. Stripes can be build in SVG as follow:

                                                                                        <defs>
                                                                                           <pattern
                                                                                             id="pattern_annotation"
                                                                                             patternUnits="userSpaceOnUse"
                                                                                        @@ -46,4 +46,4 @@
                                                                                         );

                                                                                        Full code

                                                                                        Let's wrap this up!

                                                                                        The full code for this chart is available below. Click the Show Code button.

                                                                                        Plein floraison annuelleMoyenne de la floraison (20 ans)
                                                                                        1950 - 202316 Mars21 Mars26 Mars31 Mars5 Avril10 Avril15 Avril20 Avril25 Avril30 Avril5 Mai

                                                                                        Reproduction of a chart published in the newspaper Le Monde.

                                                                                        Going further

                                                                                        This graph looks pretty good. A few potential improvements:

                                                                                        • Add a tooltip to give more information about each data point
                                                                                        • Use Voronoi for closest point detection to trigger the hover effect

                                                                                        Contact

                                                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                          -
                                                                                          \ No newline at end of file +
                                                                                          \ No newline at end of file diff --git a/fix-canvas-blurry-dataviz.html b/fix-canvas-blurry-dataviz.html index 9444949f..063a7c24 100644 --- a/fix-canvas-blurry-dataviz.html +++ b/fix-canvas-blurry-dataviz.html @@ -1,7 +1,7 @@ -Fixing the blurry canvas on retina screens

                                                                                          Fixing the blurry canvas on retina screens


                                                                                          Drawing a chart on a canvas element instead of using svg elements can be a huge performance boost. However, it leads to a blurry and unreadable viz on retina screens if the resolution is not taken into account. Here is how to fix.

                                                                                          ⬜ Pixel, Resolution and DPI

                                                                                          To understand why a canvas can get blurry on a retina screen, you first need to have some basic knowledge about how an image is displayed on a screen.

                                                                                          Screens are made up of thousands of tiny dots all bunched together called pixels. Each pixel has the ability to change its color. The total number of pixels on a screen differs from one monitor to another, we call it the screen resolution. If the screen has 1,024 pixels horizontally, and 768 vertically it has a 'resolution' of 1,024 x 768.

                                                                                          A screen is a set of pixels

                                                                                          When you watch dataviz-inspiration.com on your screen, you actually watch thousands of pixels.

                                                                                          It's important to understand that 2 screens with the same physical size (let's say 30 inches) can have very different amount of pixels. The density of pixels on a screen is called DPI for dots per inch or ppi for pixels per inch.

                                                                                          Retina screens have a very high DPI, and it is where our troubbles begin

                                                                                          Physical vs CSS resolution

                                                                                          Let's say that you create a html element and give it a width of 100px using css. This is the css width. If you use a screen that has a very high resolution, pixels are very very small. As a result, your element of 100px would appear very small too on the screen.

                                                                                          To avoid this, each monitor applies a pixel ratio. On a retina screen this ratio equals 2. When you ask the monitor to draw an element of 100px, it will actually draw it with a length of 200px. This is the physical width.

                                                                                          In javascript, you can access this ratio with window.devicePixelRatio and here is the complete doc about it.

                                                                                          🐛 Canvas, High-DPI and the bug

                                                                                          Let's add a canvas element in our DOM, with a width of 100px. It is the equivalent of building an image, 100px wide, that we insert in the DOM.

                                                                                          If we display the result on a retina screen with a devicePixelRatio of 2, the image will be scaled up to 200px wide. The browser will interpolate pixels to make the image bigger, and it results in a blurry output.

                                                                                          To avoid this issue, we the canvas we're creating must be twice bigger on retina screen

                                                                                          A pixelated output when an image is scaled up

                                                                                          A small img or canvas on a retina screen will be scaled up, resulting in a pixelated / blurry output.

                                                                                          🤦‍♂️ The 2 dimensions of the canvas element

                                                                                          There are 2 different ways to control the dimension of a canvas element.

                                                                                          • width and height attributes: They control the size of the image that is created and inserted in the DOM.
                                                                                            Default to 300px and 150px so always specify them.
                                                                                          • css style: the canvas element can be styled using CSS. As a result we can also pass a width and a height here. It controls the size of the element on the screen.

                                                                                          Here is a html code snippet illustrating this concept:

                                                                                          <canvas style="width:200px; height:200px;" width="100px" height="100px">

                                                                                          Now, let's play with those 2 values to see what happens. In the examples below, a segment going from 0,0 (top left) to 100,100 is drawn.

                                                                                          → Small image, big output

                                                                                          If I create a small image with my canvas (100x100) and output it in big (300x300), the browser has to scale it up to display it, resulting in a blurry output

                                                                                          <canvas style="width:300px; height:300px;" width="100px" height="100px">

                                                                                          This is exactly what happens when you display a canvas on a retina screen 🙀.

                                                                                          → Big image, small output

                                                                                          Now I create a big image with my canvas (200x200) and output it in small (100x100), the browser has to scale it down to display it, → crispy output!

                                                                                          <canvas style="width:100px; height:100px;" width="200px" height="200px">

                                                                                          Much better. But my diagonal is now wrong since it goes to 100,100, which is half way to 200,200. Fortunately javascript is here to the rescue. I will just have to use the scale function to automatically correct those coordinates.

                                                                                          🔨 Fixing the Canvas and Retina screens issue

                                                                                          To finally fix the retina bug, we need to:

                                                                                          • Control the size of the canvas output using the css dimension
                                                                                          • Find the device pixel ratio using window.devicePixelRatio
                                                                                          • Create a bigger canvas image if the pixel ratio is over 1. This is done thanks to the width and height attributes.
                                                                                          • Use the scale() function in our canvas context to correct our coordinates

                                                                                          Here are 2 examples. The first one does not apply the correction (left). The second does the correction (right)

                                                                                          On retina screens, the left shape is blurry when the right one is not.

                                                                                          To see the full code of those 2 examples, click the buttons below.




                                                                                          Contact

                                                                                          👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                          +Fixing the blurry canvas on retina screens

                                                                                          Fixing the blurry canvas on retina screens


                                                                                          Drawing a chart on a canvas element instead of using svg elements can be a huge performance boost. However, it leads to a blurry and unreadable viz on retina screens if the resolution is not taken into account. Here is how to fix.

                                                                                          ⬜ Pixel, Resolution and DPI

                                                                                          To understand why a canvas can get blurry on a retina screen, you first need to have some basic knowledge about how an image is displayed on a screen.

                                                                                          Screens are made up of thousands of tiny dots all bunched together called pixels. Each pixel has the ability to change its color. The total number of pixels on a screen differs from one monitor to another, we call it the screen resolution. If the screen has 1,024 pixels horizontally, and 768 vertically it has a 'resolution' of 1,024 x 768.

                                                                                          A screen is a set of pixels

                                                                                          When you watch dataviz-inspiration.com on your screen, you actually watch thousands of pixels.

                                                                                          It's important to understand that 2 screens with the same physical size (let's say 30 inches) can have very different amount of pixels. The density of pixels on a screen is called DPI for dots per inch or ppi for pixels per inch.

                                                                                          Retina screens have a very high DPI, and it is where our troubbles begin

                                                                                          Physical vs CSS resolution

                                                                                          Let's say that you create a html element and give it a width of 100px using css. This is the css width. If you use a screen that has a very high resolution, pixels are very very small. As a result, your element of 100px would appear very small too on the screen.

                                                                                          To avoid this, each monitor applies a pixel ratio. On a retina screen this ratio equals 2. When you ask the monitor to draw an element of 100px, it will actually draw it with a length of 200px. This is the physical width.

                                                                                          In javascript, you can access this ratio with window.devicePixelRatio and here is the complete doc about it.

                                                                                          🐛 Canvas, High-DPI and the bug

                                                                                          Let's add a canvas element in our DOM, with a width of 100px. It is the equivalent of building an image, 100px wide, that we insert in the DOM.

                                                                                          If we display the result on a retina screen with a devicePixelRatio of 2, the image will be scaled up to 200px wide. The browser will interpolate pixels to make the image bigger, and it results in a blurry output.

                                                                                          To avoid this issue, we the canvas we're creating must be twice bigger on retina screen

                                                                                          A pixelated output when an image is scaled up

                                                                                          A small img or canvas on a retina screen will be scaled up, resulting in a pixelated / blurry output.

                                                                                          🤦‍♂️ The 2 dimensions of the canvas element

                                                                                          There are 2 different ways to control the dimension of a canvas element.

                                                                                          • width and height attributes: They control the size of the image that is created and inserted in the DOM.
                                                                                            Default to 300px and 150px so always specify them.
                                                                                          • css style: the canvas element can be styled using CSS. As a result we can also pass a width and a height here. It controls the size of the element on the screen.

                                                                                          Here is a html code snippet illustrating this concept:

                                                                                          <canvas style="width:200px; height:200px;" width="100px" height="100px">

                                                                                          Now, let's play with those 2 values to see what happens. In the examples below, a segment going from 0,0 (top left) to 100,100 is drawn.

                                                                                          → Small image, big output

                                                                                          If I create a small image with my canvas (100x100) and output it in big (300x300), the browser has to scale it up to display it, resulting in a blurry output

                                                                                          <canvas style="width:300px; height:300px;" width="100px" height="100px">

                                                                                          This is exactly what happens when you display a canvas on a retina screen 🙀.

                                                                                          → Big image, small output

                                                                                          Now I create a big image with my canvas (200x200) and output it in small (100x100), the browser has to scale it down to display it, → crispy output!

                                                                                          <canvas style="width:100px; height:100px;" width="200px" height="200px">

                                                                                          Much better. But my diagonal is now wrong since it goes to 100,100, which is half way to 200,200. Fortunately javascript is here to the rescue. I will just have to use the scale function to automatically correct those coordinates.

                                                                                          🔨 Fixing the Canvas and Retina screens issue

                                                                                          To finally fix the retina bug, we need to:

                                                                                          • Control the size of the canvas output using the css dimension
                                                                                          • Find the device pixel ratio using window.devicePixelRatio
                                                                                          • Create a bigger canvas image if the pixel ratio is over 1. This is done thanks to the width and height attributes.
                                                                                          • Use the scale() function in our canvas context to correct our coordinates

                                                                                          Here are 2 examples. The first one does not apply the correction (left). The second does the correction (right)

                                                                                          On retina screens, the left shape is blurry when the right one is not.

                                                                                          To see the full code of those 2 examples, click the buttons below.




                                                                                          Contact

                                                                                          👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                            Contact

                                                                                            👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                            Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                              -
                                                                                              \ No newline at end of file +
                                                                                              \ No newline at end of file diff --git a/heatmap.html b/heatmap.html index 2145135d..8fb6a137 100644 --- a/heatmap.html +++ b/heatmap.html @@ -1,4 +1,4 @@ -How to build a heatmap with React and D3.

                                                                                              Heatmap

                                                                                              Dataviz logo representing a Heatmap chart.

                                                                                              A heat map (or heatmap) is a chart type that shows the magnitude of a numeric variable as a color in two dimensions. This page is a step-by-step guide on how to build your own heatmap for the web, using React and D3.js.

                                                                                              It starts by describing how the data should be organized and potentially normalized. It then shows how to initialize the heatmap component, build band scales and add rectangles to get a first heatmap. Last but not least, responsiveness and the tooltip are described in depth and a real dataset is used to get a heatmap application. 🙇‍♂️.

                                                                                              Useful links

                                                                                              The Data

                                                                                              The dataset is usually an array where each item provides information for a cell of the heatmap.

                                                                                              Each item is an object that requires at least a value property that is a number. This number will be used to color the cell.

                                                                                              Each item also requires an x and a y property, providing the position of the cell in the 2-d space. Note that those values are strings since anything can be used. We are dealing with ordinal scales here.

                                                                                              Note that you can add any kind of information to those cell objects. Such information can be included in tooltips later on.


                                                                                              Here is a minimal example of the data structure:

                                                                                              const data = [
                                                                                              +How to build a heatmap with React and D3.

                                                                                              Heatmap

                                                                                              Dataviz logo representing a Heatmap chart.

                                                                                              A heat map (or heatmap) is a chart type that shows the magnitude of a numeric variable as a color in two dimensions. This page is a step-by-step guide on how to build your own heatmap for the web, using React and D3.js.

                                                                                              It starts by describing how the data should be organized and potentially normalized. It then shows how to initialize the heatmap component, build band scales and add rectangles to get a first heatmap. Last but not least, responsiveness and the tooltip are described in depth and a real dataset is used to get a heatmap application. 🙇‍♂️.

                                                                                              Useful links

                                                                                              The Data

                                                                                              The dataset is usually an array where each item provides information for a cell of the heatmap.

                                                                                              Each item is an object that requires at least a value property that is a number. This number will be used to color the cell.

                                                                                              Each item also requires an x and a y property, providing the position of the cell in the 2-d space. Note that those values are strings since anything can be used. We are dealing with ordinal scales here.

                                                                                              Note that you can add any kind of information to those cell objects. Such information can be included in tooltips later on.


                                                                                              Here is a minimal example of the data structure:

                                                                                              const data = [
                                                                                                 { x: 'A', y: 'A', value: 12 },
                                                                                                 { x: 'B', y: 'A', value: 2 },
                                                                                                 { x: 'C', y: 'A', value: 9 }
                                                                                              @@ -52,7 +52,7 @@
                                                                                                     fill={colorScale(d.value)}
                                                                                                   />
                                                                                                 );
                                                                                              -});

                                                                                              Note that for the X and Y axis labels, just adding a set of svg text element does a pretty good job, so no need to build complicated axis components as for a scatterplot.


                                                                                              ABCDEFGHIJABCDE

                                                                                              Most basic heatmap made with react and d3.js. d3 is used to compute scales, react for the rendering.

                                                                                              That's it, we have a first good looking heatmap!

                                                                                              The process used to build it with react is pretty close from building it with d3.js only. (Check the pure d3 implementation here).

                                                                                              Responsive Heatmap with react

                                                                                              The component above is not responsive. It expects 2 props called width and height and will render a Heatmap of those dimensions.

                                                                                              Making the Heatmap responsive requires adding a wrapper component that gets the dimension of the parent div, and listening to a potential dimension change. This is possible thanks to a hook called useDimensions that will do the job for us.

                                                                                              useDimensions: a hook to make your viz responsive
                                                                                              export const useDimensions = (targetRef: React.RefObject<HTMLDivElement>) => {
                                                                                              +});

                                                                                              Note that for the X and Y axis labels, just adding a set of svg text element does a pretty good job, so no need to build complicated axis components as for a scatterplot.


                                                                                              ABCDEFGHIJABCDE

                                                                                              Most basic heatmap made with react and d3.js. d3 is used to compute scales, react for the rendering.

                                                                                              That's it, we have a first good looking heatmap!

                                                                                              The process used to build it with react is pretty close from building it with d3.js only. (Check the pure d3 implementation here).

                                                                                              Responsive Heatmap with react

                                                                                              The component above is not responsive. It expects 2 props called width and height and will render a Heatmap of those dimensions.

                                                                                              Making the Heatmap responsive requires adding a wrapper component that gets the dimension of the parent div, and listening to a potential dimension change. This is possible thanks to a hook called useDimensions that will do the job for us.

                                                                                              useDimensions: a hook to make your viz responsive
                                                                                              export const useDimensions = (targetRef: React.RefObject<HTMLDivElement>) => {
                                                                                               
                                                                                                 const getDimensions = () => {
                                                                                                   return {
                                                                                              @@ -80,7 +80,7 @@
                                                                                               }

                                                                                              I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                              Tooltip

                                                                                              Adding a tooltip is an important improvement for a heatmap. It allows us to get as much detail as needed for each cell.

                                                                                              There are many different approaches to building tooltips, and I'm preparing a whole dedicated blog post on the topic.

                                                                                              In the example below I suggest using the same strategy as for scatterplots. So you probably want to read it there for an in-depth explanation.

                                                                                              → Two layers: renderer and tooltip

                                                                                              The first task is to split the Heatmap component into 2 layers. The first layer called Renderer will render the cells as seen previously. The second is an absolute div put on top of the first one, used only to show the tooltip div.

                                                                                              This way, the x and y coordinates of cells in the first layer match with the coordinate of the second layer.

                                                                                              <div style={{ position: "relative" }}>
                                                                                                 <Renderer ..someProps />
                                                                                                 <Tooltip ..someProps />
                                                                                              -</div>

                                                                                              → A common state

                                                                                              On top of the 2 layers, we need a state that stores information about the cell being hovered over. You can create it with a useState statement. I usually call it interactionData in this website.

                                                                                              This state is passed to the Tooltip layer. The function to update it (the "setter") is passed to the Renderer layer. When the user hovers over a cell, this setter is triggered to update the state and thus the tooltip.

                                                                                              const [hoveredCell, setHoveredCell] = useState<InteractionData | null>(null);

                                                                                              → Hover, update state, render tooltips

                                                                                              The heatmap cells listen to onMouseEnter events and update the tooltip state (hoveredCell) with accurate coordinates when it happens.

                                                                                              This state is passed to the Tooltip component. It renders a div at the right position thanks to the information. A bit of smart css is used to make it pretty and include a little arrow.

                                                                                              ABCDEFGHIJABCDE

                                                                                              This heatmap has a tooltip. Hover over a cell to get its exact value.

                                                                                              There is much more to say about tooltips but hopefully that should get you started. Subscribe to the gallery, I'll post more on this topic soon.

                                                                                              Heatmap inspiration

                                                                                              If you're looking for inspiration to create your next Heatmap, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                              dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Heatmap looks good!

                                                                                              visit

                                                                                              Color legend

                                                                                              A heatmap uses a color scale to encode a numeric value into a color. As a result, it is very much advised to add a color legend to explicit how this color scale works.

                                                                                              Let's consider a variable that goes from 0 to 100. We want to encode 0 in blue and 100 in purple. The color scale is built thanks to the scaleLinear() function of d3 as described above.

                                                                                              → A common state

                                                                                              On top of the 2 layers, we need a state that stores information about the cell being hovered over. You can create it with a useState statement. I usually call it interactionData in this website.

                                                                                              This state is passed to the Tooltip layer. The function to update it (the "setter") is passed to the Renderer layer. When the user hovers over a cell, this setter is triggered to update the state and thus the tooltip.

                                                                                              const [hoveredCell, setHoveredCell] = useState<InteractionData | null>(null);

                                                                                              → Hover, update state, render tooltips

                                                                                              The heatmap cells listen to onMouseEnter events and update the tooltip state (hoveredCell) with accurate coordinates when it happens.

                                                                                              This state is passed to the Tooltip component. It renders a div at the right position thanks to the information. A bit of smart css is used to make it pretty and include a little arrow.

                                                                                              ABCDEFGHIJABCDE

                                                                                              This heatmap has a tooltip. Hover over a cell to get its exact value.

                                                                                              There is much more to say about tooltips but hopefully that should get you started. Subscribe to the gallery, I'll post more on this topic soon.

                                                                                              Heatmap inspiration

                                                                                              If you're looking for inspiration to create your next Heatmap, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                              dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Heatmap looks good!

                                                                                              visit

                                                                                              Color legend

                                                                                              A heatmap uses a color scale to encode a numeric value into a color. As a result, it is very much advised to add a color legend to explicit how this color scale works.

                                                                                              Let's consider a variable that goes from 0 to 100. We want to encode 0 in blue and 100 in purple. The color scale is built thanks to the scaleLinear() function of d3 as described above.

                                                                                              020406080100

                                                                                              A color legend built with react, canvas and d3.

                                                                                              The trick here is to create a canvas element of the desired width and height. Then, loop from left to right and add one rectangle for each pixel with the corresponding color using the same color scale as the one used on the chart. It's important to do it in canvas: you don't want to add 300 elements in your DOM if your legend is 300px wide.

                                                                                              Once the canvas element is instantiated with a ref, you can draw the color scale thanks to a useEffect like this:

                                                                                              useEffect(() => {
                                                                                                 const canvas = canvasRef.current;
                                                                                                 const context = canvas?.getContext("2d");
                                                                                              @@ -98,4 +98,4 @@
                                                                                                           0px">0k1k2k

                                                                                              Number of Measles infected people over 70-some years and across all 50 states. Can you guess when a vaccine was introduced?

                                                                                              Contact

                                                                                              👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                -
                                                                                                \ No newline at end of file +
                                                                                                \ No newline at end of file diff --git a/hexbin-map.html b/hexbin-map.html index 260db1cc..9091538a 100644 --- a/hexbin-map.html +++ b/hexbin-map.html @@ -1,4 +1,4 @@ -How to build a hexbin map component with React and D3.

                                                                                                Hexbin Map

                                                                                                Dataviz logo representing a MapHexbin chart.

                                                                                                A hexbin map is a visual representation of data that aggregates individual data points into hexagonal bins or cells, typically used for spatial analysis. It helps to condense large datasets and identify patterns or trends within specific geographic regions.

                                                                                                Two types of hexbin map exist. The first one is based on a geoJsonfile that provides the hexagon boundaries. It is similar to a choropleth map, with hexagons instead of real regions. The second is actually a 2d density chart, but with GPS locations for the x and y coordinates.

                                                                                                This page is a long form tutorial explaining how to build hexbin maps using react and d3.js. It provides interactive examples for both types of hexbin maps with code explanation and should get you started for your web app.

                                                                                                Useful links

                                                                                                Hexbin map from a geoJson file

                                                                                                Drawing a map using react and d3.js usually relies on a geoJson file. This file format provides information for geographical regions. It stores the 2d coordinates of shapes.

                                                                                                This is the way it looks:

                                                                                                {
                                                                                                +How to build a hexbin map component with React and D3.

                                                                                                Hexbin Map

                                                                                                Dataviz logo representing a MapHexbin chart.

                                                                                                A hexbin map is a visual representation of data that aggregates individual data points into hexagonal bins or cells, typically used for spatial analysis. It helps to condense large datasets and identify patterns or trends within specific geographic regions.

                                                                                                Two types of hexbin map exist. The first one is based on a geoJsonfile that provides the hexagon boundaries. It is similar to a choropleth map, with hexagons instead of real regions. The second is actually a 2d density chart, but with GPS locations for the x and y coordinates.

                                                                                                This page is a long form tutorial explaining how to build hexbin maps using react and d3.js. It provides interactive examples for both types of hexbin maps with code explanation and should get you started for your web app.

                                                                                                Useful links

                                                                                                Hexbin map from a geoJson file

                                                                                                Drawing a map using react and d3.js usually relies on a geoJson file. This file format provides information for geographical regions. It stores the 2d coordinates of shapes.

                                                                                                This is the way it looks:

                                                                                                {
                                                                                                   "type": "FeatureCollection",
                                                                                                   "features": [
                                                                                                       {
                                                                                                @@ -105,4 +105,4 @@
                                                                                                 }

                                                                                                I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                Hexbin inspiration

                                                                                                If you're looking for inspiration to create your next Hexbin, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Hexbin looks good!

                                                                                                visit

                                                                                                Contact

                                                                                                👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                  -
                                                                                                  \ No newline at end of file +
                                                                                                  \ No newline at end of file diff --git a/hierarchical-edge-bundling.html b/hierarchical-edge-bundling.html index ca579439..8f2dcb97 100644 --- a/hierarchical-edge-bundling.html +++ b/hierarchical-edge-bundling.html @@ -1,4 +1,4 @@ -Hierarchical Edge Bundling | React Graph Gallery

                                                                                                  Hierarchical edge bundling

                                                                                                  Dataviz logo representing a Bundle chart.

                                                                                                  A hierarchical edge bundling chart allows to visualize relationships between entities organized in a hierarchy. The idea is to bundle the adjacency edges together to decrease the clutter usually observed in complex networks.

                                                                                                  This page explains how to build a hierarchical edge bundling chart using d3.js to compute the node position, and React to render the nodes and edges. It starts by describing the required data format, explains how to build a very basic hierarchical edge bundling and then shows how to customize it.

                                                                                                  Useful links

                                                                                                  The Data

                                                                                                  The dataset describes a hierarchy using a recursive structure.

                                                                                                  Each item in this structure is called a node. The lowest nodes of the hierarchy being called leaves.

                                                                                                  The dataset is an object that has at least 3 properties: name, value and children. children is an array of nodes that have this structure too.

                                                                                                  This kind of data is very close to what's required for a dendrogram. But an additional property is added for the leaves: links. It provides a list of all the other leaves this leaf is connected with.

                                                                                                  Here is a minimal example of the data structure:

                                                                                                  const data = {
                                                                                                  +Hierarchical Edge Bundling | React Graph Gallery

                                                                                                  Hierarchical edge bundling

                                                                                                  Dataviz logo representing a Bundle chart.

                                                                                                  A hierarchical edge bundling chart allows to visualize relationships between entities organized in a hierarchy. The idea is to bundle the adjacency edges together to decrease the clutter usually observed in complex networks.

                                                                                                  This page explains how to build a hierarchical edge bundling chart using d3.js to compute the node position, and React to render the nodes and edges. It starts by describing the required data format, explains how to build a very basic hierarchical edge bundling and then shows how to customize it.

                                                                                                  Useful links

                                                                                                  The Data

                                                                                                  The dataset describes a hierarchy using a recursive structure.

                                                                                                  Each item in this structure is called a node. The lowest nodes of the hierarchy being called leaves.

                                                                                                  The dataset is an object that has at least 3 properties: name, value and children. children is an array of nodes that have this structure too.

                                                                                                  This kind of data is very close to what's required for a dendrogram. But an additional property is added for the leaves: links. It provides a list of all the other leaves this leaf is connected with.

                                                                                                  Here is a minimal example of the data structure:

                                                                                                  const data = {
                                                                                                     type: 'node',
                                                                                                     name: "boss",
                                                                                                     value: 2300,
                                                                                                  @@ -47,4 +47,4 @@
                                                                                                     });

                                                                                                  Resulting in our first hierarchical edge bundling example 🎉

                                                                                                  MarkRobertEmilyMarionEdyGabYanNicolasMalkiDjéJoeKarlMamTotoTuckYamMélanieEinstein

                                                                                                  A first hierarchical edge bundling chart made with d3 and react.

                                                                                                  Coming soon

                                                                                                  Using canvas for rendering is often a requirement when the number of nodes gets big. Interactivity is often necessary, for hover effect or to collapse a part of the tree. It also possible to map the node circle size to a numeric variable.

                                                                                                  This will come soon! I have a newsletter called the dataviz universe where I share my latest updates.

                                                                                                  Subscribe

                                                                                                  Contact

                                                                                                  👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                  Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                    -
                                                                                                    \ No newline at end of file +
                                                                                                    \ No newline at end of file diff --git a/histogram.html b/histogram.html index 0ea8f8b5..4de71fd1 100644 --- a/histogram.html +++ b/histogram.html @@ -1,4 +1,4 @@ -How to build a histogram with React and D3.

                                                                                                    Histogram

                                                                                                    Dataviz logo representing a Histogram chart.

                                                                                                    A histogram is a chart type that shows the distribution of a numeric variable. This page is a step-by-step guide on how to build your own histogram for the web, using React and D3.js.

                                                                                                    It starts by describing how the data should be organized and how to initialize the histogram component. It then explains how to compute the buckets composing the histogram. Once this is done, it shows how to render the bars and suggests a few variations. 🙇‍♂️.

                                                                                                    Useful links

                                                                                                    The Data

                                                                                                    Building a histogram only requires a set of numeric values.

                                                                                                    As a result, the dataset is pretty simple: an array of numbers.


                                                                                                    Here is a minimal example of the data structure:

                                                                                                    const data = [1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 9]

                                                                                                    Component skeleton

                                                                                                    The goal here is to create a Histogram component that will be stored in a Histogram.tsx file. This component requires 3 props to render: a width, a height, and some data.

                                                                                                    The shape of the data is described above. The width and height will be used to render an svg element in the DOM, in which we will insert the histogram.

                                                                                                    To put it in a nutshell, that's the skeleton of our Histogram component:

                                                                                                    import * as d3 from "d3"; // we will need d3.js
                                                                                                    +How to build a histogram with React and D3.

                                                                                                    Histogram

                                                                                                    Dataviz logo representing a Histogram chart.

                                                                                                    A histogram is a chart type that shows the distribution of a numeric variable. This page is a step-by-step guide on how to build your own histogram for the web, using React and D3.js.

                                                                                                    It starts by describing how the data should be organized and how to initialize the histogram component. It then explains how to compute the buckets composing the histogram. Once this is done, it shows how to render the bars and suggests a few variations. 🙇‍♂️.

                                                                                                    Useful links

                                                                                                    The Data

                                                                                                    Building a histogram only requires a set of numeric values.

                                                                                                    As a result, the dataset is pretty simple: an array of numbers.


                                                                                                    Here is a minimal example of the data structure:

                                                                                                    const data = [1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 9]

                                                                                                    Component skeleton

                                                                                                    The goal here is to create a Histogram component that will be stored in a Histogram.tsx file. This component requires 3 props to render: a width, a height, and some data.

                                                                                                    The shape of the data is described above. The width and height will be used to render an svg element in the DOM, in which we will insert the histogram.

                                                                                                    To put it in a nutshell, that's the skeleton of our Histogram component:

                                                                                                    import * as d3 from "d3"; // we will need d3.js
                                                                                                     
                                                                                                     type HistogramProps = {
                                                                                                       width: number;
                                                                                                    @@ -82,7 +82,7 @@
                                                                                                       }, []);
                                                                                                     
                                                                                                       return dimensions;
                                                                                                    -}

                                                                                                    I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                    Histogram inspiration

                                                                                                    If you're looking for inspiration to create your next Histogram, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                    dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Histogram looks good!

                                                                                                    visit

                                                                                                    Variations

                                                                                                    Once you've understood how to build a basic histogram with d3 and react, it opens an infinite world of customization. Here are a few examples showing how to add several groups on the same axis or how to use small multiple with histograms to compare distributions.

                                                                                                    Click on the overview below to get details and code.


                                                                                                    picture of a mirror histogram made with react and d3.js

                                                                                                    Mirror histogram

                                                                                                    Create a mirror histogram to compare the distribution of 2 groups in a dataset

                                                                                                    Picture of a histogram with small multiple built with react and d3.js

                                                                                                    Small multiple

                                                                                                    Create one panel per group to show its distribution separately

                                                                                                    Picture of a histogram with multiple groups built with react and d3.js

                                                                                                    Multiple groups

                                                                                                    A histogram with <b>multiple</b> groups displayed on the same axis.

                                                                                                    Dataset transition

                                                                                                    The last step needed for a powerful histogram React component is a proper way to transition between various datasets. When the data prop updates, we need a stunning way to transition to the new values.

                                                                                                    There are many different strategies to approach this problem. I suggest to rely on the react-spring library that has everything we need to compute spring animations.

                                                                                                    Instead of rendering usual rect elements, the library provides a animated.rect element, that is linked to a useSpringhook.

                                                                                                    A histogram that smoothly transition from 1 dataset to another

                                                                                                    This is how the Rectangle component I use looks like:

                                                                                                    Rectangle: a component that animates the transition of a rect
                                                                                                    import { useSpring, animated } from "@react-spring/web";
                                                                                                    +}

                                                                                                    I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                    Histogram inspiration

                                                                                                    If you're looking for inspiration to create your next Histogram, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                    dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Histogram looks good!

                                                                                                    visit

                                                                                                    Variations

                                                                                                    Once you've understood how to build a basic histogram with d3 and react, it opens an infinite world of customization. Here are a few examples showing how to add several groups on the same axis or how to use small multiple with histograms to compare distributions.

                                                                                                    Click on the overview below to get details and code.


                                                                                                    picture of a mirror histogram made with react and d3.js

                                                                                                    Mirror histogram

                                                                                                    Create a mirror histogram to compare the distribution of 2 groups in a dataset

                                                                                                    Picture of a histogram with small multiple built with react and d3.js

                                                                                                    Small multiple

                                                                                                    Create one panel per group to show its distribution separately

                                                                                                    Picture of a histogram with multiple groups built with react and d3.js

                                                                                                    Multiple groups

                                                                                                    A histogram with <b>multiple</b> groups displayed on the same axis.

                                                                                                    Dataset transition

                                                                                                    The last step needed for a powerful histogram React component is a proper way to transition between various datasets. When the data prop updates, we need a stunning way to transition to the new values.

                                                                                                    There are many different strategies to approach this problem. I suggest to rely on the react-spring library that has everything we need to compute spring animations.

                                                                                                    Instead of rendering usual rect elements, the library provides a animated.rect element, that is linked to a useSpringhook.

                                                                                                    A histogram that smoothly transition from 1 dataset to another

                                                                                                    This is how the Rectangle component I use looks like:

                                                                                                    Rectangle: a component that animates the transition of a rect
                                                                                                    import { useSpring, animated } from "@react-spring/web";
                                                                                                     
                                                                                                     type RectangleProps = {
                                                                                                       width: number;
                                                                                                    @@ -123,4 +123,4 @@
                                                                                                     };

                                                                                                    Animation in dataviz using React is a big topic. It's impossible to go in depth here! I will publish a dedicated blog post on the topic soon. Please subscribe to the newsletter if you want to be notified.

                                                                                                    Contact

                                                                                                    👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                      -
                                                                                                      \ No newline at end of file +
                                                                                                      \ No newline at end of file diff --git a/img/js-lib-download-npm-trend.png b/img/js-lib-download-npm-trend.png new file mode 100644 index 0000000000000000000000000000000000000000..c83007ffdb031cd87b51bbad0a6ba115a5cd9db3 GIT binary patch literal 103754 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 literal 0 HcmV?d00001 diff --git a/img/react-website.png b/img/react-website.png new file mode 100644 index 0000000000000000000000000000000000000000..3c2a7b7adb71b66621740e4b462e5b68dba1f537 GIT binary patch literal 40328 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 z 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 to build unique charts with React

                                                                                                      Build unique React charts


                                                                                                      Have you ever wanted to create your own chart for the web?

                                                                                                      Based on hundreds of graph examples, this gallery guides you through the basic concepts of data visualization with React and D3.js. It also provides ready-to-use templates to get started quicker.

                                                                                                      Stop using pre-made dataviz components → imagination will become the only boundary to your creativity.

                                                                                                      The gallery is organized by chart types following the data-to-viz classification.

                                                                                                      Contact

                                                                                                      👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                      +Learn to build unique charts with React

                                                                                                      Build unique React charts


                                                                                                      Have you ever wanted to create your own chart for the web?

                                                                                                      Based on hundreds of graph examples, this gallery guides you through the basic concepts of data visualization with React and D3.js. It also provides ready-to-use templates to get started quicker.

                                                                                                      Stop using pre-made dataviz components → imagination will become the only boundary to your creativity.

                                                                                                      The gallery is organized by chart types following the data-to-viz classification.

                                                                                                      Contact

                                                                                                      👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                        -
                                                                                                        \ No newline at end of file +
                                                                                                        \ No newline at end of file diff --git a/interactivity.html b/interactivity.html index 69fac714..c3605a88 100644 --- a/interactivity.html +++ b/interactivity.html @@ -1,4 +1,4 @@ -Interactivity

                                                                                                        Interactivity

                                                                                                        Dataviz logo representing a Interactive chart.

                                                                                                        Interactivity is a key feature of any chart displayed on the web. It includes tooltip, hover effect, cross-graph interaction, zooming, panning and more.

                                                                                                        Interactivity is a big topic. This section aims at giving general tips and tricks on the topic together with applied examples ready to be used in your project.

                                                                                                        Useful links

                                                                                                        Work in Progress

                                                                                                        This section is a work in progress. 🚧

                                                                                                        For now, it just lists all the charts using Interactivity in the gallery.

                                                                                                        But I plan to write some complete tutorials on this passionating and complicated topic. You can subscribe to the project to know when it's ready!


                                                                                                        Subscribe


                                                                                                        GIF of a scatterplot with hover effect

                                                                                                        Scatterplot Hover effect

                                                                                                        How to add a hover effect to highlight a group on a scatterplot

                                                                                                        GIF of a bubble plot smoothly transitioning data

                                                                                                        Bubble plot data set transition

                                                                                                        How to smoothly animate the transition between dataset

                                                                                                        gif of a violin plot smoothly transitioning to a boxplot using shape morphism

                                                                                                        Violin to Boxplot transition

                                                                                                        Using shape morphism to smoothly transition from a boxplot to a violin and reverse

                                                                                                        GIF showing a violin plot with varying bucket size

                                                                                                        Bucket size effect

                                                                                                        Interactive example showing the bucket size effect on a violin chart

                                                                                                        GIF showing a mirror transition between a boxplot and a violin plot

                                                                                                        Boxplot to Violin plot

                                                                                                        Interactive example showing the difference between a boxplot and a violin

                                                                                                        GIF of a histogram with animated data transition

                                                                                                        Histogram dataset transition

                                                                                                        How to animate the transition between datasets

                                                                                                        GIF of a data update on a React barplot

                                                                                                        Barplot dataset transition

                                                                                                        How to smoothly animate the transition between dataset

                                                                                                        GIF of a line chart that animates between 2 dataset

                                                                                                        Line chart with dataset transition

                                                                                                        How to smoothly animate the transition between 2 dataset on a line chart

                                                                                                        GIF of a streamgraph react component that supports hover effect

                                                                                                        Streamgraph with hover effect

                                                                                                        How to add a hover effect on a streamgraph to highlight a group

                                                                                                        GIF of a streamgraph

                                                                                                        Offset and Smoothing transition

                                                                                                        An interactive streamgraph example showing how to animate transition between the chart stacking features.

                                                                                                        GIF of a streamgraph with multiple interactive features

                                                                                                        Streamgraph application

                                                                                                        Streamgraph with a slider to zoom on a time stamp and with interactive inline legends

                                                                                                        Contact

                                                                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                        +Interactivity

                                                                                                        Interactivity

                                                                                                        Dataviz logo representing a Interactive chart.

                                                                                                        Interactivity is a key feature of any chart displayed on the web. It includes tooltip, hover effect, cross-graph interaction, zooming, panning and more.

                                                                                                        Interactivity is a big topic. This section aims at giving general tips and tricks on the topic together with applied examples ready to be used in your project.

                                                                                                        Useful links

                                                                                                        Work in Progress

                                                                                                        This section is a work in progress. 🚧

                                                                                                        For now, it just lists all the charts using Interactivity in the gallery.

                                                                                                        But I plan to write some complete tutorials on this passionating and complicated topic. You can subscribe to the project to know when it's ready!


                                                                                                        Subscribe


                                                                                                        GIF of a scatterplot with hover effect

                                                                                                        Scatterplot Hover effect

                                                                                                        How to add a hover effect to highlight a group on a scatterplot

                                                                                                        GIF of a bubble plot smoothly transitioning data

                                                                                                        Bubble plot data set transition

                                                                                                        How to smoothly animate the transition between dataset

                                                                                                        gif of a violin plot smoothly transitioning to a boxplot using shape morphism

                                                                                                        Violin to Boxplot transition

                                                                                                        Using shape morphism to smoothly transition from a boxplot to a violin and reverse

                                                                                                        GIF showing a violin plot with varying bucket size

                                                                                                        Bucket size effect

                                                                                                        Interactive example showing the bucket size effect on a violin chart

                                                                                                        GIF showing a mirror transition between a boxplot and a violin plot

                                                                                                        Boxplot to Violin plot

                                                                                                        Interactive example showing the difference between a boxplot and a violin

                                                                                                        GIF of a histogram with animated data transition

                                                                                                        Histogram dataset transition

                                                                                                        How to animate the transition between datasets

                                                                                                        GIF of a data update on a React barplot

                                                                                                        Barplot dataset transition

                                                                                                        How to smoothly animate the transition between dataset

                                                                                                        GIF of a line chart that animates between 2 dataset

                                                                                                        Line chart with dataset transition

                                                                                                        How to smoothly animate the transition between 2 dataset on a line chart

                                                                                                        GIF of a streamgraph react component that supports hover effect

                                                                                                        Streamgraph with hover effect

                                                                                                        How to add a hover effect on a streamgraph to highlight a group

                                                                                                        GIF of a streamgraph

                                                                                                        Offset and Smoothing transition

                                                                                                        An interactive streamgraph example showing how to animate transition between the chart stacking features.

                                                                                                        GIF of a streamgraph with multiple interactive features

                                                                                                        Streamgraph application

                                                                                                        Streamgraph with a slider to zoom on a time stamp and with interactive inline legends

                                                                                                        Contact

                                                                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                          -
                                                                                                          \ No newline at end of file +
                                                                                                          \ No newline at end of file diff --git a/line-chart.html b/line-chart.html index 08d6c6ad..56e41db5 100644 --- a/line-chart.html +++ b/line-chart.html @@ -1,4 +1,4 @@ -Line chart | The React Graph Gallery

                                                                                                          Line chart

                                                                                                          Dataviz logo representing a Line chart.

                                                                                                          A line chart or line graph displays the evolution of one or several numeric variables. This page is a step-by-step guide on how to build your own line chart component for the web, using React and D3.js.

                                                                                                          It starts by describing how the data should be organized and how to initialize the react component. It then explains how to compute the scales, and axes. Once this is done, it shows how to render the lines and suggests a few variations. 🙇‍♂️.

                                                                                                          Useful links

                                                                                                          The Data

                                                                                                          The dataset required to build a line chart is usually an array where each item is an object providing the x and the y values of the data point.


                                                                                                          Here is a minimal example:

                                                                                                          const data = [
                                                                                                          +Line chart | The React Graph Gallery

                                                                                                          Line chart

                                                                                                          Dataviz logo representing a Line chart.

                                                                                                          A line chart or line graph displays the evolution of one or several numeric variables. This page is a step-by-step guide on how to build your own line chart component for the web, using React and D3.js.

                                                                                                          It starts by describing how the data should be organized and how to initialize the react component. It then explains how to compute the scales, and axes. Once this is done, it shows how to render the lines and suggests a few variations. 🙇‍♂️.

                                                                                                          Useful links

                                                                                                          The Data

                                                                                                          The dataset required to build a line chart is usually an array where each item is an object providing the x and the y values of the data point.


                                                                                                          Here is a minimal example:

                                                                                                          const data = [
                                                                                                             {x:1, y: 90},
                                                                                                             {x: 2, y: 12},
                                                                                                             {x: 3, y: 34},
                                                                                                          @@ -93,4 +93,4 @@
                                                                                                           };

                                                                                                          Click on the buttons to trigger a smooth transition between the 2 line charts.

                                                                                                          Animation in dataviz using React is a big topic. It's impossible to go in-depth here! I will publish a dedicated blog post on the topic soon. Please subscribe to the newsletter if you want to be notified.

                                                                                                          Variations

                                                                                                          You now have the basic understanding on how to build a basic line chart component with React and d3.js. Below are a few examples showing how to build more complex graphs based on those principles.

                                                                                                          GIF of a radar chart, a line chart and a lollipop that animate between dataset

                                                                                                          Radar chart, line chart an lollipop with animated transition

                                                                                                          Three charts connected to same buttons, with smooth, synchronized animation when a button is clicked

                                                                                                          line charts with synchronized cursors

                                                                                                          Synchronized cursors

                                                                                                          Add a cursor synchronized on all your charts

                                                                                                          Picture of a timeseries chart made with React and D3.js: scatterplot and line chart in use.

                                                                                                          Timeseries with moving average

                                                                                                          A scatterplot used for timeseries, with the moving average shown as a line chart on top.

                                                                                                          Next

                                                                                                          The react graph gallery is under heavy development. Here is a list of things that will be added soon.

                                                                                                          ToDoHow to add a tooltip
                                                                                                          ToDoMulti groups line charts aka Spaghetti chart
                                                                                                          ToDoSync with a bar chart
                                                                                                          ToDoDual Y Axis
                                                                                                          ToDoInline legend with Reppel


                                                                                                          Subscribe to the gallery to know when it is ready!

                                                                                                          Subscribe


                                                                                                          Contact

                                                                                                          👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                            -
                                                                                                            \ No newline at end of file +
                                                                                                            \ No newline at end of file diff --git a/lollipop-plot.html b/lollipop-plot.html index fd90f44f..2cadc66c 100644 --- a/lollipop-plot.html +++ b/lollipop-plot.html @@ -1,4 +1,4 @@ -Lollipop plot with React

                                                                                                            Lollipop plot

                                                                                                            Dataviz logo representing a Lollipop chart.

                                                                                                            A lollipop plot is a variation of the more common barplot. This page is a step-by-step guide on how to build your own lollipop for the web, using React and D3.js.

                                                                                                            It starts by describing how the data should be organized and how to initialize the lollipop component. It explains how to build the scales and axes and how to add the shapes. A few variations are described and a focus is made on the hover interaction. 🙇‍♂️.

                                                                                                            Useful links

                                                                                                            The Data

                                                                                                            The dataset required to build a lollipop is usually an array where each item is an object providing the name and the value of the group.


                                                                                                            Here is a minimal example:

                                                                                                            const data = [
                                                                                                            +Lollipop plot with React

                                                                                                            Lollipop plot

                                                                                                            Dataviz logo representing a Lollipop chart.

                                                                                                            A lollipop plot is a variation of the more common barplot. This page is a step-by-step guide on how to build your own lollipop for the web, using React and D3.js.

                                                                                                            It starts by describing how the data should be organized and how to initialize the lollipop component. It explains how to build the scales and axes and how to add the shapes. A few variations are described and a focus is made on the hover interaction. 🙇‍♂️.

                                                                                                            Useful links

                                                                                                            The Data

                                                                                                            The dataset required to build a lollipop is usually an array where each item is an object providing the name and the value of the group.


                                                                                                            Here is a minimal example:

                                                                                                            const data = [
                                                                                                               {name:"Mark", value: 90},
                                                                                                               {name:"Robert", value: 12},
                                                                                                               {name:"Emily", value: 34},
                                                                                                            @@ -68,4 +68,4 @@
                                                                                                             }

                                                                                                            → For the second effect, 2 svg rectangles must be drawn. The first one fills the full width and height of the row. It is the one that triggers the mouse event. (It is important to remember that a svg g element does not trigger mouse events. Only what is drawn inside it does). The second rectangle is the one that we see. We can add some vertical padding to it since it is not use for mouse detection.

                                                                                                            20406080100NicolasMarkMarionEmilyMélanieGabrielRobertPaul

                                                                                                            Try to hover a row in the lollipop above to reveal the hover interaction.

                                                                                                            Data transition

                                                                                                            It is very common to deal with various variables and compare the behaviour of some data items for them. It adds a nice touch to the graph to smoothly transition between 2 states using a quick animation.

                                                                                                            For the example below I rely on the react-spring library. This lib allows to quickly create spring animations using javascript. It results in a very a natural transition that can be interrupted without restarting from 0. (try to toggle between datasets quickly).

                                                                                                            It would be too long to explain the code here. Instead, I'm currently writing a set of dedicated tutorials. Please subscribe to the newsletter to know when this will be released.

                                                                                                            A lollipop chart with smooth transition between dataset.

                                                                                                            Variation

                                                                                                            Check a few other examples of the gallery involving lollipop plots:

                                                                                                            GIF of a radar chart, a line chart and a lollipop that animate between dataset

                                                                                                            Radar chart, line chart an lollipop with animated transition

                                                                                                            Three charts connected to same buttons, with smooth, synchronized animation when a button is clicked


                                                                                                            Contact

                                                                                                            👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                            Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                              -
                                                                                                              \ No newline at end of file +
                                                                                                              \ No newline at end of file diff --git a/map.html b/map.html index a1b126ea..7e423164 100644 --- a/map.html +++ b/map.html @@ -1,4 +1,4 @@ -How to build a background map with React and D3.

                                                                                                              Background Map

                                                                                                              Dataviz logo representing a Map chart.

                                                                                                              This section is dedicated to background maps. It is the fundation required to build more interesting dataviz-related mapslike bubble maps, choropleth maps and more.

                                                                                                              The interactive sandboxes and explanation below explain how to read a geoJson file and draw its content using React. It also show how useful the d3-geo module can be to deal with this format, notably to control the various existing projections.

                                                                                                              Last but not least, this document also briefly explains how Leaflet can be used in a React environment to display interactive maps.

                                                                                                              Useful links

                                                                                                              The Data

                                                                                                              The first thing you need to build a map is the 2d coordinates of the boundaries of the regions you want to represent. If you are trying to build a world map, you need to know where the country boundaries are located 🤷‍♀️.

                                                                                                              Several formats exist to store such a piece of information. When working with d3.js, the expected format is geoJSON. A geoJSON file looks pretty much like this:


                                                                                                              Here is a minimal example of the data structure:

                                                                                                              {
                                                                                                              +How to build a background map with React and D3.

                                                                                                              Background Map

                                                                                                              Dataviz logo representing a Map chart.

                                                                                                              This section is dedicated to background maps. It is the fundation required to build more interesting dataviz-related mapslike bubble maps, choropleth maps and more.

                                                                                                              The interactive sandboxes and explanation below explain how to read a geoJson file and draw its content using React. It also show how useful the d3-geo module can be to deal with this format, notably to control the various existing projections.

                                                                                                              Last but not least, this document also briefly explains how Leaflet can be used in a React environment to display interactive maps.

                                                                                                              Useful links

                                                                                                              The Data

                                                                                                              The first thing you need to build a map is the 2d coordinates of the boundaries of the regions you want to represent. If you are trying to build a world map, you need to know where the country boundaries are located 🤷‍♀️.

                                                                                                              Several formats exist to store such a piece of information. When working with d3.js, the expected format is geoJSON. A geoJSON file looks pretty much like this:


                                                                                                              Here is a minimal example of the data structure:

                                                                                                              {
                                                                                                                 "type": "FeatureCollection",
                                                                                                                 "features": [
                                                                                                                   {
                                                                                                              @@ -96,4 +96,4 @@
                                                                                                               }

                                                                                                              I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                              Map inspiration

                                                                                                              If you're looking for inspiration to create your next Map, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                              dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Map looks good!

                                                                                                              visit

                                                                                                              Contact

                                                                                                              👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                -
                                                                                                                \ No newline at end of file +
                                                                                                                \ No newline at end of file diff --git a/network-chart.html b/network-chart.html index bba5315e..7ffd6cb6 100644 --- a/network-chart.html +++ b/network-chart.html @@ -1,4 +1,4 @@ -How to build a Network Diagram with React and D3.

                                                                                                                Network diagram

                                                                                                                Dataviz logo representing a Network chart.

                                                                                                                A network diagram shows the interconnections between entities. It is consituted by nodes that represent entities and by links that show relationships between entities.

                                                                                                                This page is a step by step tutorial explaining how to build a network diagram component with React and D3.js. It relies on the d3-force plugin to compute the node positions. It comes with explanations and code sandboxes. It starts by simple concepts like how to format the data and how to draw nodes and links in SVG, and then goes further with hover effect, tooltip and more.

                                                                                                                Useful links

                                                                                                                The Data

                                                                                                                Two layers of information are required to build a network diagram: a list of nodes to build the circles and a list of links to build the lines.

                                                                                                                Many different data structures can be used to store such information. In this tutorial I suggest to start with the following:

                                                                                                                export const data = {
                                                                                                                +How to build a Network Diagram with React and D3.

                                                                                                                Network diagram

                                                                                                                Dataviz logo representing a Network chart.

                                                                                                                A network diagram shows the interconnections between entities. It is consituted by nodes that represent entities and by links that show relationships between entities.

                                                                                                                This page is a step by step tutorial explaining how to build a network diagram component with React and D3.js. It relies on the d3-force plugin to compute the node positions. It comes with explanations and code sandboxes. It starts by simple concepts like how to format the data and how to draw nodes and links in SVG, and then goes further with hover effect, tooltip and more.

                                                                                                                Useful links

                                                                                                                The Data

                                                                                                                Two layers of information are required to build a network diagram: a list of nodes to build the circles and a list of links to build the lines.

                                                                                                                Many different data structures can be used to store such information. In this tutorial I suggest to start with the following:

                                                                                                                export const data = {
                                                                                                                   nodes: [
                                                                                                                       { id: "Myriel", group: 'team1' },
                                                                                                                       { id: "Anne", group: 'team1' },
                                                                                                                @@ -99,4 +99,4 @@
                                                                                                                 }

                                                                                                                I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                Network inspiration

                                                                                                                If you're looking for inspiration to create your next Network, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Network looks good!

                                                                                                                visit

                                                                                                                Available forces

                                                                                                                The exausthive list of forces that can be applied to nodes is available in the official documentation. Here is an overview of the main ones:

                                                                                                                • d3.forceManyBody() → simulates attraction between nodes if its strength is positive, repulsion otherwise.

                                                                                                                • d3.forceCenter() → translates nodes uniformly so that the mean position of all nodes is at a given position.

                                                                                                                • d3.forceCollide() → tries to avoid node collision and overlap. You can provide a radius and a strength.

                                                                                                                • d3.forceLink() → pushes linked nodes together or apart according to the desired link distance.

                                                                                                                • d3.forceX() → applies a force toward a X position to all nodes. d3.forceY() is also available.
                                                                                                                Radius used to avoid collision: 25
                                                                                                                ManyBody strength: 0
                                                                                                                ForceY strength: 0.1

                                                                                                                A first network diagram built using react and d3-force.

                                                                                                                Variations

                                                                                                                Once you've understood how to build a basic network diagram with d3 and react, it opens an infinite world of customization. Here are a few examples using the same concepts.

                                                                                                                Click on the overview below to get details and code.


                                                                                                                Picture of a circle packing chart made using the d3-force plugin

                                                                                                                Circle Pack with d3-force

                                                                                                                Another approach to build a circle packing chart using physical forces to compute node positions.

                                                                                                                Picture of a vertical arc diagram

                                                                                                                Vertical arc diagram

                                                                                                                The vertical version of the arc diagram is more convenient to display labels

                                                                                                                Picture of a force directed network chart showing character co-occurence in les miserables

                                                                                                                Force directed graph

                                                                                                                A force directed network chart showing character co-occurence in les miserables

                                                                                                                Contact

                                                                                                                👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                  -
                                                                                                                  \ No newline at end of file +
                                                                                                                  \ No newline at end of file diff --git a/parallel-plot.html b/parallel-plot.html index 9890d886..9a312ae1 100644 --- a/parallel-plot.html +++ b/parallel-plot.html @@ -1,4 +1,4 @@ -Parallel Coordinate chart | React graph gallery

                                                                                                                  Parallel coordinates

                                                                                                                  Dataviz logo representing a Parallel1 chart.

                                                                                                                  A parallel coordinate chart is a type of visualization used to represent multivariate data on a two-dimensional plane by plotting each variable as a separate axis arranged in parallel, and then connecting the data points with lines.

                                                                                                                  This page is a step-by-step guide on how to build your own parallel coordinate chart for the web, using React (for rendering) and D3.js (to compute the axis, and shape coordinates).

                                                                                                                  It starts by describing how the data should be organized and how to initialize the parallel coordinate component. It then explains how to compute axis dynamically, and plot the lines and axis. Once this is done, it shows how to deal with scaling and how to add an interactive legend. 🙇‍♂️.

                                                                                                                  Useful links

                                                                                                                  The Data

                                                                                                                  The dataset provides several numeric values for a set of data points. It can also add some categorical variables that can be added to customize the marker colors.

                                                                                                                  The suggested data structure is an array of object, where each object is a data point. It can have as many numeric properties as needed.


                                                                                                                  Here is a minimal example of the data structure:

                                                                                                                  const data = [
                                                                                                                  +Parallel Coordinate chart | React graph gallery

                                                                                                                  Parallel coordinates

                                                                                                                  Dataviz logo representing a Parallel1 chart.

                                                                                                                  A parallel coordinate chart is a type of visualization used to represent multivariate data on a two-dimensional plane by plotting each variable as a separate axis arranged in parallel, and then connecting the data points with lines.

                                                                                                                  This page is a step-by-step guide on how to build your own parallel coordinate chart for the web, using React (for rendering) and D3.js (to compute the axis, and shape coordinates).

                                                                                                                  It starts by describing how the data should be organized and how to initialize the parallel coordinate component. It then explains how to compute axis dynamically, and plot the lines and axis. Once this is done, it shows how to deal with scaling and how to add an interactive legend. 🙇‍♂️.

                                                                                                                  Useful links

                                                                                                                  The Data

                                                                                                                  The dataset provides several numeric values for a set of data points. It can also add some categorical variables that can be added to customize the marker colors.

                                                                                                                  The suggested data structure is an array of object, where each object is a data point. It can have as many numeric properties as needed.


                                                                                                                  Here is a minimal example of the data structure:

                                                                                                                  const data = [
                                                                                                                     {var1: 5.1, var2: 3.5, ..., group: 'setosa'},
                                                                                                                     {var1: 4.9, var2: 3.0, ..., group: 'setosa'},
                                                                                                                     ...
                                                                                                                  @@ -84,4 +84,4 @@
                                                                                                                   }

                                                                                                                  I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                  Parallel inspiration

                                                                                                                  If you're looking for inspiration to create your next Parallel, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                  dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Parallel looks good!

                                                                                                                  visit

                                                                                                                  Contact

                                                                                                                  👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                  Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                    -
                                                                                                                    \ No newline at end of file +
                                                                                                                    \ No newline at end of file diff --git a/pie-plot.html b/pie-plot.html index 061a0b2c..bab1c8d7 100644 --- a/pie-plot.html +++ b/pie-plot.html @@ -1,4 +1,4 @@ -Pie chart with React

                                                                                                                    Pie chart

                                                                                                                    Dataviz logo representing a Pie chart.

                                                                                                                    A pie chart is a type of graph used to visually represent data as a circular, segmented chart. The chart is divided into slices, where the size of each slice represents the proportion of data that falls within a particular category or group.

                                                                                                                    This post explains how to build a pie chart with react, using the pie() function of d3.js. It describes the expected data format, how the Pie component must be structured, how to compute the slice positions and how to render those slices. Last but not least, it provides the implementation for common use-cases like hover effect and data transition.

                                                                                                                    Useful links

                                                                                                                    The Data

                                                                                                                    The dataset required to build a pie chart is pretty simple. It is an array where each item represents a group of the pie chart. Each item is an object with 2 properties. They provide the group name (name) and its value (value).


                                                                                                                    For instance, here is the dataset used for the simple pie chart below:

                                                                                                                    const data = [
                                                                                                                    +Pie chart with React

                                                                                                                    Pie chart

                                                                                                                    Dataviz logo representing a Pie chart.

                                                                                                                    A pie chart is a type of graph used to visually represent data as a circular, segmented chart. The chart is divided into slices, where the size of each slice represents the proportion of data that falls within a particular category or group.

                                                                                                                    This post explains how to build a pie chart with react, using the pie() function of d3.js. It describes the expected data format, how the Pie component must be structured, how to compute the slice positions and how to render those slices. Last but not least, it provides the implementation for common use-cases like hover effect and data transition.

                                                                                                                    Useful links

                                                                                                                    The Data

                                                                                                                    The dataset required to build a pie chart is pretty simple. It is an array where each item represents a group of the pie chart. Each item is an object with 2 properties. They provide the group name (name) and its value (value).


                                                                                                                    For instance, here is the dataset used for the simple pie chart below:

                                                                                                                    const data = [
                                                                                                                       {name:"Mark", value: 90},
                                                                                                                       {name:"Robert", value: 12},
                                                                                                                       {name:"Emily", value: 34},
                                                                                                                    @@ -99,4 +99,4 @@
                                                                                                                     }

                                                                                                                    I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                    Pie Chart inspiration

                                                                                                                    If you're looking for inspiration to create your next Pie Chart, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                    dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Pie Chart looks good!

                                                                                                                    visit

                                                                                                                    Data transition

                                                                                                                    The Pie component expects a data prop. What should we do when this data changes?

                                                                                                                    By default, the chart will update instantly, with no transition. Adding a smooth transition gives a nice polish touch to the graph. Try to switch between the 2 datasets below to see the animation in action.

                                                                                                                    The code below relies on the react-spring library. Instead of rendering a path for each slice, it uses a animated.path component that handles the spring animation for us.

                                                                                                                    The implementation is not trivial. I plan to publish a full tutorial on react-spring for data visualization soon. You can subscribe here to be notified when it is ready.

                                                                                                                    A donut chart with clean inline legends, built thanks to the centroid function of d3.js.

                                                                                                                    Note: check the blue group that appears / disappears between dataset. This kind of enter/exit pattern is something to keep in mind when building animations.

                                                                                                                    Pie chart to barplot

                                                                                                                    Pie charts are often criticized since angles are hard to read. Let's represent the same data using a pie chart or a barplot, to see what's the most insightful 🤷‍♂️.

                                                                                                                    Note that here we animate the transition between different shape types: each arc becomes a rectangle and reciprocally. This is made possible thanks to the flubber library, used in coordination with react-spring.

                                                                                                                    Once more, a full tutorial is needed here. You can subscribe here to be notified when it is ready. In the meanwhile, the code of this specific example is provided below.

                                                                                                                    Transition from a pie chart to a barplot with a smooth animation using the buttons on top.

                                                                                                                    Contact

                                                                                                                    👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                      -
                                                                                                                      \ No newline at end of file +
                                                                                                                      \ No newline at end of file diff --git a/radar-chart.html b/radar-chart.html index 486415f8..21cdad87 100644 --- a/radar-chart.html +++ b/radar-chart.html @@ -1,4 +1,4 @@ -Radar chart | React graph gallery

                                                                                                                      Radar Chart

                                                                                                                      Dataviz logo representing a Spider chart.

                                                                                                                      A radar or spider or web chart is a two-dimensional chart type designed to plot one or more series of values over multiple quantitative variables. Each variable has its own axis, all axes are joined in the center of the figure.

                                                                                                                      This page is a step-by-step guide on how to build your own radar chart for the web, using React (for rendering) and D3.js (to compute the axis, and shape coordinates).

                                                                                                                      It starts by describing how the data should be organized and how to initialize the Radar component. It then explains how to compute axis dynamically, and plot the lines and axis. Once this is done, it shows how to deal with scaling and how to add an interactive legend. 🙇‍♂️.

                                                                                                                      Useful links

                                                                                                                      The Data

                                                                                                                      The dataset provides several numeric values for a set of data items.

                                                                                                                      The suggested data structure is an array of object, where each object is a data item. It can have as many numeric properties as needed. It also has a name property that identifies the data item.


                                                                                                                      Here is a minimal example of the data structure:

                                                                                                                      const data = [
                                                                                                                      +Radar chart | React graph gallery

                                                                                                                      Radar Chart

                                                                                                                      Dataviz logo representing a Spider chart.

                                                                                                                      A radar or spider or web chart is a two-dimensional chart type designed to plot one or more series of values over multiple quantitative variables. Each variable has its own axis, all axes are joined in the center of the figure.

                                                                                                                      This page is a step-by-step guide on how to build your own radar chart for the web, using React (for rendering) and D3.js (to compute the axis, and shape coordinates).

                                                                                                                      It starts by describing how the data should be organized and how to initialize the Radar component. It then explains how to compute axis dynamically, and plot the lines and axis. Once this is done, it shows how to deal with scaling and how to add an interactive legend. 🙇‍♂️.

                                                                                                                      Useful links

                                                                                                                      The Data

                                                                                                                      The dataset provides several numeric values for a set of data items.

                                                                                                                      The suggested data structure is an array of object, where each object is a data item. It can have as many numeric properties as needed. It also has a name property that identifies the data item.


                                                                                                                      Here is a minimal example of the data structure:

                                                                                                                      const data = [
                                                                                                                         {var1: 5.1, var2: 3.5, ..., name: 'Mark'},
                                                                                                                         {var1: 4.9, var2: 3.0, ..., name: 'Rosa'},
                                                                                                                         ...
                                                                                                                      @@ -89,4 +89,4 @@
                                                                                                                       }

                                                                                                                      I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                      Spider / Radar inspiration

                                                                                                                      If you're looking for inspiration to create your next Spider / Radar, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                      dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Spider / Radar looks good!

                                                                                                                      visit

                                                                                                                      Radar chart with several groups

                                                                                                                      The process to get a radar chart with several groups is very similar to the previous example.

                                                                                                                      We just need to create a color scale and add a shape for each item of the dataset through a loop. Do not try to add too many groups on the same figure, it make it totally unreadable.

                                                                                                                      speedaccelerationconsosafetystyleprice

                                                                                                                      A radar chart with several groups displayed on the same figure. Made with React and d3.js

                                                                                                                      ToDospider chart with small multiple to make it more readable

                                                                                                                      Animation

                                                                                                                      It is common to have a radar chart that is updated when a button is clicked on the application. It is possible to implement a smooth, animated transition between states thanks to the react-spring library.

                                                                                                                      The following example illustrates this with a real world example. The radar chart is animated, together with a line chart and a lollipop.


                                                                                                                      GIF of a radar chart, a line chart and a lollipop that animate between dataset

                                                                                                                      Radar chart, line chart an lollipop with animated transition

                                                                                                                      Three charts connected to same buttons, with smooth, synchronized animation when a button is clicked

                                                                                                                      Contact

                                                                                                                      👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                        -
                                                                                                                        \ No newline at end of file +
                                                                                                                        \ No newline at end of file diff --git a/react-d3-dataviz-course.html b/react-d3-dataviz-course.html index ed8e444c..71607b72 100644 --- a/react-d3-dataviz-course.html +++ b/react-d3-dataviz-course.html @@ -1,4 +1,4 @@ -Dataviz with react online course

                                                                                                                        Dataviz with React fundamentals


                                                                                                                        Mastering chart creation with React and D3 involves understanding a multitude of concepts. It took me 5 years to get them.

                                                                                                                        The gallery offers hundreds of examples and several ready-to-use components to help you get started.

                                                                                                                        However, to truly grasp the big picture, guidance is essential. It took me thousands of hours to achieve this understanding, and I'm here to guide you!

                                                                                                                        Module 0

                                                                                                                        Introduction

                                                                                                                        While you're likely familiar with React, you might not know that D3 is the essential JavaScript library for data visualization.

                                                                                                                        This module provides a quick overview of the tools needed to create great charts in a browser.

                                                                                                                        Module 2

                                                                                                                        Scales

                                                                                                                        Your svg area goes from 0 to 500px. Your data goes from 0 to 100. If the value of a data point is 30, where should you draw it?

                                                                                                                        You need a scale to find out.

                                                                                                                        Module 4

                                                                                                                        Responsiveness

                                                                                                                        Some people have big monitors when others will read your work on their phone. Let's see how to make your graph look good in any situation.

                                                                                                                        Module 6

                                                                                                                        Tooltip

                                                                                                                        Let's check how to add a tooltip. Give a tooltip definition. Give several tooltip component starters.

                                                                                                                        Module 8

                                                                                                                        Legend

                                                                                                                        Those little legends are often small, but as complicated to build as the main graph. This module provides a few ready to use legend components.

                                                                                                                        Module 10

                                                                                                                        Canvas

                                                                                                                        With thousands of shapes on your graph, using SVG will make your graph slow.

                                                                                                                        Canvas is an alternative way to draw on a screen. Much more performant, but harder to deal with.

                                                                                                                        Module 1

                                                                                                                        SVG

                                                                                                                        A graph is basically a compendium of shapes drawn on a screen.

                                                                                                                        The most common way to draw shapes in a browser is to use SVG. Let's learn the essential of what SVG is, step by step.

                                                                                                                        Module 3

                                                                                                                        Axes

                                                                                                                        Now that we know how to add shapes on the graph, it is time to add context to it. Let's see how to draw axes.

                                                                                                                        Module 5

                                                                                                                        Hover effect

                                                                                                                        You want something to happen when a graph element is hovered. This module dives into several strategies using CSS and Javascript. It provides a clear mental modal of the main use cases and how to deal with each of them.

                                                                                                                        Module 7

                                                                                                                        Reading data

                                                                                                                        Your data can be a json file or a tabular format. It can be hosted locally or available through an API. How can you read it?

                                                                                                                        Module 9

                                                                                                                        Animation

                                                                                                                        Let's dig into those smooth dataset transition that make the viz magical. It's challenging, but react-spring is of great help here.

                                                                                                                        Contact

                                                                                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                        +Dataviz with react online course

                                                                                                                        Dataviz with React fundamentals


                                                                                                                        Mastering chart creation with React and D3 involves understanding a multitude of concepts. It took me 5 years to get them.

                                                                                                                        The gallery offers hundreds of examples and several ready-to-use components to help you get started.

                                                                                                                        However, to truly grasp the big picture, guidance is essential. It took me thousands of hours to achieve this understanding, and I'm here to guide you!

                                                                                                                        Module 0

                                                                                                                        Introduction

                                                                                                                        While you're likely familiar with React, you might not know that D3 is the essential JavaScript library for data visualization.

                                                                                                                        This module provides a quick overview of the tools needed to create great charts in a browser.

                                                                                                                        Module 2

                                                                                                                        Scales

                                                                                                                        Your svg area goes from 0 to 500px. Your data goes from 0 to 100. If the value of a data point is 30, where should you draw it?

                                                                                                                        You need a scale to find out.

                                                                                                                        Module 4

                                                                                                                        Responsiveness

                                                                                                                        Some people have big monitors when others will read your work on their phone. Let's see how to make your graph look good in any situation.

                                                                                                                        Module 6

                                                                                                                        Tooltip

                                                                                                                        Let's check how to add a tooltip. Give a tooltip definition. Give several tooltip component starters.

                                                                                                                        Module 8

                                                                                                                        Legend

                                                                                                                        Those little legends are often small, but as complicated to build as the main graph. This module provides a few ready to use legend components.

                                                                                                                        Module 10

                                                                                                                        Canvas

                                                                                                                        With thousands of shapes on your graph, using SVG will make your graph slow.

                                                                                                                        Canvas is an alternative way to draw on a screen. Much more performant, but harder to deal with.

                                                                                                                        Module 1

                                                                                                                        SVG

                                                                                                                        A graph is basically a compendium of shapes drawn on a screen.

                                                                                                                        The most common way to draw shapes in a browser is to use SVG. Let's learn the essential of what SVG is, step by step.

                                                                                                                        Module 3

                                                                                                                        Axes

                                                                                                                        Now that we know how to add shapes on the graph, it is time to add context to it. Let's see how to draw axes.

                                                                                                                        Module 5

                                                                                                                        Hover effect

                                                                                                                        You want something to happen when a graph element is hovered. This module dives into several strategies using CSS and Javascript. It provides a clear mental modal of the main use cases and how to deal with each of them.

                                                                                                                        Module 7

                                                                                                                        Reading data

                                                                                                                        Your data can be a json file or a tabular format. It can be hosted locally or available through an API. How can you read it?

                                                                                                                        Module 9

                                                                                                                        Animation

                                                                                                                        Let's dig into those smooth dataset transition that make the viz magical. It's challenging, but react-spring is of great help here.

                                                                                                                        Contact

                                                                                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                          -
                                                                                                                          \ No newline at end of file +
                                                                                                                          \ No newline at end of file diff --git a/react-dataviz-animation-with-react-spring.html b/react-dataviz-animation-with-react-spring.html index 733dadd4..3cf88684 100644 --- a/react-dataviz-animation-with-react-spring.html +++ b/react-dataviz-animation-with-react-spring.html @@ -1,7 +1,7 @@ -React-spring for data visualization

                                                                                                                          React-spring for data visualization


                                                                                                                          This post is dedicated to react-spring, a javascript library for spring animations. It quickly explains what it is and how it works, and then explains how it can be used in the field of data visualization.

                                                                                                                          A minimal react-spring dataviz example. A viz component expect a position and a color prop. But it smoothly animates the transition.

                                                                                                                          What is spring animation

                                                                                                                          Spring animations are different than typical CSS easing animation. They're built on spring physics, which gives a more fluid and organic feel. The best way to be introduced to this concept is to read Josh Comeau's friendly Introduction to Spring Physics

                                                                                                                          To quote him directly:

                                                                                                                          Spring physics are like a secret ingredient; they make all animations taste better

                                                                                                                          Basic react spring animation

                                                                                                                          The best tool to build a spring animation in the react world is react-spring, a library dedicated to it. If you're not familiar with it already you probably want to take a look at their home page.

                                                                                                                          Let's start with a basic example showing how to animate a very basic viz component that just renders a circle.

                                                                                                                          A very basic animation using react and react-spring.

                                                                                                                          The useSpring funtion can take 2 types of input: an object or a function

                                                                                                                          • if object, it returns an object that has the values of our animation
                                                                                                                          • if function, it returns an array of length 2. First item is the object mentionned above. item 2 is the api that controls the spring. api is used for imperative style

                                                                                                                          Animating axes

                                                                                                                          A common hassle is to animate axes, since it's a lot of svg elements.

                                                                                                                          A very basic animation using react and react-spring.




                                                                                                                          Contact

                                                                                                                          👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                          +React-spring for data visualization

                                                                                                                          React-spring for data visualization


                                                                                                                          This post is dedicated to react-spring, a javascript library for spring animations. It quickly explains what it is and how it works, and then explains how it can be used in the field of data visualization.

                                                                                                                          A minimal react-spring dataviz example. A viz component expect a position and a color prop. But it smoothly animates the transition.

                                                                                                                          What is spring animation

                                                                                                                          Spring animations are different than typical CSS easing animation. They're built on spring physics, which gives a more fluid and organic feel. The best way to be introduced to this concept is to read Josh Comeau's friendly Introduction to Spring Physics

                                                                                                                          To quote him directly:

                                                                                                                          Spring physics are like a secret ingredient; they make all animations taste better

                                                                                                                          Basic react spring animation

                                                                                                                          The best tool to build a spring animation in the react world is react-spring, a library dedicated to it. If you're not familiar with it already you probably want to take a look at their home page.

                                                                                                                          Let's start with a basic example showing how to animate a very basic viz component that just renders a circle.

                                                                                                                          A very basic animation using react and react-spring.

                                                                                                                          The useSpring funtion can take 2 types of input: an object or a function

                                                                                                                          • if object, it returns an object that has the values of our animation
                                                                                                                          • if function, it returns an array of length 2. First item is the object mentionned above. item 2 is the api that controls the spring. api is used for imperative style

                                                                                                                          Animating axes

                                                                                                                          A common hassle is to animate axes, since it's a lot of svg elements.

                                                                                                                          A very basic animation using react and react-spring.




                                                                                                                          Contact

                                                                                                                          👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                            Contact

                                                                                                                            👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                            Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                              -
                                                                                                                              \ No newline at end of file +
                                                                                                                              \ No newline at end of file diff --git a/ridgeline.html b/ridgeline.html index 8095d95f..86d30277 100644 --- a/ridgeline.html +++ b/ridgeline.html @@ -1,4 +1,4 @@ -Ridgeline chart with React

                                                                                                                              Ridgeline chart

                                                                                                                              Dataviz logo representing a Joyplot chart.

                                                                                                                              A ridgeline chart is a chart type that shows the distribution of a numeric variable for several groups, stacked one of top of each other. This page is a step-by-step guide on how to build your own histogram for the web, using React and D3.js.

                                                                                                                              It starts by describing how the data should be organized and how to initialize the ridgeline component. It then quickly recalls how to compute and draw a kernel density, and shows how to stack this information for several groups of a dataset. 🙇‍♂️.

                                                                                                                              Useful links

                                                                                                                              The Data

                                                                                                                              To build a ridgeline chart, the input dataset must provide a set ofnumeric values for several groups.

                                                                                                                              The best way to format this kind of information is with an array of object. Each object represents a group. Agroup property provides the group name, and a values property provides the values.


                                                                                                                              Here is a minimal example of the data structure:

                                                                                                                              export const data = [
                                                                                                                              +Ridgeline chart with React

                                                                                                                              Ridgeline chart

                                                                                                                              Dataviz logo representing a Joyplot chart.

                                                                                                                              A ridgeline chart is a chart type that shows the distribution of a numeric variable for several groups, stacked one of top of each other. This page is a step-by-step guide on how to build your own histogram for the web, using React and D3.js.

                                                                                                                              It starts by describing how the data should be organized and how to initialize the ridgeline component. It then quickly recalls how to compute and draw a kernel density, and shows how to stack this information for several groups of a dataset. 🙇‍♂️.

                                                                                                                              Useful links

                                                                                                                              The Data

                                                                                                                              To build a ridgeline chart, the input dataset must provide a set ofnumeric values for several groups.

                                                                                                                              The best way to format this kind of information is with an array of object. Each object represents a group. Agroup property provides the group name, and a values property provides the values.


                                                                                                                              Here is a minimal example of the data structure:

                                                                                                                              export const data = [
                                                                                                                                 {
                                                                                                                                   group: "A",
                                                                                                                                   values: [0, 0, 2, 2, 2, 0, 0, 1],
                                                                                                                              @@ -57,4 +57,4 @@
                                                                                                                               }

                                                                                                                              I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                              Ridgeline inspiration

                                                                                                                              If you're looking for inspiration to create your next Ridgeline, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                              dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Ridgeline looks good!

                                                                                                                              visit

                                                                                                                              Variations

                                                                                                                              Ridgeline charts are not the only way to compare the distribution of several groups in a dataset. Boxplots, violins, histograms and densities are variations that could interst you in order to solve this goal. Check the examples below to get the code.

                                                                                                                              Picture of a basic violin chart built in react

                                                                                                                              Basic violin plot

                                                                                                                              Learn how to build a basic violin chart with d3 and react

                                                                                                                              Picture of a density plot with multiple groups

                                                                                                                              Density plot with multiple groups

                                                                                                                              How to add several groups on the same density plot

                                                                                                                              Picture of a histogram with small multiple built with react and d3.js

                                                                                                                              Small multiple

                                                                                                                              Create one panel per group to show its distribution separately

                                                                                                                              Picture of a histogram with multiple groups built with react and d3.js

                                                                                                                              Multiple groups

                                                                                                                              A histogram with <b>multiple</b> groups displayed on the same axis.

                                                                                                                              Picture of a boxplot with jitter built using react and d3.js

                                                                                                                              Boxplot with jitter

                                                                                                                              Add individual data points using jitter on top of the boxplot

                                                                                                                              Picture of a basic boxplot built with react and d3

                                                                                                                              Basic boxplot

                                                                                                                              How to build a basic boxplot with react

                                                                                                                              Contact

                                                                                                                              👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                -
                                                                                                                                \ No newline at end of file +
                                                                                                                                \ No newline at end of file diff --git a/sankey-diagram.html b/sankey-diagram.html index 559b85f7..d251567f 100644 --- a/sankey-diagram.html +++ b/sankey-diagram.html @@ -1,4 +1,4 @@ -How to build a Sankey Diagram with React and D3.

                                                                                                                                Sankey Diagram

                                                                                                                                Dataviz logo representing a Sankey chart.

                                                                                                                                A Sankey Diagram display flows. Several entities (nodes) are represented by rectangles or text. Directed links are represented with arrows or arcs that have a width proportional to the importance of the flow.

                                                                                                                                This tutorial explains how to use React, D3.js and the d3-sankey plugin to build a Sankey diagram. It comes with explanations and code sandboxes to play along with the suggested implementation.

                                                                                                                                Useful links

                                                                                                                                The Data

                                                                                                                                Two layers of information are required to build a Sankey diagram: a list of nodes to build the rectangles and a list of links to build the paths between them.

                                                                                                                                Many different data structures can be used to store such information. In this tutorial I suggest to start with the following:

                                                                                                                                const data = {
                                                                                                                                +How to build a Sankey Diagram with React and D3.

                                                                                                                                Sankey Diagram

                                                                                                                                Dataviz logo representing a Sankey chart.

                                                                                                                                A Sankey Diagram display flows. Several entities (nodes) are represented by rectangles or text. Directed links are represented with arrows or arcs that have a width proportional to the importance of the flow.

                                                                                                                                This tutorial explains how to use React, D3.js and the d3-sankey plugin to build a Sankey diagram. It comes with explanations and code sandboxes to play along with the suggested implementation.

                                                                                                                                Useful links

                                                                                                                                The Data

                                                                                                                                Two layers of information are required to build a Sankey diagram: a list of nodes to build the rectangles and a list of links to build the paths between them.

                                                                                                                                Many different data structures can be used to store such information. In this tutorial I suggest to start with the following:

                                                                                                                                const data = {
                                                                                                                                   nodes: [
                                                                                                                                       { node: 0, name: "node0" },
                                                                                                                                       { node: 1, name: "node1" },
                                                                                                                                @@ -82,4 +82,4 @@
                                                                                                                                 }

                                                                                                                                I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                                Sankey inspiration

                                                                                                                                If you're looking for inspiration to create your next Sankey, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                                dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Sankey looks good!

                                                                                                                                visit

                                                                                                                                Application to a real dataset

                                                                                                                                This Sankey diagram visualizes the flow of energy: supplies are on the left, and demands are on the right. It is a reproduction of this famous observable example. Links show how varying amounts of energy are converted or transmitted before being consumed or lost.

                                                                                                                                The code is very similar to the example above. On top of it, a color scale is used for the node and connection colors, and some text labels have been added.

                                                                                                                                A Sankey diagram showing the flow of energy. Supplies on the left, demands on the right.

                                                                                                                                ToDoAdd hover effect to highlight links
                                                                                                                                ToDoAdd gradient along links
                                                                                                                                ToDoFix types

                                                                                                                                Contact

                                                                                                                                👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                  -
                                                                                                                                  \ No newline at end of file +
                                                                                                                                  \ No newline at end of file diff --git a/scatter-plot.html b/scatter-plot.html index 84359c5d..71ad14e7 100644 --- a/scatter-plot.html +++ b/scatter-plot.html @@ -1,4 +1,4 @@ -How to build a scatter plot with React and D3.

                                                                                                                                  Scatterplot

                                                                                                                                  Dataviz logo representing a ScatterPlot chart.

                                                                                                                                  A scatterplot displays the relationship between 2 numeric variables. This page is a step-by-step guide on how to build your own scatterplot for the web, using React and D3.js.

                                                                                                                                  It starts with very basic concepts like data structure, scales and svg circle rendering. It then shows how to add interactivity to the chart with hover effects and tooltips. At the end of the post, you should be able to build you own ready-to-publish scatterplot 🙇‍♂️.

                                                                                                                                  Useful links

                                                                                                                                  The Data

                                                                                                                                  The dataset used to build a scatterplot is usually an array of objects.

                                                                                                                                  For each object, at least 2 properties are required: x and y. The value of x will control the position of the datapoint on the horizontal axis. The value of y will be linked with the vertical axis.

                                                                                                                                  const data = [
                                                                                                                                  +How to build a scatter plot with React and D3.

                                                                                                                                  Scatterplot

                                                                                                                                  Dataviz logo representing a ScatterPlot chart.

                                                                                                                                  A scatterplot displays the relationship between 2 numeric variables. This page is a step-by-step guide on how to build your own scatterplot for the web, using React and D3.js.

                                                                                                                                  It starts with very basic concepts like data structure, scales and svg circle rendering. It then shows how to add interactivity to the chart with hover effects and tooltips. At the end of the post, you should be able to build you own ready-to-publish scatterplot 🙇‍♂️.

                                                                                                                                  Useful links

                                                                                                                                  The Data

                                                                                                                                  The dataset used to build a scatterplot is usually an array of objects.

                                                                                                                                  For each object, at least 2 properties are required: x and y. The value of x will control the position of the datapoint on the horizontal axis. The value of y will be linked with the vertical axis.

                                                                                                                                  const data = [
                                                                                                                                     {
                                                                                                                                       x: 2,
                                                                                                                                       y: 4
                                                                                                                                  @@ -232,4 +232,4 @@
                                                                                                                                   });

                                                                                                                                  Last but not least, some css needs to be added to customize the circle depending on if they are in default, .dimmed or :hover mode.

                                                                                                                                  Note that the filter: saturate(0) is a good way to dim unwanted circles. Also, playing with transition-delay and transition-duration adds to animate the transition is a nice touch you should consider. Check the code below the example to see the full css.

                                                                                                                                  The hover effect is another big topic in data visualization. A dedicated post will be published soon on the topic, feel free to subscribe to know when.

                                                                                                                                  Scatterplot inspiration

                                                                                                                                  If you're looking for inspiration to create your next Scatterplot, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                                  dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Scatterplot looks good!

                                                                                                                                  visit

                                                                                                                                  Real-life application

                                                                                                                                  Let's apply the concepts learned above to a real-life example.

                                                                                                                                  I like this scatterplot originally published on the data wrapper blog. It shows a strong correlation between vulnerability to climate change and CO2 emissions.


                                                                                                                                  The chart has several features that are interesting to reproduce fom a technical point of view:

                                                                                                                                  • Custom annotation: only a fraction of the country names are written
                                                                                                                                  • Hover effect: the hovered country is highlighted with a black stroke. After a short delay, countries of other groups are dimmed. Note that the effect is triggered once the mouse approaches the marker, no need to be perfectly on top.
                                                                                                                                  • Tooltip: highly customized and linked to the mouse position

                                                                                                                                  The countries with the highest vulnerability to climate change have the lowest CO2 emissions

                                                                                                                                  All countries sorted by their vulnerability and readiness to climate change. The size shows the CO2 emission per person in that country.

                                                                                                                                  High ReadinessLow ReadinessQatarBahrainU.S.Trinidad and TobagoCzech RepublicSingaporeNorwayIndiaSudanChadSomalia

                                                                                                                                  Reproduction of a chart originally published by Data Wrapper using react and d3.js.

                                                                                                                                  Variations

                                                                                                                                  The scatterplot examples described above are just the beginning of your journey. There is an infinite world of customization that is open to you. You can also explore related chart types that can be a good fit for your data:

                                                                                                                                  Click on the overview below to get details and code.


                                                                                                                                  gif of a scatterplot with voronoi diagram for closest point detection

                                                                                                                                  Closest point detection with Voronoi

                                                                                                                                  Using a voronoi diagram in the scatterplot background is a smart way to efficiently find the mouse closest point

                                                                                                                                  a scatterplot made with react and rendered in canvas

                                                                                                                                  Scatterplot in Canvas

                                                                                                                                  Learn how to render a scatterplot in canvas to improve performances

                                                                                                                                  Picture of a correlogram built with react and d3

                                                                                                                                  Basic correlogram

                                                                                                                                  Learn how to build a correlogram with react and d3

                                                                                                                                  Picture of a simple bubble plot with a legend made with react and d3.js

                                                                                                                                  Bubble plot

                                                                                                                                  Learn how to build a bubble plot with react and d3.js

                                                                                                                                  Picture of a hexbin chart made with React and d3.js

                                                                                                                                  Hexbin chart

                                                                                                                                  A hexbin chart split the figure in hexagons to show a 2d density

                                                                                                                                  Picture of a timeseries chart made with React and D3.js: scatterplot and line chart in use.

                                                                                                                                  Timeseries with moving average

                                                                                                                                  A scatterplot used for timeseries, with the moving average shown as a line chart on top.

                                                                                                                                  Useful links

                                                                                                                                  The following links have been useful to create this page:

                                                                                                                                  Contact

                                                                                                                                  👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                  Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                    -
                                                                                                                                    \ No newline at end of file +
                                                                                                                                    \ No newline at end of file diff --git a/shape-morphism-for-dataviz-with-react.html b/shape-morphism-for-dataviz-with-react.html index 91f35d7a..06100539 100644 --- a/shape-morphism-for-dataviz-with-react.html +++ b/shape-morphism-for-dataviz-with-react.html @@ -1,4 +1,4 @@ -Shape morphism for data visualization

                                                                                                                                    Shape morphism for data visualization


                                                                                                                                    Shape morphism is the art of transitioning between 2 shapes as smoothly as possible. This post explores how it can be useful for data visualization and how it can be done using React, d3.js, react-spring and flubber.

                                                                                                                                    This post is about shape morphism, which means animating the properties that define the actual shape of the elements.
                                                                                                                                    As always when talking about animation, it is good to recall this citation by Josh Comeau:

                                                                                                                                    Animation is like salt: too much of it spoils the dish

                                                                                                                                    Examples

                                                                                                                                    Here is a list of nifty viz examples using shape morphism to transition between several viz types


                                                                                                                                    Why

                                                                                                                                    In the field of data visualization shape morphism is mostly usefull to transition between 2 chart types. It is pretty hard to implement that kind of smooth transition so why should we even care?


                                                                                                                                    • Eye catching effect

                                                                                                                                    • Highlight the direct relationship between 2 charts. During the transition one can follow a specific item and understand it's the same.
                                                                                                                                    • Make sure that we're looking at the same dataset, but represented differently

                                                                                                                                    What are we trying to do

                                                                                                                                    Sometimes in dataviz we want to transition between 2 chart types, let's say between a pie chart and a barplot. This is pretty hard since the shapes used for those 2 charts are very different: arc versus rectangle.


                                                                                                                                    This is still possible thanks to a few libraries. This post suggests to use d3.js to build the start and end svg path, flubberto interpolate those path, react-spring for the animation and react for the rendering.


                                                                                                                                    This is the kind of thing we're gonna learn to build:


                                                                                                                                    Shape morphism on the web: a review

                                                                                                                                    I knew nothing about shape morphism 3 weeks ago. It took me a lot of effort to browse the web and find what the most appropriate tools are. To avoid you the hassle, here is a quick summary:


                                                                                                                                    • SMIL (Synchronized Multimedia Integration Language) is a feature introduced in firefox 4, allowing to follow a motion path. Basically it means you can use an animate element in your svg that will support shape morphism.
                                                                                                                                      Unfortunately, this feature is probably get deprecated soon. Furthermore, it supports transition only between shapes with the same number of nodes.
                                                                                                                                      DocCodePen.

                                                                                                                                    • pure CSS: Chrome has started to allow shape morphing through css. You can simply change the d attribute of a path in a css file and add sometransition to it. But chrome only and same number of nodes only.
                                                                                                                                      CodePen

                                                                                                                                    • greenSock MorphSvg plugin: a promising javascript library for shape morphism, widely cited on the internet. Supports shapes with different number of nodes. But it's not free and not open source.
                                                                                                                                      WebsiteCodePen

                                                                                                                                    • superformula is a mathematic formula that can be used to describe many complex shapes. Using 6 numbers as parameters, this formula can build many complex shapes. Interpolating between 2 shapes becomes easy: we just have to interpolate those numbers. Problem: it does not work with any shape and building a chart from this formula is thus impossible.
                                                                                                                                      Example

                                                                                                                                    • d3-interpolate is a d3 module that provides a variety of interpolation methods. It works for paths, even with different number of nodes. But when the shape 2 has more nodes than shape 1 it just adds some nodes to the end of the shape 1 path. This result in a bad visual effect.
                                                                                                                                      Doc

                                                                                                                                    • d3-interpolate-path is an open-source js library that adds an interpolator optimized for SVG path elements. It works very well for path including segments only, but from my experience less well for arcs.
                                                                                                                                      DocDemo

                                                                                                                                    • Vizzu is a library for animated data visualizations and data stories. It looks very promising for transition between chart types. But since it is a library, it means that customization is limited to the offered options.
                                                                                                                                      DocDemo

                                                                                                                                    None of the item of this list suits my need. We need an open source library capable of interpolating any path, even with different number of nodes..

                                                                                                                                    Shape interpolation with flubber

                                                                                                                                    flubber is an open source javascript library built by Noah Veltman. Unlike most of the shape morphism libraries it works very well to interpolate shapes that are completely different and don't have the same number of nodes.


                                                                                                                                    Let's start by creating 2 svg shapes

                                                                                                                                    const shape1 = "M10,140 L50,60 L90,140 Z"; // triangle
                                                                                                                                    +Shape morphism for data visualization

                                                                                                                                    Shape morphism for data visualization


                                                                                                                                    Shape morphism is the art of transitioning between 2 shapes as smoothly as possible. This post explores how it can be useful for data visualization and how it can be done using React, d3.js, react-spring and flubber.

                                                                                                                                    This post is about shape morphism, which means animating the properties that define the actual shape of the elements.
                                                                                                                                    As always when talking about animation, it is good to recall this citation by Josh Comeau:

                                                                                                                                    Animation is like salt: too much of it spoils the dish

                                                                                                                                    Examples

                                                                                                                                    Here is a list of nifty viz examples using shape morphism to transition between several viz types


                                                                                                                                    Why

                                                                                                                                    In the field of data visualization shape morphism is mostly usefull to transition between 2 chart types. It is pretty hard to implement that kind of smooth transition so why should we even care?


                                                                                                                                    • Eye catching effect

                                                                                                                                    • Highlight the direct relationship between 2 charts. During the transition one can follow a specific item and understand it's the same.
                                                                                                                                    • Make sure that we're looking at the same dataset, but represented differently

                                                                                                                                    What are we trying to do

                                                                                                                                    Sometimes in dataviz we want to transition between 2 chart types, let's say between a pie chart and a barplot. This is pretty hard since the shapes used for those 2 charts are very different: arc versus rectangle.


                                                                                                                                    This is still possible thanks to a few libraries. This post suggests to use d3.js to build the start and end svg path, flubberto interpolate those path, react-spring for the animation and react for the rendering.


                                                                                                                                    This is the kind of thing we're gonna learn to build:


                                                                                                                                    Shape morphism on the web: a review

                                                                                                                                    I knew nothing about shape morphism 3 weeks ago. It took me a lot of effort to browse the web and find what the most appropriate tools are. To avoid you the hassle, here is a quick summary:


                                                                                                                                    • SMIL (Synchronized Multimedia Integration Language) is a feature introduced in firefox 4, allowing to follow a motion path. Basically it means you can use an animate element in your svg that will support shape morphism.
                                                                                                                                      Unfortunately, this feature is probably get deprecated soon. Furthermore, it supports transition only between shapes with the same number of nodes.
                                                                                                                                      DocCodePen.

                                                                                                                                    • pure CSS: Chrome has started to allow shape morphing through css. You can simply change the d attribute of a path in a css file and add sometransition to it. But chrome only and same number of nodes only.
                                                                                                                                      CodePen

                                                                                                                                    • greenSock MorphSvg plugin: a promising javascript library for shape morphism, widely cited on the internet. Supports shapes with different number of nodes. But it's not free and not open source.
                                                                                                                                      WebsiteCodePen

                                                                                                                                    • superformula is a mathematic formula that can be used to describe many complex shapes. Using 6 numbers as parameters, this formula can build many complex shapes. Interpolating between 2 shapes becomes easy: we just have to interpolate those numbers. Problem: it does not work with any shape and building a chart from this formula is thus impossible.
                                                                                                                                      Example

                                                                                                                                    • d3-interpolate is a d3 module that provides a variety of interpolation methods. It works for paths, even with different number of nodes. But when the shape 2 has more nodes than shape 1 it just adds some nodes to the end of the shape 1 path. This result in a bad visual effect.
                                                                                                                                      Doc

                                                                                                                                    • d3-interpolate-path is an open-source js library that adds an interpolator optimized for SVG path elements. It works very well for path including segments only, but from my experience less well for arcs.
                                                                                                                                      DocDemo

                                                                                                                                    • Vizzu is a library for animated data visualizations and data stories. It looks very promising for transition between chart types. But since it is a library, it means that customization is limited to the offered options.
                                                                                                                                      DocDemo

                                                                                                                                    None of the item of this list suits my need. We need an open source library capable of interpolating any path, even with different number of nodes..

                                                                                                                                    Shape interpolation with flubber

                                                                                                                                    flubber is an open source javascript library built by Noah Veltman. Unlike most of the shape morphism libraries it works very well to interpolate shapes that are completely different and don't have the same number of nodes.


                                                                                                                                    Let's start by creating 2 svg shapes

                                                                                                                                    const shape1 = "M10,140 L50,60 L90,140 Z"; // triangle
                                                                                                                                     const shape2 = "M350,50 L400,83 L400,116 L350,150 L300,116 L300,83"; // polygon

                                                                                                                                    It's very straightforward to interpolate a y between the 2 of them thanks to the interpolate() function offlubber. This function expects 2 arguments: the starting shape and the ending shape:

                                                                                                                                    const interpolator = interpolate(shape1, shape2);

                                                                                                                                    interpolate() returns a function. This function accepts only 1 argument: a value between 0 (start) and 1 (end). It will return the interpolated shape for this progress.

                                                                                                                                    interpolator(0.2)
                                                                                                                                     // M110,58L113.25,62.825L116.5,67.65L119.75,72.475L123,77.3L126.25,82.125L129.5,86.95L.......Z

                                                                                                                                    Here is a visualization of the final result

                                                                                                                                    step: 0.0

                                                                                                                                    Switching from a triangle to a polygon using flubber for shape interpolation


                                                                                                                                    Awesome video by the Flubber creator: link

                                                                                                                                    Animating the transition with react spring

                                                                                                                                    Now that we know how to build an interpolated shape between a starting and an ending point, let's animated this transition using react-spring.

                                                                                                                                    The transition is now animated thanks to react-spring, a react library for spring animation.

                                                                                                                                    Pie chart to barplot transition

                                                                                                                                    I knew nothing about shape morphism 3 weeks ago. It took me a lot of effort to browse the web and find what the most appropriate tools are. To avoid you the hassle, here is a quick summary:

                                                                                                                                    Violin to boxplot transition

                                                                                                                                    I knew nothing about shape morphism 3 weeks ago. It took me a lot of effort to browse the web and find what the most appropriate tools are. To avoid you the hassle, here is a quick summary:

                                                                                                                                    How to smoothly transition between a boxplot and a violin plot. Math by d3.js, rendering using react, animation using react-spring and interpolation using flubber.


                                                                                                                                    Contact

                                                                                                                                    👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                    @@ -6,4 +6,4 @@

                                                                                                                                    Contact

                                                                                                                                    👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                      -
                                                                                                                                      \ No newline at end of file +
                                                                                                                                      \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index d7615cbe..4079fc5f 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,102 +1,102 @@ -https://www.react-graph-gallery.com2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/2d-density-plot2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/about2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/all2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/animation2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/arc-diagram2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/area-plot2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/articles2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/barplot2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/boxplot2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/bubble-map2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/bubble-plot2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/build-axis-with-react2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/cartogram2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/chord-diagram2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/choropleth-map2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/circular-barplot2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/circular-packing2024-09-27T08:23:25.615Zdaily0.7 -https://www.react-graph-gallery.com/connected-scatter-plot2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/connection-map2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/correlogram2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/axis/axis-variations2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/axis/axis-with-d32024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/axis/bottom-axis2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/axis/introduction2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/axis/margin-and-translation2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/hover-effect/css-descendant-selector2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/hover-effect/css-pseudo-class2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/hover-effect/internal-state2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/hover-effect/introduction2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/hover-effect/link-two-graphs2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/hover-effect/toggle-class-in-js2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/introduction/initial-setup2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/introduction/introduction-to-d32024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/introduction/introduction-to-react2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/introduction/js-dataviz-libraries2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/responsiveness/code-organization2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/responsiveness/common-pitfalls2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/responsiveness/introduction2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/responsiveness/use-dimension-hook2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/responsiveness/using-the-hook2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/scales/introduction2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/svg/introduction2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/svg/main-svg-elements2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/svg/path-element2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/course/svg/tips-and-tricks2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/cross-graph-highlight-interaction2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/dataset-transition2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/dendrogram2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/density-plot2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/donut2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/arc-diagram-vertical2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/barplot-data-transition-animation2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/barplot-stacked-horizontal2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/barplot-stacked-vertical2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/boxplot-horizontal2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/boxplot-jitter2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/circle-packing-with-d3-force2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/histogram-mirror2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/histogram-small-multiple2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/histogram-with-several-groups2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/line-chart-synchronized-cursors2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/network-diagram-with-colored-groups2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/population-pyramid2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/radar-chart-animation2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/scatterplot-basic-canvas2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/example/timeseries-moving-average2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/fix-canvas-blurry-dataviz2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/heatmap2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/hexbin-map2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/hierarchical-edge-bundling2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/histogram2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/interactivity2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/line-chart2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/lollipop-plot2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/map2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/network-chart2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/parallel-plot2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/pie-plot2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/radar-chart2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/react-d3-dataviz-course2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/react-dataviz-animation-with-react-spring2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/ridgeline2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/sankey-diagram2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/scatter-plot2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/shape-morphism-for-dataviz-with-react2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/stacked-area-plot2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/stacked-barplot-with-negative-values2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/streamchart2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/subscribe2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/timeseries2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/treemap2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/typescript-d3-axis2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/violin-plot2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/viz-from-the-future2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/voronoi2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/what-is-a-color2024-09-27T08:23:25.616Zdaily0.7 -https://www.react-graph-gallery.com/wordcloud2024-09-27T08:23:25.616Zdaily0.7 +https://www.react-graph-gallery.com2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/2d-density-plot2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/about2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/all2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/animation2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/arc-diagram2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/area-plot2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/articles2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/barplot2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/boxplot2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/bubble-map2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/bubble-plot2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/build-axis-with-react2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/cartogram2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/chord-diagram2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/choropleth-map2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/circular-barplot2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/circular-packing2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/connected-scatter-plot2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/connection-map2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/correlogram2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/axis/axis-variations2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/axis/axis-with-d32024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/axis/bottom-axis2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/axis/introduction2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/axis/margin-and-translation2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/hover-effect/css-descendant-selector2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/hover-effect/css-pseudo-class2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/hover-effect/internal-state2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/hover-effect/introduction2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/hover-effect/link-two-graphs2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/hover-effect/toggle-class-in-js2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/introduction/initial-setup2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/introduction/introduction-to-d32024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/introduction/introduction-to-react2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/introduction/js-dataviz-libraries2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/responsiveness/code-organization2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/responsiveness/common-pitfalls2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/responsiveness/introduction2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/responsiveness/use-dimension-hook2024-09-27T09:00:39.760Zdaily0.7 +https://www.react-graph-gallery.com/course/responsiveness/using-the-hook2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/course/scales/introduction2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/course/svg/introduction2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/course/svg/main-svg-elements2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/course/svg/path-element2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/course/svg/tips-and-tricks2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/cross-graph-highlight-interaction2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/dataset-transition2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/dendrogram2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/density-plot2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/donut2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/arc-diagram-vertical2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/barplot-data-transition-animation2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/barplot-stacked-horizontal2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/barplot-stacked-vertical2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/boxplot-horizontal2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/boxplot-jitter2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/circle-packing-with-d3-force2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/histogram-mirror2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/histogram-small-multiple2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/histogram-with-several-groups2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/line-chart-synchronized-cursors2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/network-diagram-with-colored-groups2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/population-pyramid2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/radar-chart-animation2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/scatterplot-basic-canvas2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/scatterplot-tooltip-with-voronoi-for-closest-point-detection2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/example/timeseries-moving-average2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/fix-canvas-blurry-dataviz2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/heatmap2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/hexbin-map2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/hierarchical-edge-bundling2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/histogram2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/interactivity2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/line-chart2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/lollipop-plot2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/map2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/network-chart2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/parallel-plot2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/pie-plot2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/radar-chart2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/react-d3-dataviz-course2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/react-dataviz-animation-with-react-spring2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/ridgeline2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/sankey-diagram2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/scatter-plot2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/shape-morphism-for-dataviz-with-react2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/stacked-area-plot2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/stacked-barplot-with-negative-values2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/streamchart2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/subscribe2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/timeseries2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/treemap2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/typescript-d3-axis2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/violin-plot2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/viz-from-the-future2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/voronoi2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/what-is-a-color2024-09-27T09:00:39.761Zdaily0.7 +https://www.react-graph-gallery.com/wordcloud2024-09-27T09:00:39.761Zdaily0.7 \ No newline at end of file diff --git a/stacked-area-plot.html b/stacked-area-plot.html index c502208e..cddf6768 100644 --- a/stacked-area-plot.html +++ b/stacked-area-plot.html @@ -1,4 +1,4 @@ -Stacked Area charts with React

                                                                                                                                      Stacked Area charts

                                                                                                                                      Dataviz logo representing a StackedArea chart.

                                                                                                                                      A stacked area chart is an evolution of an area chart used to display the evolution of several groups in a dataset. This section explains how to build it with d3.js and react. It focus on stacking, so make sure to read the area chart section first.

                                                                                                                                      Useful links

                                                                                                                                      The Data

                                                                                                                                      Most of the time the input dataset is an array where each item is an object.
                                                                                                                                      Each object provides information for a step on the X axis. It has a value like x that provides the exact position on the X axis. It then has several numeric values, one for each group of the dataset.


                                                                                                                                      Here is a minimal example:

                                                                                                                                      const data = [
                                                                                                                                      +Stacked Area charts with React

                                                                                                                                      Stacked Area charts

                                                                                                                                      Dataviz logo representing a StackedArea chart.

                                                                                                                                      A stacked area chart is an evolution of an area chart used to display the evolution of several groups in a dataset. This section explains how to build it with d3.js and react. It focus on stacking, so make sure to read the area chart section first.

                                                                                                                                      Useful links

                                                                                                                                      The Data

                                                                                                                                      Most of the time the input dataset is an array where each item is an object.
                                                                                                                                      Each object provides information for a step on the X axis. It has a value like x that provides the exact position on the X axis. It then has several numeric values, one for each group of the dataset.


                                                                                                                                      Here is a minimal example:

                                                                                                                                      const data = [
                                                                                                                                         {
                                                                                                                                           x: 1,
                                                                                                                                           groupA: 38,
                                                                                                                                      @@ -111,4 +111,4 @@
                                                                                                                                       }

                                                                                                                                      I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                                      Stacked Area inspiration

                                                                                                                                      If you're looking for inspiration to create your next Stacked Area, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                                      dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Stacked Area looks good!

                                                                                                                                      visit

                                                                                                                                      Offset and Curve types

                                                                                                                                      Stacked area charts can easily be customized to use other offset and smoothing algorithm. This process can be used to create streamgraphs which are a varation of the stacked area graph.

                                                                                                                                      The offset type controls how the data are stacked. You can read about the offset options available in the official documentation or play with the little example below.

                                                                                                                                      The curve type controls how the smoothing of each shape is made. There are a myriad of options described in the official documentation.

                                                                                                                                      Offset typeCurve type
                                                                                                                                      246810

                                                                                                                                      Try d3.js various options to offset the data and smooth shapes. See a smooth transition between options.

                                                                                                                                      The animation uses react-spring to run. I'll publish a full blogpost on the topic soon!

                                                                                                                                      Get notified


                                                                                                                                      Contact

                                                                                                                                      👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                        -
                                                                                                                                        \ No newline at end of file +
                                                                                                                                        \ No newline at end of file diff --git a/stacked-barplot-with-negative-values.html b/stacked-barplot-with-negative-values.html index 14ac9bd1..2e6f9dae 100644 --- a/stacked-barplot-with-negative-values.html +++ b/stacked-barplot-with-negative-values.html @@ -1,4 +1,4 @@ -Dealing with negative values on a stacked barplot

                                                                                                                                        Dealing with negative values on a stacked barplot


                                                                                                                                        Drawing a stacked barplot sounds like pretty basic task for somebody into dataviz. But it gets surprisingly tricky once the dataset includes negative values.

                                                                                                                                        This post explains how to deal with it, suggesting several options coming together with some reproducible code examples.

                                                                                                                                        🍔 Regular stacked barplot with positive values

                                                                                                                                        Let's consider a company that has 3 employees: a, b and c. Each month those employees sell umbrellas and make money.

                                                                                                                                        In January, they made 1, 1 and 2 dollars respectively. It's pretty easy to represent those sales as a stacked barplot!

                                                                                                                                        There is even a bonus! The total height of those bars is 4. So is the value of the stack on the Y axis. We now know what's the total revenue of the company 🎉!

                                                                                                                                        explanation of a stacked barplot wit positive values

                                                                                                                                        Stacking positive values is straightforward


                                                                                                                                        Now let's follow the same process for the 12 months of the year. That makes a stacked area barplot built with react and d3.js. If you need explanations for the code, please refer to the d3.js gallery or to the barplot section of the react gallery.


                                                                                                                                        A stacked area chart with positive values only. Built with react and d3.js


                                                                                                                                        That's the end of the easy part. Now, let's say that sometimes employees spend more money than what they make.

                                                                                                                                        We now have some negative values in the dataset 😳. How can we deal with it?

                                                                                                                                        1️⃣ Stacked barplot with negative values: the diverging strategy

                                                                                                                                        We are in January but this time, employee A lost 1$! 😥

                                                                                                                                        To represent this on the stack, we can add all the positive values on top of the chart, and all the negative ones below the 0 axis.

                                                                                                                                        It is still very easy to see how much each employee made in a glimpse!

                                                                                                                                        However, it is now impossible to know what's the company revenue! Indeed, the total height of the bars is 4, the value on the y axis is 3, but the real revenue is 1 + 2 - 1 = 2!

                                                                                                                                        shema of a stacked barplot with the diverging strategy for stacking

                                                                                                                                        Stacking with negative values with all negative values below the 0 axis


                                                                                                                                        Using almost the same code we can build the stacked barplot including those negative values. Note that when stacking the data with the stack() function of d3, the specific stackOffsetDiverging offset parameter must be passed, handling all the work for us (doc).


                                                                                                                                        With the diverging strategy, all negative values are located under the 0 baseline.


                                                                                                                                        Let's recap the pros and cons of this diverging option:

                                                                                                                                        Pros

                                                                                                                                        • Easy to read the value of each item
                                                                                                                                        • Obvious what's negative and what's positive

                                                                                                                                        Cons

                                                                                                                                        • Impossible to know the total value of each stack
                                                                                                                                        • A series can jump from the bottom to the top of the chart and is thus hard to follow

                                                                                                                                        2️⃣ Stacked barplot with negative values: the overlapping strategy

                                                                                                                                        Another strategy can be applied to stack the items including negative values.

                                                                                                                                        Items can be added one by one, with rectangles going up when values are positive and going down when values are negative.

                                                                                                                                        stacked barplot with overlapping item does not work well

                                                                                                                                        Stacking items by overlapping the items on top of each other.


                                                                                                                                        It's important to understand that here, the item order is important. We will get very different results depending on the order since not all groups are visible.


                                                                                                                                        With the overlapping strategy items are drawn successively, going up and down and overlapping if necessary


                                                                                                                                        Let's recap the pros and cons of this diverging option:

                                                                                                                                        Pros

                                                                                                                                        • Depending on the group order, the Y value can reflect the sum of the items. But it's not guarantee.

                                                                                                                                        Cons

                                                                                                                                        • Groups overlap each other. Information is hidden. Chart is unreadable

                                                                                                                                        Conclusion

                                                                                                                                        In my opinion the first option (diverging) makes much more sense than the second one (overlapping). The cons are very limited:

                                                                                                                                        • It is true that the net total value is not available. But if that's what interests you, you don't have to split the dataset by subgroups, just create a line chart with a single line!
                                                                                                                                        • Having a group flipping from top to bottom is indeed annoying. However, the hover effect that is included allows to quickly see what happens for a specific group.

                                                                                                                                        It's also important to note that most dataviz tools choosed this approach. Here is an example using the same dataset using the ggplot2library (left) and data wrapper (right).


                                                                                                                                        stacked barplot with R and ggplot2stacked barplot with data wrapper

                                                                                                                                        Same dataset that includes negative values plotted with ggplot2 (left) and data wrapper (right)


                                                                                                                                        Last but not least, I really like this example by chartio that fixes the non available total issue by adding a line on top of the stacked barchart to show the total:


                                                                                                                                        stacked barplot with chartio

                                                                                                                                        Chartio displays the total of each timestamp using a line chart on top of the stacked items.




                                                                                                                                        Contact

                                                                                                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                        +Dealing with negative values on a stacked barplot

                                                                                                                                        Dealing with negative values on a stacked barplot


                                                                                                                                        Drawing a stacked barplot sounds like pretty basic task for somebody into dataviz. But it gets surprisingly tricky once the dataset includes negative values.

                                                                                                                                        This post explains how to deal with it, suggesting several options coming together with some reproducible code examples.

                                                                                                                                        🍔 Regular stacked barplot with positive values

                                                                                                                                        Let's consider a company that has 3 employees: a, b and c. Each month those employees sell umbrellas and make money.

                                                                                                                                        In January, they made 1, 1 and 2 dollars respectively. It's pretty easy to represent those sales as a stacked barplot!

                                                                                                                                        There is even a bonus! The total height of those bars is 4. So is the value of the stack on the Y axis. We now know what's the total revenue of the company 🎉!

                                                                                                                                        explanation of a stacked barplot wit positive values

                                                                                                                                        Stacking positive values is straightforward


                                                                                                                                        Now let's follow the same process for the 12 months of the year. That makes a stacked area barplot built with react and d3.js. If you need explanations for the code, please refer to the d3.js gallery or to the barplot section of the react gallery.


                                                                                                                                        A stacked area chart with positive values only. Built with react and d3.js


                                                                                                                                        That's the end of the easy part. Now, let's say that sometimes employees spend more money than what they make.

                                                                                                                                        We now have some negative values in the dataset 😳. How can we deal with it?

                                                                                                                                        1️⃣ Stacked barplot with negative values: the diverging strategy

                                                                                                                                        We are in January but this time, employee A lost 1$! 😥

                                                                                                                                        To represent this on the stack, we can add all the positive values on top of the chart, and all the negative ones below the 0 axis.

                                                                                                                                        It is still very easy to see how much each employee made in a glimpse!

                                                                                                                                        However, it is now impossible to know what's the company revenue! Indeed, the total height of the bars is 4, the value on the y axis is 3, but the real revenue is 1 + 2 - 1 = 2!

                                                                                                                                        shema of a stacked barplot with the diverging strategy for stacking

                                                                                                                                        Stacking with negative values with all negative values below the 0 axis


                                                                                                                                        Using almost the same code we can build the stacked barplot including those negative values. Note that when stacking the data with the stack() function of d3, the specific stackOffsetDiverging offset parameter must be passed, handling all the work for us (doc).


                                                                                                                                        With the diverging strategy, all negative values are located under the 0 baseline.


                                                                                                                                        Let's recap the pros and cons of this diverging option:

                                                                                                                                        Pros

                                                                                                                                        • Easy to read the value of each item
                                                                                                                                        • Obvious what's negative and what's positive

                                                                                                                                        Cons

                                                                                                                                        • Impossible to know the total value of each stack
                                                                                                                                        • A series can jump from the bottom to the top of the chart and is thus hard to follow

                                                                                                                                        2️⃣ Stacked barplot with negative values: the overlapping strategy

                                                                                                                                        Another strategy can be applied to stack the items including negative values.

                                                                                                                                        Items can be added one by one, with rectangles going up when values are positive and going down when values are negative.

                                                                                                                                        stacked barplot with overlapping item does not work well

                                                                                                                                        Stacking items by overlapping the items on top of each other.


                                                                                                                                        It's important to understand that here, the item order is important. We will get very different results depending on the order since not all groups are visible.


                                                                                                                                        With the overlapping strategy items are drawn successively, going up and down and overlapping if necessary


                                                                                                                                        Let's recap the pros and cons of this diverging option:

                                                                                                                                        Pros

                                                                                                                                        • Depending on the group order, the Y value can reflect the sum of the items. But it's not guarantee.

                                                                                                                                        Cons

                                                                                                                                        • Groups overlap each other. Information is hidden. Chart is unreadable

                                                                                                                                        Conclusion

                                                                                                                                        In my opinion the first option (diverging) makes much more sense than the second one (overlapping). The cons are very limited:

                                                                                                                                        • It is true that the net total value is not available. But if that's what interests you, you don't have to split the dataset by subgroups, just create a line chart with a single line!
                                                                                                                                        • Having a group flipping from top to bottom is indeed annoying. However, the hover effect that is included allows to quickly see what happens for a specific group.

                                                                                                                                        It's also important to note that most dataviz tools choosed this approach. Here is an example using the same dataset using the ggplot2library (left) and data wrapper (right).


                                                                                                                                        stacked barplot with R and ggplot2stacked barplot with data wrapper

                                                                                                                                        Same dataset that includes negative values plotted with ggplot2 (left) and data wrapper (right)


                                                                                                                                        Last but not least, I really like this example by chartio that fixes the non available total issue by adding a line on top of the stacked barchart to show the total:


                                                                                                                                        stacked barplot with chartio

                                                                                                                                        Chartio displays the total of each timestamp using a line chart on top of the stacked items.




                                                                                                                                        Contact

                                                                                                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                          -
                                                                                                                                          \ No newline at end of file +
                                                                                                                                          \ No newline at end of file diff --git a/streamchart.html b/streamchart.html index cf5a79c7..4d78b256 100644 --- a/streamchart.html +++ b/streamchart.html @@ -1,4 +1,4 @@ -Streamchart with React

                                                                                                                                          Streamchart

                                                                                                                                          Dataviz logo representing a Stream chart.

                                                                                                                                          A streamgraph is a variation of the more common stacked area chart. It rounds edges and displays areas around the central axis which gives a nice impression of flow.

                                                                                                                                          This section explains how to stack and smooth the data with d3.js, and render the shapes with react. It starts from the basic and goes until necessary customization like tooltips, hover effect, legend and annotation. Examples always come with editable sandboxes.

                                                                                                                                          Useful links

                                                                                                                                          The Data

                                                                                                                                          Most of the time the input dataset is an array where each item is an object.

                                                                                                                                          Each object provides information for a step on the X axis. It has a value like x or date that provides the exact position on the X axis. Then it has several numeric values, one for each group of the dataset.

                                                                                                                                          Here is a minimal example:

                                                                                                                                          const data = [
                                                                                                                                          +Streamchart with React

                                                                                                                                          Streamchart

                                                                                                                                          Dataviz logo representing a Stream chart.

                                                                                                                                          A streamgraph is a variation of the more common stacked area chart. It rounds edges and displays areas around the central axis which gives a nice impression of flow.

                                                                                                                                          This section explains how to stack and smooth the data with d3.js, and render the shapes with react. It starts from the basic and goes until necessary customization like tooltips, hover effect, legend and annotation. Examples always come with editable sandboxes.

                                                                                                                                          Useful links

                                                                                                                                          The Data

                                                                                                                                          Most of the time the input dataset is an array where each item is an object.

                                                                                                                                          Each object provides information for a step on the X axis. It has a value like x or date that provides the exact position on the X axis. Then it has several numeric values, one for each group of the dataset.

                                                                                                                                          Here is a minimal example:

                                                                                                                                          const data = [
                                                                                                                                             {
                                                                                                                                               x: 1,
                                                                                                                                               groupA: 38,
                                                                                                                                          @@ -100,4 +100,4 @@
                                                                                                                                           }

                                                                                                                                          I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                                          Hover effect

                                                                                                                                          It is pretty hard to follow the evolution of a specific group on a streamgraph.

                                                                                                                                          It is common to add an hover effect to the figure: hovering over a group will highlight it, making it easier to follow its evolution. Try it on the graph below:

                                                                                                                                          246810

                                                                                                                                          StreamGraph with hover effect that highlights a specific series

                                                                                                                                          There are various strategies to implement such an hover effect.

                                                                                                                                          Here, I suggest to do everything in css using pseudo classes, and targetting svg elements only. Basically, everything in the svg container will be dimmed (lower opacity and saturation) when the mouse goes over the chart. But the specific shape that is hovered over will keep its full opacity thanks to a more specific css selector.

                                                                                                                                          Hover effect is a big topic and I will post more about it soon!

                                                                                                                                          Know when

                                                                                                                                          Streamgraph inspiration

                                                                                                                                          If you're looking for inspiration to create your next Streamgraph, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                                          dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Streamgraph looks good!

                                                                                                                                          visit

                                                                                                                                          Streamgraph algorithm with transition

                                                                                                                                          Our streamgraph is renderer using a set of path. The d attribute of those paths provides the boundary coordinates of those paths.

                                                                                                                                          When a prop of the StreamGraph component updates, we might want to update the paths to represent the latest state of our application. It can be an update of the dataset, or an update of the function used to stack the data or smooth the area as below.

                                                                                                                                          It is possible to smoothly animate this transition thanks to react-spring.

                                                                                                                                          Offset typeCurve type
                                                                                                                                          246810

                                                                                                                                          Try d3.js various options to offset the data and smooth shapes. See a smooth transition between options.

                                                                                                                                          The animation suggested above is a bit tricky to implement. Indeed, we need to transition from paths that do not have the same number of edges. It is possible thanks to a library called flubber but definitely deserves its own blogpost.

                                                                                                                                          I'll publish a full blogpost on the topic soon!

                                                                                                                                          Get notified
                                                                                                                                          ToDofind why flubber does some weird interpolation in some cases

                                                                                                                                          Application

                                                                                                                                          The following chart is a real-life application of a streamgraph. It shows the evolution if the number of page-views for 5 tech websites in the last 7 years. My goal was to assess if the rise of chat-GPT had an impact on it.

                                                                                                                                          This interactive chart has several interesting features:

                                                                                                                                          • slider: you can control the displayed time-frame thanks to a slider.
                                                                                                                                          • inline legend: label of each series are written inline. A background proportional to their value provides additional insight.
                                                                                                                                          • hover effect: legend will be updated with precise values at the hovered timestamp.

                                                                                                                                          A customized streamgraph built with React and D3.js. It has inline legends, slider to control timeframe, hover effect and more.

                                                                                                                                          Contact

                                                                                                                                          👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                            -
                                                                                                                                            \ No newline at end of file +
                                                                                                                                            \ No newline at end of file diff --git a/subscribe.html b/subscribe.html index 0913491d..26acf94c 100644 --- a/subscribe.html +++ b/subscribe.html @@ -1,7 +1,7 @@ -Subscribe

                                                                                                                                            Want more graph examples?


                                                                                                                                            The react graph gallery is a project that just started! If you want to know when a new section gets released, follow me on twitter or subscribe below!

                                                                                                                                            +Subscribe

                                                                                                                                            Want more graph examples?


                                                                                                                                            The react graph gallery is a project that just started! If you want to know when a new section gets released, follow me on twitter or subscribe below!

                                                                                                                                              Contact

                                                                                                                                              👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                -
                                                                                                                                                \ No newline at end of file +
                                                                                                                                                \ No newline at end of file diff --git a/timeseries.html b/timeseries.html index d58aa030..987c7459 100644 --- a/timeseries.html +++ b/timeseries.html @@ -1,4 +1,4 @@ -Timeseries| The React Graph Gallery

                                                                                                                                                Timeseries

                                                                                                                                                Dataviz logo representing a Time chart.

                                                                                                                                                This section does not target a specific chart type, even though timeseries are often represented as line charts or area charts.

                                                                                                                                                Instead, it provides a tips and tricks to deal with charts that represent the evolution in time of a numeric variable. For instance, it provides hints on how to deal with dates, how to pan on a chart and more

                                                                                                                                                Useful links

                                                                                                                                                Useful chart types

                                                                                                                                                This page is not about a specific chart type. Instead it provides hints on how to deal with time.

                                                                                                                                                Check the graph sections that are used to visualize timeseries below if there is a specific chart type you want to make.


                                                                                                                                                Picture of a simple heatmap made with react and d3.js

                                                                                                                                                Basic heatmap

                                                                                                                                                Most basic heatmap

                                                                                                                                                Picture of a very simple line chart made with react and d3

                                                                                                                                                Most basic line chart

                                                                                                                                                The most basic line chart one can make using d3 and react

                                                                                                                                                Picture of a basic streamgraph made using Reacrt and d3.js

                                                                                                                                                Basic Streamgraph

                                                                                                                                                Most basic streamgraph one can build using d3 and react

                                                                                                                                                The Date format

                                                                                                                                                The first struggle when dealing with timeseries is to work with the javascript Date format. A Date represents a single moment in time and is usually stored as a string in the input dataset.

                                                                                                                                                Here is an FAQ about the Date format. I constantly forget how this works and come back here for reference. Note that it heavily relies on the d3-time-format module that provides great helpers.

                                                                                                                                                Transform a string into a date

                                                                                                                                                In your dataset, the date of each data point is probably stored as a string, like 2015-06-01 for instance.

                                                                                                                                                In order to manipulate and plot those dates, you need to transform it into a javascript date format.

                                                                                                                                                // import the timeParse function from d3
                                                                                                                                                +Timeseries| The React Graph Gallery

                                                                                                                                                Timeseries

                                                                                                                                                Dataviz logo representing a Time chart.

                                                                                                                                                This section does not target a specific chart type, even though timeseries are often represented as line charts or area charts.

                                                                                                                                                Instead, it provides a tips and tricks to deal with charts that represent the evolution in time of a numeric variable. For instance, it provides hints on how to deal with dates, how to pan on a chart and more

                                                                                                                                                Useful links

                                                                                                                                                Useful chart types

                                                                                                                                                This page is not about a specific chart type. Instead it provides hints on how to deal with time.

                                                                                                                                                Check the graph sections that are used to visualize timeseries below if there is a specific chart type you want to make.


                                                                                                                                                Picture of a simple heatmap made with react and d3.js

                                                                                                                                                Basic heatmap

                                                                                                                                                Most basic heatmap

                                                                                                                                                Picture of a very simple line chart made with react and d3

                                                                                                                                                Most basic line chart

                                                                                                                                                The most basic line chart one can make using d3 and react

                                                                                                                                                Picture of a basic streamgraph made using Reacrt and d3.js

                                                                                                                                                Basic Streamgraph

                                                                                                                                                Most basic streamgraph one can build using d3 and react

                                                                                                                                                The Date format

                                                                                                                                                The first struggle when dealing with timeseries is to work with the javascript Date format. A Date represents a single moment in time and is usually stored as a string in the input dataset.

                                                                                                                                                Here is an FAQ about the Date format. I constantly forget how this works and come back here for reference. Note that it heavily relies on the d3-time-format module that provides great helpers.

                                                                                                                                                Transform a string into a date

                                                                                                                                                In your dataset, the date of each data point is probably stored as a string, like 2015-06-01 for instance.

                                                                                                                                                In order to manipulate and plot those dates, you need to transform it into a javascript date format.

                                                                                                                                                // import the timeParse function from d3
                                                                                                                                                 import { timeParse } from "d3";
                                                                                                                                                 
                                                                                                                                                 // create a time parser function that works for our time format
                                                                                                                                                @@ -41,4 +41,4 @@
                                                                                                                                                   .range([0, width]);

                                                                                                                                                Following this code block xScale is a function. You give it a Date, it returns a position in pixels

                                                                                                                                                You can finally use this scale to draw the X axis using your favorite method:

                                                                                                                                                • create your own react component
                                                                                                                                                • call d3.axisBottom() in a useEffect

                                                                                                                                                I'm preparing a full post on axes with d3 and react, subscribe to the newsletter if you want to be notified when it's out!

                                                                                                                                                More on axes

                                                                                                                                                A basic time axis build with d3.js and react.

                                                                                                                                                d3 is very smart at picking the right label format. If you're dealing with a very long period of time (years), it will display years. If you're dealing with a month, it will display days. And so on. It is very convenient. The logic controlling this formatting is provided here.

                                                                                                                                                Note that you can customize how dates are formatted along the X axis thanks to the tickFormat function.

                                                                                                                                                Line chart application

                                                                                                                                                If you already understood the content of the line chart section of the gallery, you just have to use a scaleTime instead of a scaleLinear and that's it, you have your first timeseries visualization. 😋

                                                                                                                                                Line chart section

                                                                                                                                                A first timeseries line chart made thanks to the scaleTime function of d3.

                                                                                                                                                Synchronized cursor

                                                                                                                                                Another pretty common task when dealing with timeseries is to add a synchronized cursor on all charts.

                                                                                                                                                This makes the dashboard more insightful: hovering over an interesting part of a chart reveals where the timestamp is localized on other charts instantly.

                                                                                                                                                The implementation required to build a shared state between all charts of the webpage. Hovering a specific chart will update this state and thus update all other plots. This process is extensively described in this synchronized cursor for timeseries post.

                                                                                                                                                Read full post

                                                                                                                                                Hover over a chart to see a cursor on both of them, easing the time comparison.

                                                                                                                                                On top of the generic use-cases presented above, here is a gallery of chart examples involving timeseries visualization:


                                                                                                                                                Picture of a timeseries chart made with React and D3.js: scatterplot and line chart in use.

                                                                                                                                                Timeseries with moving average

                                                                                                                                                A scatterplot used for timeseries, with the moving average shown as a line chart on top.

                                                                                                                                                Contact

                                                                                                                                                👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                  -
                                                                                                                                                  \ No newline at end of file +
                                                                                                                                                  \ No newline at end of file diff --git a/treemap.html b/treemap.html index 3b4f4463..88c79b4a 100644 --- a/treemap.html +++ b/treemap.html @@ -1,4 +1,4 @@ -Treemap with React

                                                                                                                                                  Treemap

                                                                                                                                                  Dataviz logo representing a Tree chart.

                                                                                                                                                  A treemap displays a hierarchical dataset (a tree) as a set of rectangles. Rectangle sizes are proportional to their numeric value.

                                                                                                                                                  d3.js has some handy functions to compute the rectangle positions. React becomes useful to render those rectangles, animate transitions and more. This post explains how to make those 2 tools work together to build a Treemap component.

                                                                                                                                                  Useful links

                                                                                                                                                  The Data

                                                                                                                                                  The dataset describes a hierarchy using a recursive structure. Each item in this structure is called a node, the lowest nodes of the hierarchy being called leaves.

                                                                                                                                                  The dataset is an object that has at least 3 properties: name, value and children.children is an array of nodes that have this structure too.


                                                                                                                                                  Here is a minimal example of the data structure:

                                                                                                                                                  const data = {
                                                                                                                                                  +Treemap with React

                                                                                                                                                  Treemap

                                                                                                                                                  Dataviz logo representing a Tree chart.

                                                                                                                                                  A treemap displays a hierarchical dataset (a tree) as a set of rectangles. Rectangle sizes are proportional to their numeric value.

                                                                                                                                                  d3.js has some handy functions to compute the rectangle positions. React becomes useful to render those rectangles, animate transitions and more. This post explains how to make those 2 tools work together to build a Treemap component.

                                                                                                                                                  Useful links

                                                                                                                                                  The Data

                                                                                                                                                  The dataset describes a hierarchy using a recursive structure. Each item in this structure is called a node, the lowest nodes of the hierarchy being called leaves.

                                                                                                                                                  The dataset is an object that has at least 3 properties: name, value and children.children is an array of nodes that have this structure too.


                                                                                                                                                  Here is a minimal example of the data structure:

                                                                                                                                                  const data = {
                                                                                                                                                     type: 'node',
                                                                                                                                                     name: "boss",
                                                                                                                                                     value: 2300,
                                                                                                                                                  @@ -39,4 +39,4 @@
                                                                                                                                                   }
                                                                                                                                                  Mark90Robert12Emily34Marion53Nicolas98Malki22Djé12Mélanie45Einstein76

                                                                                                                                                  Treemap with 2 levels of hierarchy and a color scale, made with react and d3.js.

                                                                                                                                                  Hover effect

                                                                                                                                                  Adding a hover effect to your treemap is a nice polish detail. Here I suggest to highlight the slice that is hovered over by dimming all the other slices.

                                                                                                                                                  There are several strategies available to implement such an effect. One can rely on css pseudo classes only, or add a css class using javascript and the onMouseEnter event. It's also possible to rely on an animation library like react-spring.

                                                                                                                                                  I'm preparing a full section on the topic. You can subscribe to my dataviz-universe newsletter to know when it will be ready. Meanwhile, there is a code sandbox waiting for you below to reveal the code of this example.

                                                                                                                                                  Subscribe
                                                                                                                                                  Mark90Robert12Emily34Marion53Nicolas98Malki22Djé12Mélanie45Einstein76

                                                                                                                                                  Hover over a group on the treemap to see the other groups fading.




                                                                                                                                                  Contact

                                                                                                                                                  👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                  Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                    -
                                                                                                                                                    \ No newline at end of file +
                                                                                                                                                    \ No newline at end of file diff --git a/typescript-d3-axis.html b/typescript-d3-axis.html index 93505f89..ae0ff269 100644 --- a/typescript-d3-axis.html +++ b/typescript-d3-axis.html @@ -1,4 +1,4 @@ -Dealing with d3 axis in a typescript environment

                                                                                                                                                    D3 axis and typescript

                                                                                                                                                    Dataviz logo representing a Lollipop chart.

                                                                                                                                                    What is typescript and why it is awesome to use it. How are d3 functions typed.

                                                                                                                                                    A few examples on how it works.

                                                                                                                                                    Useful links

                                                                                                                                                    Most basic linear axis

                                                                                                                                                    A graph axis is based on a scale. But what is a scale? This is how thed3-scale module describes it:

                                                                                                                                                    Scales are a convenient abstraction for a fundamental task in visualization: mapping a dimension of abstract data to a visual representation

                                                                                                                                                    So basically a scale is a function. You provide it with an input like the value of a data point, and it returns another value like a position in pixel.

                                                                                                                                                    Here is a very basic implementation of a scale using the scaleLinear function of d3.

                                                                                                                                                    const xScale = d3.scaleLinear()
                                                                                                                                                    +Dealing with d3 axis in a typescript environment

                                                                                                                                                    D3 axis and typescript

                                                                                                                                                    Dataviz logo representing a Lollipop chart.

                                                                                                                                                    What is typescript and why it is awesome to use it. How are d3 functions typed.

                                                                                                                                                    A few examples on how it works.

                                                                                                                                                    Useful links

                                                                                                                                                    Most basic linear axis

                                                                                                                                                    A graph axis is based on a scale. But what is a scale? This is how thed3-scale module describes it:

                                                                                                                                                    Scales are a convenient abstraction for a fundamental task in visualization: mapping a dimension of abstract data to a visual representation

                                                                                                                                                    So basically a scale is a function. You provide it with an input like the value of a data point, and it returns another value like a position in pixel.

                                                                                                                                                    Here is a very basic implementation of a scale using the scaleLinear function of d3.

                                                                                                                                                    const xScale = d3.scaleLinear()
                                                                                                                                                       .domain([0, 10]) // data can go from 0 to 10
                                                                                                                                                       .range([0, width]); // it will result in a value that goes from 0 to width
                                                                                                                                                     
                                                                                                                                                    @@ -23,4 +23,4 @@
                                                                                                                                                       .range(COLORS);

                                                                                                                                                    You can see how scaleOrdinal type implementation

                                                                                                                                                    Contact

                                                                                                                                                    👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                      -
                                                                                                                                                      \ No newline at end of file +
                                                                                                                                                      \ No newline at end of file diff --git a/violin-plot.html b/violin-plot.html index d0f909da..0aca5198 100644 --- a/violin-plot.html +++ b/violin-plot.html @@ -1,4 +1,4 @@ -Violin plot with React

                                                                                                                                                      Violin plot

                                                                                                                                                      Dataviz logo representing a Violin chart.

                                                                                                                                                      A violin chart displays the distribution of a numeric variable, often for several groups of a dataset. This page is a step-by-step guide on how to build your own violin component for the web, using React and D3.js.

                                                                                                                                                      It starts by describing how the data should be organized and how to initialize the violin component. D3.js is then used to split the data in buckets thanks to the bin() function. It then adds smoothing to it with curve(). React is finally used to render the violin using a SVG path.

                                                                                                                                                      Useful links

                                                                                                                                                      The Data 💾

                                                                                                                                                      The dataset used to build a violin chart is usually an array of object. For each object, a name property provides the group name, and a value property provides the numeric value. It looks like this:

                                                                                                                                                      const data = [
                                                                                                                                                      +Violin plot with React

                                                                                                                                                      Violin plot

                                                                                                                                                      Dataviz logo representing a Violin chart.

                                                                                                                                                      A violin chart displays the distribution of a numeric variable, often for several groups of a dataset. This page is a step-by-step guide on how to build your own violin component for the web, using React and D3.js.

                                                                                                                                                      It starts by describing how the data should be organized and how to initialize the violin component. D3.js is then used to split the data in buckets thanks to the bin() function. It then adds smoothing to it with curve(). React is finally used to render the violin using a SVG path.

                                                                                                                                                      Useful links

                                                                                                                                                      The Data 💾

                                                                                                                                                      The dataset used to build a violin chart is usually an array of object. For each object, a name property provides the group name, and a value property provides the numeric value. It looks like this:

                                                                                                                                                      const data = [
                                                                                                                                                         { name: "A", value: 10.7577 },
                                                                                                                                                         { name: "A", value: 19.9273 },
                                                                                                                                                         { name: "B", value: 13.8917 },
                                                                                                                                                      @@ -144,7 +144,7 @@
                                                                                                                                                         }, []);
                                                                                                                                                       
                                                                                                                                                         return dimensions;
                                                                                                                                                      -}

                                                                                                                                                      I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                                                      Violin inspiration

                                                                                                                                                      If you're looking for inspiration to create your next Violin, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                                                      dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Violin looks good!

                                                                                                                                                      visit

                                                                                                                                                      Effect of the bucket size

                                                                                                                                                      It's important to understand that under the hood, a violin shape is nothing else than a smoothed histogram. You can use the sentence below the following chart to switch from one to the other and understand the tight connection.

                                                                                                                                                      As a result the violin plot suffers the same flaw as the histogram: its shape highly depends on the number of buckets used for the computation. Use the slider to see the impact of the target bucket number on the violin shape.

                                                                                                                                                      Each violin shape based on approx. 5 buckets
                                                                                                                                                      -10-505101520253035ABCD
                                                                                                                                                      You can use smoothing or steps.

                                                                                                                                                      Interactive violin plot: try to toggle smoothing and change the number of buckets in use.

                                                                                                                                                      Note: the requested number of buckets is a target. The bin() function of d3 will create smart buckets around this value.

                                                                                                                                                      Comparison with a boxplot

                                                                                                                                                      The boxplot is an alternative to represent the exact same kind of dataset. You can visit the boxplot section of the gallery or play with the interactive example below to understand how those 2 options behave on the same dataset.

                                                                                                                                                      Use the slider to switch from the violin to the box. Play with the sentence below the chart to toggle smoothing on the violin.

                                                                                                                                                      -10-505101520253035ABCD
                                                                                                                                                      You can use smoothing or steps.

                                                                                                                                                      Compare how violins and boxplots look like for the same dataset.

                                                                                                                                                      Animation

                                                                                                                                                      Animating the transition between 2 datasets, or from/to another chart type is hard, because the violin plot is based on SVG path. It is doable though and I'm working on a specific post that will be released soon.

                                                                                                                                                      schema explaining how histogram buckets are created from the original dataset

                                                                                                                                                      Using shape morphism to transition between a boxplot and a violin plot. Blog post coming soon!

                                                                                                                                                      If you're interested in this topic, feel free to subscribe to the newsletter to be informed when this post is available!

                                                                                                                                                      Contact

                                                                                                                                                      👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                      +}

                                                                                                                                                      I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                                                      Violin inspiration

                                                                                                                                                      If you're looking for inspiration to create your next Violin, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                                                      dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Violin looks good!

                                                                                                                                                      visit

                                                                                                                                                      Effect of the bucket size

                                                                                                                                                      It's important to understand that under the hood, a violin shape is nothing else than a smoothed histogram. You can use the sentence below the following chart to switch from one to the other and understand the tight connection.

                                                                                                                                                      As a result the violin plot suffers the same flaw as the histogram: its shape highly depends on the number of buckets used for the computation. Use the slider to see the impact of the target bucket number on the violin shape.

                                                                                                                                                      Each violin shape based on approx. 5 buckets
                                                                                                                                                      -10-505101520253035ABCD
                                                                                                                                                      You can use smoothing or steps.

                                                                                                                                                      Interactive violin plot: try to toggle smoothing and change the number of buckets in use.

                                                                                                                                                      Note: the requested number of buckets is a target. The bin() function of d3 will create smart buckets around this value.

                                                                                                                                                      Comparison with a boxplot

                                                                                                                                                      The boxplot is an alternative to represent the exact same kind of dataset. You can visit the boxplot section of the gallery or play with the interactive example below to understand how those 2 options behave on the same dataset.

                                                                                                                                                      Use the slider to switch from the violin to the box. Play with the sentence below the chart to toggle smoothing on the violin.

                                                                                                                                                      -10-505101520253035ABCD
                                                                                                                                                      You can use smoothing or steps.

                                                                                                                                                      Compare how violins and boxplots look like for the same dataset.

                                                                                                                                                      Animation

                                                                                                                                                      Animating the transition between 2 datasets, or from/to another chart type is hard, because the violin plot is based on SVG path. It is doable though and I'm working on a specific post that will be released soon.

                                                                                                                                                      schema explaining how histogram buckets are created from the original dataset

                                                                                                                                                      Using shape morphism to transition between a boxplot and a violin plot. Blog post coming soon!

                                                                                                                                                      If you're interested in this topic, feel free to subscribe to the newsletter to be informed when this post is available!

                                                                                                                                                      Contact

                                                                                                                                                      👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                      Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                        -
                                                                                                                                                        \ No newline at end of file +
                                                                                                                                                        \ No newline at end of file diff --git a/viz-from-the-future.html b/viz-from-the-future.html index 993fe54a..6b36a4c4 100644 --- a/viz-from-the-future.html +++ b/viz-from-the-future.html @@ -1,7 +1,7 @@ -How to build a responsive chart with React and d3.js

                                                                                                                                                        A viz from the future


                                                                                                                                                        Building a viz from the future?

                                                                                                                                                        What is a viz from the future?

                                                                                                                                                        You know minority report?

                                                                                                                                                        This video is what I mean

                                                                                                                                                        • Dark mode
                                                                                                                                                        • Flashy, Neon color
                                                                                                                                                        • Glowing shapes
                                                                                                                                                        • Gradient
                                                                                                                                                        • Animation

                                                                                                                                                        glowing div with box shadow

                                                                                                                                                        Can be done with overlapping box-shadow.

                                                                                                                                                        Official doc is here

                                                                                                                                                        A box shadow is described by X and Y offsets relative to the element, blur and spread radius, and color.

                                                                                                                                                        With inset, I can put the shadow inside of the shape

                                                                                                                                                        shadows are drawn one of top of each other.

                                                                                                                                                        But there is an issue: box-shadow does not exist for svg.

                                                                                                                                                        Glowing SVG with

                                                                                                                                                        How can I do.

                                                                                                                                                        Two main ways: svg filter and css filter

                                                                                                                                                        css filter is easy, it works like box-shadows that is described above

                                                                                                                                                        BUT, it does not work with inset, so we need another solution for inside shadow.

                                                                                                                                                        But there is an issue: how to do for canvas




                                                                                                                                                        Contact

                                                                                                                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                        +How to build a responsive chart with React and d3.js

                                                                                                                                                        A viz from the future


                                                                                                                                                        Building a viz from the future?

                                                                                                                                                        What is a viz from the future?

                                                                                                                                                        You know minority report?

                                                                                                                                                        This video is what I mean

                                                                                                                                                        • Dark mode
                                                                                                                                                        • Flashy, Neon color
                                                                                                                                                        • Glowing shapes
                                                                                                                                                        • Gradient
                                                                                                                                                        • Animation

                                                                                                                                                        glowing div with box shadow

                                                                                                                                                        Can be done with overlapping box-shadow.

                                                                                                                                                        Official doc is here

                                                                                                                                                        A box shadow is described by X and Y offsets relative to the element, blur and spread radius, and color.

                                                                                                                                                        With inset, I can put the shadow inside of the shape

                                                                                                                                                        shadows are drawn one of top of each other.

                                                                                                                                                        But there is an issue: box-shadow does not exist for svg.

                                                                                                                                                        Glowing SVG with

                                                                                                                                                        How can I do.

                                                                                                                                                        Two main ways: svg filter and css filter

                                                                                                                                                        css filter is easy, it works like box-shadows that is described above

                                                                                                                                                        BUT, it does not work with inset, so we need another solution for inside shadow.

                                                                                                                                                        But there is an issue: how to do for canvas




                                                                                                                                                        Contact

                                                                                                                                                        👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                        Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                          Contact

                                                                                                                                                          👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                          Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                            -
                                                                                                                                                            \ No newline at end of file +
                                                                                                                                                            \ No newline at end of file diff --git a/voronoi.html b/voronoi.html index 3c25de56..e7d7ca3c 100644 --- a/voronoi.html +++ b/voronoi.html @@ -1,4 +1,4 @@ -How to build a Voronoi Diagram with React and D3.

                                                                                                                                                            Voronoi Diagram

                                                                                                                                                            Dataviz logo representing a Voronoi chart.

                                                                                                                                                            A voronoi diagram is a partition of a plane into regions called voronoi cells. A voronoi cell consists of every point in the plane whose distance to its linked data point is less than or equal to its distance to any other data point.

                                                                                                                                                            This page is a step-by-step guide on how to build your own voronoi diagram for the web, using React and D3.js.

                                                                                                                                                            It starts by describing how the data should be organized and explains how to run and plot a Delaunay triangulation. Based on this, it explains how to build the voronoi diagram. Finally it shows how this can be used for real life application like for a scatterplot or to build a voronoi treemap.

                                                                                                                                                            Useful links

                                                                                                                                                            The Data

                                                                                                                                                            Everything starts with a set of two-dimensional points. Their coordinates are available with x representing the position on the horizontal axis and y being for the vertical axis.

                                                                                                                                                            As a result, the dataset is pretty simple: an array of objects that looks like this:


                                                                                                                                                            export const data = [
                                                                                                                                                            +How to build a Voronoi Diagram with React and D3.

                                                                                                                                                            Voronoi Diagram

                                                                                                                                                            Dataviz logo representing a Voronoi chart.

                                                                                                                                                            A voronoi diagram is a partition of a plane into regions called voronoi cells. A voronoi cell consists of every point in the plane whose distance to its linked data point is less than or equal to its distance to any other data point.

                                                                                                                                                            This page is a step-by-step guide on how to build your own voronoi diagram for the web, using React and D3.js.

                                                                                                                                                            It starts by describing how the data should be organized and explains how to run and plot a Delaunay triangulation. Based on this, it explains how to build the voronoi diagram. Finally it shows how this can be used for real life application like for a scatterplot or to build a voronoi treemap.

                                                                                                                                                            Useful links

                                                                                                                                                            The Data

                                                                                                                                                            Everything starts with a set of two-dimensional points. Their coordinates are available with x representing the position on the horizontal axis and y being for the vertical axis.

                                                                                                                                                            As a result, the dataset is pretty simple: an array of objects that looks like this:


                                                                                                                                                            export const data = [
                                                                                                                                                               { x: 10, y: 10 },
                                                                                                                                                               { x: 4, y: 4 },
                                                                                                                                                               { x: 35, y: 90 },
                                                                                                                                                            @@ -39,4 +39,4 @@
                                                                                                                                                             }

                                                                                                                                                            I'm in the process of writing a complete blog post on the topic. Subscribe to the project to know when it's ready.




                                                                                                                                                            Voronoi inspiration

                                                                                                                                                            If you're looking for inspiration to create your next Voronoi, note that dataviz-inspiration.com showcases many examples. Definitely the best place to get ... inspiration!

                                                                                                                                                            dataviz-inspiration.com showcases hundreds of stunning dataviz projects. Have a look to get some ideas on how to make your Voronoi looks good!

                                                                                                                                                            visit

                                                                                                                                                            Closest point detection

                                                                                                                                                            The voronoi diagram is commonly used to detect the closest data point of the mouse position. This can be pretty useful to highlight the closest point without having to hover exactly over it.

                                                                                                                                                            In the example below, the closest dot will be highlighted with a red circle ⭕️ using the voronoi cells.


                                                                                                                                                            Use the voronoi algorithm to detect the closest point of the mouse position.

                                                                                                                                                            Variations

                                                                                                                                                            A glimpse of what it is possible to do using the voronoi diagram for data visualization.

                                                                                                                                                            Click on the overview below to get details and code.


                                                                                                                                                            gif of a scatterplot with voronoi diagram for closest point detection

                                                                                                                                                            Closest point detection with Voronoi

                                                                                                                                                            Using a voronoi diagram in the scatterplot background is a smart way to efficiently find the mouse closest point

                                                                                                                                                            ToDoAdd voronoi treemap example

                                                                                                                                                            Contact

                                                                                                                                                            👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                            Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                              -
                                                                                                                                                              \ No newline at end of file +
                                                                                                                                                              \ No newline at end of file diff --git a/what-is-a-color.html b/what-is-a-color.html index 322e7e4a..ce0644a1 100644 --- a/what-is-a-color.html +++ b/what-is-a-color.html @@ -1,7 +1,7 @@ -What is a color

                                                                                                                                                              What is a color


                                                                                                                                                              There are so many ways to define a color when talking with a computer. Let's take a tour and see what's the most appropriate in a dataviz point of view.

                                                                                                                                                              Color on screen

                                                                                                                                                              A computer screen is made of thousands of pixels.

                                                                                                                                                              Each pixel generates three colors of light (red, green, and blue) and the different colors we see are due to different combinations and intensities of these three primary colors.

                                                                                                                                                              red, green and blue are the primary colors.

                                                                                                                                                              The RGB color model

                                                                                                                                                              The color information for each pixel is typically stored in a 24-bit format: 8 bit per primary color. This is 2^8 = 256 possibilities for each primary color. This means more than 16M possible color variations for each pixel (256^3)!

                                                                                                                                                              The HSV, HSL and HSB color model

                                                                                                                                                              That's the famous color wheel you see in every color picker!


                                                                                                                                                              overview of color picker.me

                                                                                                                                                              On colorpicker.me you can define a color using its hue (vertical bar), its saturation (x axis of the square) and its lightness (vertical axis)

                                                                                                                                                              HSL stands for hue, saturation, lightness

                                                                                                                                                              HSV and HSB are the same and stand for hue, saturation, value or hue, saturation, brightness respectively.

                                                                                                                                                              But what does it even mean?

                                                                                                                                                              • Hue: the initial color. Between 0 and 360.
                                                                                                                                                              • Saturation: when closer to 100, the color shines. represents how “colorful” the color is. Intensity. Purity. When 0, you get grey
                                                                                                                                                              • Lighness, Value, Brightness

                                                                                                                                                              color cylinder of HSV

                                                                                                                                                              The color cylinder of HSV

                                                                                                                                                              There are an alternative to the RGB color model to more closely align with the way human vision perceives color-making attributes

                                                                                                                                                              Indeed, it allows us to describe meaningful relationships between colors. For instance, to create 2 complementary colors you can select 2 colors on the opposite side of the wheel, with same saturation and brithness. Same principle for analogous, monochrome palette and other famous combinations.

                                                                                                                                                              HSV is criticized. This is because in HSV the V (value) is just a measure for the physical lightness of color, but not for the perceived brightness. So 2 colors with the same value are not perceive with the same lightness by the Human Eye. There is a hue-dependency of brightness in this model.

                                                                                                                                                              Note: pastel color = high lightness and low saturation.

                                                                                                                                                              The CIELAB color model

                                                                                                                                                              Try to fix this difference between computer and human perception.

                                                                                                                                                              unintuitive to use to generate colors

                                                                                                                                                              cielab color spec

                                                                                                                                                              The cielab color space

                                                                                                                                                              The HCL color model

                                                                                                                                                              Stands for Hue-Chroma-Lightness. A cylindrical transformation of CIE Lab*

                                                                                                                                                              Luminance of a color

                                                                                                                                                              TODO

                                                                                                                                                              The Contrast Ratio

                                                                                                                                                              The Web Content Accessibility Guidelines (WCAG) include convenient quantitative recommendations for making a color accessible based on the minimum acceptable contrast of foreground against background.

                                                                                                                                                              Basically, you can compare the luminance of 2 colors and compute their contrast ratio. The luminance is computed using the amount of red, green and blue in it.

                                                                                                                                                              To see the exact formulas and compute the contrast ratio between 2 colors, see this notebook by Mike Bostock


                                                                                                                                                              contrast ratio calculator

                                                                                                                                                              A tool to compute the contrast ratio between 2 colors.

                                                                                                                                                              Note: the notebook provides the d3 code to compute this contrast ratio.




                                                                                                                                                              Contact

                                                                                                                                                              👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                              +What is a color

                                                                                                                                                              What is a color


                                                                                                                                                              There are so many ways to define a color when talking with a computer. Let's take a tour and see what's the most appropriate in a dataviz point of view.

                                                                                                                                                              Color on screen

                                                                                                                                                              A computer screen is made of thousands of pixels.

                                                                                                                                                              Each pixel generates three colors of light (red, green, and blue) and the different colors we see are due to different combinations and intensities of these three primary colors.

                                                                                                                                                              red, green and blue are the primary colors.

                                                                                                                                                              The RGB color model

                                                                                                                                                              The color information for each pixel is typically stored in a 24-bit format: 8 bit per primary color. This is 2^8 = 256 possibilities for each primary color. This means more than 16M possible color variations for each pixel (256^3)!

                                                                                                                                                              The HSV, HSL and HSB color model

                                                                                                                                                              That's the famous color wheel you see in every color picker!


                                                                                                                                                              overview of color picker.me

                                                                                                                                                              On colorpicker.me you can define a color using its hue (vertical bar), its saturation (x axis of the square) and its lightness (vertical axis)

                                                                                                                                                              HSL stands for hue, saturation, lightness

                                                                                                                                                              HSV and HSB are the same and stand for hue, saturation, value or hue, saturation, brightness respectively.

                                                                                                                                                              But what does it even mean?

                                                                                                                                                              • Hue: the initial color. Between 0 and 360.
                                                                                                                                                              • Saturation: when closer to 100, the color shines. represents how “colorful” the color is. Intensity. Purity. When 0, you get grey
                                                                                                                                                              • Lighness, Value, Brightness

                                                                                                                                                              color cylinder of HSV

                                                                                                                                                              The color cylinder of HSV

                                                                                                                                                              There are an alternative to the RGB color model to more closely align with the way human vision perceives color-making attributes

                                                                                                                                                              Indeed, it allows us to describe meaningful relationships between colors. For instance, to create 2 complementary colors you can select 2 colors on the opposite side of the wheel, with same saturation and brithness. Same principle for analogous, monochrome palette and other famous combinations.

                                                                                                                                                              HSV is criticized. This is because in HSV the V (value) is just a measure for the physical lightness of color, but not for the perceived brightness. So 2 colors with the same value are not perceive with the same lightness by the Human Eye. There is a hue-dependency of brightness in this model.

                                                                                                                                                              Note: pastel color = high lightness and low saturation.

                                                                                                                                                              The CIELAB color model

                                                                                                                                                              Try to fix this difference between computer and human perception.

                                                                                                                                                              unintuitive to use to generate colors

                                                                                                                                                              cielab color spec

                                                                                                                                                              The cielab color space

                                                                                                                                                              The HCL color model

                                                                                                                                                              Stands for Hue-Chroma-Lightness. A cylindrical transformation of CIE Lab*

                                                                                                                                                              Luminance of a color

                                                                                                                                                              TODO

                                                                                                                                                              The Contrast Ratio

                                                                                                                                                              The Web Content Accessibility Guidelines (WCAG) include convenient quantitative recommendations for making a color accessible based on the minimum acceptable contrast of foreground against background.

                                                                                                                                                              Basically, you can compare the luminance of 2 colors and compute their contrast ratio. The luminance is computed using the amount of red, green and blue in it.

                                                                                                                                                              To see the exact formulas and compute the contrast ratio between 2 colors, see this notebook by Mike Bostock


                                                                                                                                                              contrast ratio calculator

                                                                                                                                                              A tool to compute the contrast ratio between 2 colors.

                                                                                                                                                              Note: the notebook provides the d3 code to compute this contrast ratio.




                                                                                                                                                              Contact

                                                                                                                                                              👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                              Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                                Contact

                                                                                                                                                                👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                                Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                                  -
                                                                                                                                                                  \ No newline at end of file +
                                                                                                                                                                  \ No newline at end of file diff --git a/wordcloud.html b/wordcloud.html index 222f3484..78c8eae3 100644 --- a/wordcloud.html +++ b/wordcloud.html @@ -1,4 +1,4 @@ -Wordcloud with React

                                                                                                                                                                  Wordcloud

                                                                                                                                                                  Dataviz logo representing a Wordcloud chart.

                                                                                                                                                                  This page explains how to build a wordcloud using react and d3.js. It uses the d3-cloud plugin to compute the position of each word, and render them with react.

                                                                                                                                                                  This section is rather short as I'm not a big fan of wordclouds. They can be quite misleading and you should consider building a barplot or a lollipop plot instead.

                                                                                                                                                                  Useful links
                                                                                                                                                                  This page uses the d3-cloud plugin that you can install in your project with npm install d3-cloud

                                                                                                                                                                  The Data

                                                                                                                                                                  The data is an array. Each item is an object describing a word. Its name is provided, together with a related value that will be used to size the word on the final figure.

                                                                                                                                                                  Note that you can add any additional property here, like a color, a font weight or anything else that you want to use to draw the word later on.

                                                                                                                                                                  const data = [
                                                                                                                                                                  +Wordcloud with React

                                                                                                                                                                  Wordcloud

                                                                                                                                                                  Dataviz logo representing a Wordcloud chart.

                                                                                                                                                                  This page explains how to build a wordcloud using react and d3.js. It uses the d3-cloud plugin to compute the position of each word, and render them with react.

                                                                                                                                                                  This section is rather short as I'm not a big fan of wordclouds. They can be quite misleading and you should consider building a barplot or a lollipop plot instead.

                                                                                                                                                                  Useful links
                                                                                                                                                                  This page uses the d3-cloud plugin that you can install in your project with npm install d3-cloud

                                                                                                                                                                  The Data

                                                                                                                                                                  The data is an array. Each item is an object describing a word. Its name is provided, together with a related value that will be used to size the word on the final figure.

                                                                                                                                                                  Note that you can add any additional property here, like a color, a font weight or anything else that you want to use to draw the word later on.

                                                                                                                                                                  const data = [
                                                                                                                                                                     { text: "hello", value: 12 },
                                                                                                                                                                     { text: "world", value: 2 },
                                                                                                                                                                   ];

                                                                                                                                                                  Most basic wordcloud with React and D3.js

                                                                                                                                                                  Everything starts by instantiating a wordcloud layout using thed3Cloud() function of the d3-cloud library.

                                                                                                                                                                  const layout = d3Cloud()
                                                                                                                                                                  @@ -11,4 +11,4 @@
                                                                                                                                                                     });

                                                                                                                                                                  This layout can then be called from a useEffect using layout.start(). The layout algorithm will loop through each word of the dataset and try to place them on the chart, avoiding overlaps with other words.

                                                                                                                                                                  Once the loop is over, the layout algorithm will produce a words object and provide it to the end() function. This function update a state that stores the position and feature of each word.

                                                                                                                                                                  It is thus possible to map through those word features and draw them using html, svg or canvas. Here is an example using HTML


                                                                                                                                                                  Most basic Wordcloud made with react and d3.js

                                                                                                                                                                  Todo: write better explanation
                                                                                                                                                                  Todo: the layout algorithm currently provides unperfect values, resulting in a lot of word overlaps. Please tell me if you find where the bug is.

                                                                                                                                                                  Warning

                                                                                                                                                                  Wordclouds are useful for quickly perceiving the most prominent terms. They are widely used in media and well understood by the public. However, they are criticized for 2 main reasons:

                                                                                                                                                                  • Area is a poor metaphor of a numeric value, it is hardly perceive by the human eye
                                                                                                                                                                  • Longer words appear bigger by construction

                                                                                                                                                                  To put it in a nutshell, wordclouds must be avoided. You can read more about that in data-to-viz. Why not consider a lollipop plot or a barplot instead?

                                                                                                                                                                  Contact

                                                                                                                                                                  👋 Hey, I'm Yan and I'm currently working on this project!

                                                                                                                                                                  Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

                                                                                                                                                                    -
                                                                                                                                                                    \ No newline at end of file +
                                                                                                                                                                    \ No newline at end of file