diff --git a/pages/course/svg/d3-shape.tsx b/pages/course/svg/d3-shape.tsx index 5f03ce34..188bb0c2 100644 --- a/pages/course/svg/d3-shape.tsx +++ b/pages/course/svg/d3-shape.tsx @@ -13,6 +13,7 @@ import { } from '@/component/ExerciseDoubleSandbox'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/component/UI/tabs'; import { Caption } from '@/component/UI/Caption'; +import { GraphTOTO } from '@/viz/exercise/d3LineMultipleLineChartSolution/Graph'; const previousURL = '/course/svg/path-element'; const currentURL = '/course/svg/d3-shape'; @@ -341,8 +342,16 @@ multiply(4, 6)) ), content: , }, + { + title: Multiple lines!, + content: , + }, + { + title: Line chart with filled area, + content: , + }, ]} - />{' '} + /> ); } @@ -431,4 +440,84 @@ const exercices: Exercise[] = [ practiceSandbox: 'exercise/d3AreaFunctionPractice', solutionSandbox: 'exercise/d3AreaFunctionSolution', }, + + { + whyItMatters: ( + <> +

+ Using the area() function is almost the same as the{' '} + line() function. +

+

+ That's the magic of the d3-shape module, you switch from + one shape to the other easily! +

+ + ), + toDo: ( +
    +
  • + Let's switch to an area chart, thanks to the d3.area(){' '} + function. Three methods must be chained to area(): +
  • +
  • + x() is the same as for the line chart. +
  • +
  • + y0(): Y coordinate of the bottom of the area +
  • +
  • + y1() Y coordinate of the top. +
  • +
+ ), + practiceSandbox: 'exercise/d3LineMultipleLineChartPractice', + solutionSandbox: 'exercise/d3LineMultipleLineChartSolution', + }, + + { + whyItMatters: ( + <> +

+ Once the path generator is available, it can be used to create as many + elements as you wish! +

+ + ), + toDo: ( +
    +
  • This time, 2 datasets are available. We want to draw 2 lines.
  • +
  • Create a line path generator.
  • +
  • + Use the path generator twice, once per dataset, to create 2 paths and + draw them! +
  • +
+ ), + practiceSandbox: 'exercise/d3LineMultipleLineChartPractice', + solutionSandbox: 'exercise/d3LineMultipleLineChartSolution', + }, + + { + whyItMatters: ( + <> +

+ A chart is essentially a combination of shapes! Once you know how to + build them individually, it's just a matter of drawing them together! +

+ + ), + toDo: ( +
    +
  • Create both a line generator and an area generator
  • +
  • Add 2 paths to the SVG: the area first, the line second.
  • +
  • + Use low opacity for the area and a stroke width of 2 for the line. +
  • +
+ ), + + practiceSandbox: 'exercise/d3LineFilledAreaPractice', + solutionSandbox: 'exercise/d3LineFilledAreaSolution', + }, ]; diff --git a/viz/exercise/d3LineFilledAreaPractice/Graph.tsx b/viz/exercise/d3LineFilledAreaPractice/Graph.tsx new file mode 100644 index 00000000..cfbe29d5 --- /dev/null +++ b/viz/exercise/d3LineFilledAreaPractice/Graph.tsx @@ -0,0 +1,25 @@ +import { line } from 'd3'; + +// Positions in pixels +const data = [ + { x: 0, y: 40 }, + { x: 50, y: 70 }, + { x: 100, y: 150 }, + { x: 200, y: 50 }, + { x: 300, y: 250 }, +]; + +export const Graph = () => { + // Use the line() function of d3 to create a path generator that expects data as input + const lineGenerator = ''; + + // Use the lineGenerator function above to build the path string + const path = ''; + + return ( + + {/* The path built above is used here for the d argument */} + + + ); +}; diff --git a/viz/exercise/d3LineFilledAreaPractice/d3LineFunctionBasicSolution/Graph.tsx b/viz/exercise/d3LineFilledAreaPractice/d3LineFunctionBasicSolution/Graph.tsx new file mode 100644 index 00000000..72f1f517 --- /dev/null +++ b/viz/exercise/d3LineFilledAreaPractice/d3LineFunctionBasicSolution/Graph.tsx @@ -0,0 +1,24 @@ +import { line } from 'd3'; + +// Positions in pixels +const data = [ + { x: 0, y: 40 }, + { x: 50, y: 70 }, + { x: 100, y: 150 }, + { x: 200, y: 50 }, + { x: 300, y: 250 }, +]; + +export const Graph = () => { + const lineGenerator = line() + .x((d) => d.x) + .y((d) => d.y); + + const path = lineGenerator(data); + + return ( + + + + ); +}; diff --git a/viz/exercise/d3LineFilledAreaPractice/d3LineFunctionBasicSolution/index.js b/viz/exercise/d3LineFilledAreaPractice/d3LineFunctionBasicSolution/index.js new file mode 100644 index 00000000..fa564d27 --- /dev/null +++ b/viz/exercise/d3LineFilledAreaPractice/d3LineFunctionBasicSolution/index.js @@ -0,0 +1,6 @@ +// File used to render something in codesandbox only +import ReactDOM from 'react-dom'; +import { Graph } from './Graph'; + +const rootElement = document.getElementById('root'); +ReactDOM.render(, rootElement); diff --git a/viz/exercise/d3LineFilledAreaPractice/d3LineFunctionBasicSolution/package.json b/viz/exercise/d3LineFilledAreaPractice/d3LineFunctionBasicSolution/package.json new file mode 100644 index 00000000..84ed1985 --- /dev/null +++ b/viz/exercise/d3LineFilledAreaPractice/d3LineFunctionBasicSolution/package.json @@ -0,0 +1,29 @@ +{ + "name": "pie-chart-basic", + "version": "1.0.0", + "description": "", + "keywords": [], + "main": "index.js", + "dependencies": { + "react": "17.0.2", + "d3": "7.1.1", + "react-dom": "17.0.2", + "react-scripts": "4.0.0" + }, + "devDependencies": { + "@babel/runtime": "7.13.8", + "typescript": "4.1.3" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/viz/exercise/d3LineFilledAreaPractice/index.js b/viz/exercise/d3LineFilledAreaPractice/index.js new file mode 100644 index 00000000..fa564d27 --- /dev/null +++ b/viz/exercise/d3LineFilledAreaPractice/index.js @@ -0,0 +1,6 @@ +// File used to render something in codesandbox only +import ReactDOM from 'react-dom'; +import { Graph } from './Graph'; + +const rootElement = document.getElementById('root'); +ReactDOM.render(, rootElement); diff --git a/viz/exercise/d3LineFilledAreaPractice/package.json b/viz/exercise/d3LineFilledAreaPractice/package.json new file mode 100644 index 00000000..84ed1985 --- /dev/null +++ b/viz/exercise/d3LineFilledAreaPractice/package.json @@ -0,0 +1,29 @@ +{ + "name": "pie-chart-basic", + "version": "1.0.0", + "description": "", + "keywords": [], + "main": "index.js", + "dependencies": { + "react": "17.0.2", + "d3": "7.1.1", + "react-dom": "17.0.2", + "react-scripts": "4.0.0" + }, + "devDependencies": { + "@babel/runtime": "7.13.8", + "typescript": "4.1.3" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/viz/exercise/d3LineFilledAreaSolution/Graph.tsx b/viz/exercise/d3LineFilledAreaSolution/Graph.tsx new file mode 100644 index 00000000..07d10423 --- /dev/null +++ b/viz/exercise/d3LineFilledAreaSolution/Graph.tsx @@ -0,0 +1,38 @@ +import { area, line } from 'd3'; + +// Positions in pixels +const data = [ + { x: 0, y: 40 }, + { x: 50, y: 70 }, + { x: 100, y: 150 }, + { x: 200, y: 50 }, + { x: 300, y: 250 }, +]; + +export const Graph = () => { + const lineGenerator = line() + .x((d) => d.x) + .y((d) => d.y); + + const areaGenerator = area() + .x((d) => d.x) + .y0((d) => 300) + .y1((d) => d.y); + + return ( + + + + + ); +}; diff --git a/viz/exercise/d3LineFilledAreaSolution/index.js b/viz/exercise/d3LineFilledAreaSolution/index.js new file mode 100644 index 00000000..fa564d27 --- /dev/null +++ b/viz/exercise/d3LineFilledAreaSolution/index.js @@ -0,0 +1,6 @@ +// File used to render something in codesandbox only +import ReactDOM from 'react-dom'; +import { Graph } from './Graph'; + +const rootElement = document.getElementById('root'); +ReactDOM.render(, rootElement); diff --git a/viz/exercise/d3LineFilledAreaSolution/package.json b/viz/exercise/d3LineFilledAreaSolution/package.json new file mode 100644 index 00000000..84ed1985 --- /dev/null +++ b/viz/exercise/d3LineFilledAreaSolution/package.json @@ -0,0 +1,29 @@ +{ + "name": "pie-chart-basic", + "version": "1.0.0", + "description": "", + "keywords": [], + "main": "index.js", + "dependencies": { + "react": "17.0.2", + "d3": "7.1.1", + "react-dom": "17.0.2", + "react-scripts": "4.0.0" + }, + "devDependencies": { + "@babel/runtime": "7.13.8", + "typescript": "4.1.3" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/viz/exercise/d3LineMultipleLineChartPractice/Graph.tsx b/viz/exercise/d3LineMultipleLineChartPractice/Graph.tsx new file mode 100644 index 00000000..52fe19b0 --- /dev/null +++ b/viz/exercise/d3LineMultipleLineChartPractice/Graph.tsx @@ -0,0 +1,30 @@ +import { line } from 'd3'; + +// Positions in pixels +const data = [ + { x: 0, y: 40 }, + { x: 50, y: 70 }, + { x: 100, y: 150 }, + { x: 200, y: 50 }, + { x: 300, y: 250 }, +]; + +const data2 = [ + { x: 0, y: 140 }, + { x: 50, y: 20 }, + { x: 100, y: 110 }, + { x: 200, y: 150 }, + { x: 300, y: 50 }, +]; + +export const Graph = () => { + const lineGenerator = line() + .x((d) => d.x) + .y((d) => d.y); + + return ( + + {/* Write 2 paths here, one for each dataset! */} + + ); +}; diff --git a/viz/exercise/d3LineMultipleLineChartPractice/d3LineFunctionBasicSolution/Graph.tsx b/viz/exercise/d3LineMultipleLineChartPractice/d3LineFunctionBasicSolution/Graph.tsx new file mode 100644 index 00000000..72f1f517 --- /dev/null +++ b/viz/exercise/d3LineMultipleLineChartPractice/d3LineFunctionBasicSolution/Graph.tsx @@ -0,0 +1,24 @@ +import { line } from 'd3'; + +// Positions in pixels +const data = [ + { x: 0, y: 40 }, + { x: 50, y: 70 }, + { x: 100, y: 150 }, + { x: 200, y: 50 }, + { x: 300, y: 250 }, +]; + +export const Graph = () => { + const lineGenerator = line() + .x((d) => d.x) + .y((d) => d.y); + + const path = lineGenerator(data); + + return ( + + + + ); +}; diff --git a/viz/exercise/d3LineMultipleLineChartPractice/d3LineFunctionBasicSolution/index.js b/viz/exercise/d3LineMultipleLineChartPractice/d3LineFunctionBasicSolution/index.js new file mode 100644 index 00000000..fa564d27 --- /dev/null +++ b/viz/exercise/d3LineMultipleLineChartPractice/d3LineFunctionBasicSolution/index.js @@ -0,0 +1,6 @@ +// File used to render something in codesandbox only +import ReactDOM from 'react-dom'; +import { Graph } from './Graph'; + +const rootElement = document.getElementById('root'); +ReactDOM.render(, rootElement); diff --git a/viz/exercise/d3LineMultipleLineChartPractice/d3LineFunctionBasicSolution/package.json b/viz/exercise/d3LineMultipleLineChartPractice/d3LineFunctionBasicSolution/package.json new file mode 100644 index 00000000..84ed1985 --- /dev/null +++ b/viz/exercise/d3LineMultipleLineChartPractice/d3LineFunctionBasicSolution/package.json @@ -0,0 +1,29 @@ +{ + "name": "pie-chart-basic", + "version": "1.0.0", + "description": "", + "keywords": [], + "main": "index.js", + "dependencies": { + "react": "17.0.2", + "d3": "7.1.1", + "react-dom": "17.0.2", + "react-scripts": "4.0.0" + }, + "devDependencies": { + "@babel/runtime": "7.13.8", + "typescript": "4.1.3" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/viz/exercise/d3LineMultipleLineChartPractice/index.js b/viz/exercise/d3LineMultipleLineChartPractice/index.js new file mode 100644 index 00000000..fa564d27 --- /dev/null +++ b/viz/exercise/d3LineMultipleLineChartPractice/index.js @@ -0,0 +1,6 @@ +// File used to render something in codesandbox only +import ReactDOM from 'react-dom'; +import { Graph } from './Graph'; + +const rootElement = document.getElementById('root'); +ReactDOM.render(, rootElement); diff --git a/viz/exercise/d3LineMultipleLineChartPractice/package.json b/viz/exercise/d3LineMultipleLineChartPractice/package.json new file mode 100644 index 00000000..84ed1985 --- /dev/null +++ b/viz/exercise/d3LineMultipleLineChartPractice/package.json @@ -0,0 +1,29 @@ +{ + "name": "pie-chart-basic", + "version": "1.0.0", + "description": "", + "keywords": [], + "main": "index.js", + "dependencies": { + "react": "17.0.2", + "d3": "7.1.1", + "react-dom": "17.0.2", + "react-scripts": "4.0.0" + }, + "devDependencies": { + "@babel/runtime": "7.13.8", + "typescript": "4.1.3" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +} diff --git a/viz/exercise/d3LineMultipleLineChartSolution/Graph.tsx b/viz/exercise/d3LineMultipleLineChartSolution/Graph.tsx new file mode 100644 index 00000000..aedf4eac --- /dev/null +++ b/viz/exercise/d3LineMultipleLineChartSolution/Graph.tsx @@ -0,0 +1,31 @@ +import { line } from 'd3'; + +// Positions in pixels +const data = [ + { x: 0, y: 40 }, + { x: 50, y: 70 }, + { x: 100, y: 150 }, + { x: 200, y: 50 }, + { x: 300, y: 250 }, +]; + +const data2 = [ + { x: 0, y: 140 }, + { x: 50, y: 20 }, + { x: 100, y: 110 }, + { x: 200, y: 150 }, + { x: 300, y: 50 }, +]; + +export const Graph = () => { + const lineGenerator = line() + .x((d) => d.x) + .y((d) => d.y); + + return ( + + + + + ); +}; diff --git a/viz/exercise/d3LineMultipleLineChartSolution/index.js b/viz/exercise/d3LineMultipleLineChartSolution/index.js new file mode 100644 index 00000000..fa564d27 --- /dev/null +++ b/viz/exercise/d3LineMultipleLineChartSolution/index.js @@ -0,0 +1,6 @@ +// File used to render something in codesandbox only +import ReactDOM from 'react-dom'; +import { Graph } from './Graph'; + +const rootElement = document.getElementById('root'); +ReactDOM.render(, rootElement); diff --git a/viz/exercise/d3LineMultipleLineChartSolution/package.json b/viz/exercise/d3LineMultipleLineChartSolution/package.json new file mode 100644 index 00000000..84ed1985 --- /dev/null +++ b/viz/exercise/d3LineMultipleLineChartSolution/package.json @@ -0,0 +1,29 @@ +{ + "name": "pie-chart-basic", + "version": "1.0.0", + "description": "", + "keywords": [], + "main": "index.js", + "dependencies": { + "react": "17.0.2", + "d3": "7.1.1", + "react-dom": "17.0.2", + "react-scripts": "4.0.0" + }, + "devDependencies": { + "@babel/runtime": "7.13.8", + "typescript": "4.1.3" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test --env=jsdom", + "eject": "react-scripts eject" + }, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] +}