Last active
May 7, 2021 11:13
-
-
Save dibyanshusinha/68047595bbd346406146f84f1519c6a5 to your computer and use it in GitHub Desktop.
BlackBoxing Approach D3 with React.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Approach uses clear Seperation of concern | |
// Lifecycle Methods wraps D3 chart created outside | |
// Cons - No SSR | |
import React, { useLayoutEffect } from "react"; | |
import * as d3 from "d3"; | |
const draw = () => { | |
const width = 600; | |
const dataSet = [ | |
{ type: "success", count: "15", color: "#2F80ED" }, | |
{ type: "error", count: "5", color: "#F2C94C" }, | |
{ type: "warning", count: "3", color: "#27AE60" } | |
]; | |
const sliceGrow = 50; | |
const sliceMove = 20; | |
const pie = d3 | |
.pie() | |
.startAngle(0) | |
.endAngle(2 * Math.PI) | |
.sort(null) | |
.value((data) => data.count); | |
const outerRadius = width / 2 - sliceGrow; | |
const innerRadius = 0; | |
const arc = d3.arc().innerRadius(innerRadius).outerRadius(outerRadius); | |
const calcTranslate = (data, move) => { | |
const moveAngle = data.startAngle + (data.endAngle - data.startAngle) / 2; | |
return `translate(${-move * Math.cos(moveAngle + Math.PI / 2)}, ${ | |
-move * Math.sin(moveAngle + Math.PI / 2) | |
})`; | |
}; | |
const mouseOver = (event, d) => { | |
// event.persist(); | |
d3.select(event.target) | |
.transition() | |
.duration(250) | |
.attr("opacity", ".7") | |
.attr("transform", calcTranslate(d, sliceMove)) | |
.attr("stroke", "#98898955") | |
.attr("stroke-width", 4) | |
.attrTween("d", () => { | |
const interpolator = d3.interpolate( | |
outerRadius, | |
outerRadius + sliceGrow | |
); | |
return (t) => { | |
const newOuterRadius = interpolator(t); | |
return arc.outerRadius(newOuterRadius)(d); | |
}; | |
}); | |
}; | |
const mouseOut = (event, d) => { | |
// event.persist(); | |
d3.select(event.target) | |
.transition() | |
.duration(250) | |
.attr("opacity", "1") | |
.attr("transform", "translate(0, 0)") | |
.attr("stroke", "transparent") | |
.attr("stroke-width", 0) | |
.attrTween("d", () => { | |
const interpolator = d3.interpolate(outerRadius, outerRadius); | |
return (t) => { | |
const newOuterRadius = interpolator(t); | |
return arc.outerRadius(newOuterRadius)(d); | |
}; | |
}); | |
}; | |
d3.select("#piechart") | |
.append("svg") | |
.attr("height", width + sliceMove * 2) | |
.attr("width", "100%") | |
.append("g") | |
.attr( | |
"transform", | |
`translate(${width / 2 + sliceMove}, ${width / 2 + sliceMove})` | |
) | |
.selectAll("path") | |
// .data(pie(dataSet)) | |
// .enter() | |
// .append("path") | |
.data(pie(dataSet)) | |
// .join("path") | |
.join( | |
(enter) => enter.append("path"), | |
(update) => update, | |
(exit) => exit.remove() | |
) | |
.on("mouseover", mouseOver) | |
.on("mouseout", mouseOut) | |
.attr("fill", function (d, i) { | |
return d.data.color; | |
}) | |
.transition() | |
.duration(2000) | |
.attrTween("d", (d) => { | |
const i = d3.interpolate({ startAngle: 0, endAngle: 0 }, d); | |
return (t) => { | |
return arc(i(t)); | |
}; | |
}); | |
}; | |
const ResponsivePieChart = () => { | |
useLayoutEffect(() => { | |
draw(); | |
}, []); | |
return <div id="piechart"></div>; | |
}; | |
export default ResponsivePieChart; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment