diff --git a/pages/course/hover-effect/toggle-class-in-js.tsx b/pages/course/hover-effect/toggle-class-in-js.tsx
index 29bd81b9..f556e126 100644
--- a/pages/course/hover-effect/toggle-class-in-js.tsx
+++ b/pages/course/hover-effect/toggle-class-in-js.tsx
@@ -17,6 +17,7 @@ import {
} from '@/component/ExerciseDoubleSandbox';
import { ExerciseAccordion } from '@/component/ExerciseAccordion';
import { Graph23 } from '@/viz/exercise/PieFirstSolution/Graph';
+import { Graph42 } from '@/viz/exercise/PieHoverEffectSolution/Graph';
const previousURL = '/course/hover-effect/css-descendant-selector';
const currentURL = '/course/hover-effect/toggle-class-in-js';
@@ -204,6 +205,7 @@ const containerRef = useRef();
>
Visit project
+
{/* -
-
@@ -217,7 +219,7 @@ const containerRef = useRef();
localStorageId={currentLesson.link}
exercises={[
{
- title: Your first pie chart! 🍭 ,
+ title: Your first pie chart! 🍰 ,
content: ,
},
{
@@ -234,8 +236,9 @@ const exercises: Exercise[] = [
whyItMatters: (
<>
- With the SVG and D3 foundations you’ve built, creating a new chart
- type becomes a breeze!
+ Time to learn a new chart type! Check the{' '}
+ pie chart page for the full in-depth
+ tutorial.
>
),
@@ -243,12 +246,11 @@ const exercises: Exercise[] = [
<>
A dataset is provided in the sandbox folder.
+ Build a pie chart representing this dataset.
- Build a Cleveland chart with this dataset. (This chart is a
- variation of the lollipop plot and is helpful for comparing two
- values across multiple groups.)
+ Read the pie chart section for help on
+ d3.pie()
and d3.arc()
.
- Check the solution tab to see the intended chart appearance.
>
),
diff --git a/viz/exercise/PieHoverEffectPractice/Graph.tsx b/viz/exercise/PieHoverEffectPractice/Graph.tsx
new file mode 100644
index 00000000..25419fbf
--- /dev/null
+++ b/viz/exercise/PieHoverEffectPractice/Graph.tsx
@@ -0,0 +1,40 @@
+import * as d3 from 'd3';
+import { data, DataItem } from './data';
+import { useRef } from 'react';
+import styles from './graph.module.css';
+
+const MARGIN = 30;
+const width = 400;
+const height = 400;
+const colors = ['#98abc5', '#8a89a6', '#7b6888', '#6b486b', '#a05d56'];
+
+export const Graph = () => {
+ const containerRef = useRef(null);
+
+ const radius = Math.min(width, height) / 2 - MARGIN;
+
+ const pieGenerator = d3.pie().value((d) => d.value);
+ const pie = pieGenerator(data);
+
+ const arcPathGenerator = d3.arc();
+ const arcs = pie.map((p) =>
+ arcPathGenerator({
+ innerRadius: 0,
+ outerRadius: radius,
+ startAngle: p.startAngle,
+ endAngle: p.endAngle,
+ })
+ );
+
+ return (
+
+
+ {arcs.map((arc, i) => {
+ return (
+
+ );
+ })}
+
+
+ );
+};
diff --git a/viz/exercise/PieHoverEffectPractice/data.ts b/viz/exercise/PieHoverEffectPractice/data.ts
new file mode 100644
index 00000000..4069b832
--- /dev/null
+++ b/viz/exercise/PieHoverEffectPractice/data.ts
@@ -0,0 +1,12 @@
+export type DataItem = {
+ name: string;
+ value: number;
+};
+
+export const data: DataItem[] = [
+ { name: "Mark", value: 90 },
+ { name: "Robert", value: 12 },
+ { name: "Emily", value: 34 },
+ { name: "Marion", value: 53 },
+ { name: "Nicolas", value: 98 },
+]
diff --git a/viz/exercise/PieHoverEffectPractice/graph.module.css b/viz/exercise/PieHoverEffectPractice/graph.module.css
new file mode 100644
index 00000000..107eee4e
--- /dev/null
+++ b/viz/exercise/PieHoverEffectPractice/graph.module.css
@@ -0,0 +1,12 @@
+.container .slice {
+ opacity: 0.8;
+ cursor: pointer;
+}
+
+.container.hasHighlight .slice {
+ opacity: 0.2;
+}
+
+.container.hasHighlight .slice:hover {
+ opacity: 1;
+}
diff --git a/viz/exercise/PieHoverEffectPractice/index.js b/viz/exercise/PieHoverEffectPractice/index.js
new file mode 100644
index 00000000..fa564d27
--- /dev/null
+++ b/viz/exercise/PieHoverEffectPractice/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/PieHoverEffectPractice/package.json b/viz/exercise/PieHoverEffectPractice/package.json
new file mode 100644
index 00000000..84ed1985
--- /dev/null
+++ b/viz/exercise/PieHoverEffectPractice/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/PieHoverEffectSolution/Graph.tsx b/viz/exercise/PieHoverEffectSolution/Graph.tsx
new file mode 100644
index 00000000..92ced5d0
--- /dev/null
+++ b/viz/exercise/PieHoverEffectSolution/Graph.tsx
@@ -0,0 +1,60 @@
+import * as d3 from 'd3';
+import { data, DataItem } from './data';
+import { useRef } from 'react';
+import styles from './graph.module.css';
+
+const MARGIN = 30;
+const width = 400;
+const height = 400;
+const colors = ['#98abc5', '#8a89a6', '#7b6888', '#6b486b', '#a05d56'];
+
+export const Graph = () => {
+ const containerRef = useRef(null);
+
+ const radius = Math.min(width, height) / 2 - MARGIN;
+
+ const pieGenerator = d3.pie().value((d) => d.value);
+ const pie = pieGenerator(data);
+
+ const arcPathGenerator = d3.arc();
+ const arcs = pie.map((p) =>
+ arcPathGenerator({
+ innerRadius: 0,
+ outerRadius: radius,
+ startAngle: p.startAngle,
+ endAngle: p.endAngle,
+ })
+ );
+
+ return (
+
+
+ {arcs.map((arc, i) => {
+ return (
+ {
+ if (containerRef.current) {
+ containerRef.current.classList.add(styles.hasHighlight);
+ }
+ }}
+ onMouseLeave={() => {
+ if (containerRef.current) {
+ containerRef.current.classList.remove(styles.hasHighlight);
+ }
+ }}
+ />
+ );
+ })}
+
+
+ );
+};
diff --git a/viz/exercise/PieHoverEffectSolution/data.ts b/viz/exercise/PieHoverEffectSolution/data.ts
new file mode 100644
index 00000000..4069b832
--- /dev/null
+++ b/viz/exercise/PieHoverEffectSolution/data.ts
@@ -0,0 +1,12 @@
+export type DataItem = {
+ name: string;
+ value: number;
+};
+
+export const data: DataItem[] = [
+ { name: "Mark", value: 90 },
+ { name: "Robert", value: 12 },
+ { name: "Emily", value: 34 },
+ { name: "Marion", value: 53 },
+ { name: "Nicolas", value: 98 },
+]
diff --git a/viz/exercise/PieHoverEffectSolution/graph.module.css b/viz/exercise/PieHoverEffectSolution/graph.module.css
new file mode 100644
index 00000000..107eee4e
--- /dev/null
+++ b/viz/exercise/PieHoverEffectSolution/graph.module.css
@@ -0,0 +1,12 @@
+.container .slice {
+ opacity: 0.8;
+ cursor: pointer;
+}
+
+.container.hasHighlight .slice {
+ opacity: 0.2;
+}
+
+.container.hasHighlight .slice:hover {
+ opacity: 1;
+}
diff --git a/viz/exercise/PieHoverEffectSolution/index.js b/viz/exercise/PieHoverEffectSolution/index.js
new file mode 100644
index 00000000..fa564d27
--- /dev/null
+++ b/viz/exercise/PieHoverEffectSolution/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/PieHoverEffectSolution/package.json b/viz/exercise/PieHoverEffectSolution/package.json
new file mode 100644
index 00000000..84ed1985
--- /dev/null
+++ b/viz/exercise/PieHoverEffectSolution/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"
+ ]
+}