Skip to content

Instantly share code, notes, and snippets.

@dibyanshusinha
Last active May 7, 2021 11:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dibyanshusinha/68047595bbd346406146f84f1519c6a5 to your computer and use it in GitHub Desktop.
Save dibyanshusinha/68047595bbd346406146f84f1519c6a5 to your computer and use it in GitHub Desktop.
BlackBoxing Approach D3 with React.
// 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