Hi, this is part 8 of "Using React (Hooks) with D3, and in this one, we visualize the Breaking Bad timeline, by working with time scales.
Code:
https://github.com/muratkemaldar/using-react-hooks-with-d3/tree/08-breaking-bad
Timeline component:
import React, { useRef, useEffect } from "react";
import { select, min, max, scaleTime, scaleLinear, axisBottom } from "d3";
import useResizeObserver from "./useResizeObserver";
// helper to transform date strings to date objects
const getDate = dateString => {
const date = dateString.split("-");
return new Date(date[2], date[0] - 1, date[1]);
};
function BBTimeline({ data, highlight }) {
const svgRef = useRef();
const wrapperRef = useRef();
const dimensions = useResizeObserver(wrapperRef);
// will be called initially and on every data change
useEffect(() => {
const svg = select(svgRef.current);
if (!dimensions) return;
const minDate = min(data, episode => getDate(episode.air_date));
const maxDate = max(data, episode => getDate(episode.air_date));
// maps dates to x-values
const xScale = scaleTime()
.domain([minDate, maxDate])
.range([0, dimensions.width]);
// maps numbers (character count) to y-values
const yScale = scaleLinear()
.domain([max(data, episode => episode.characters.length), 0])
.range([0, dimensions.height]);
// renders line for each episode
svg
.selectAll(".episode")
.data(data)
.join("line")
.attr("class", "episode")
.attr("stroke", episode =>
episode.characters.includes(highlight) ? "blue" : "black"
)
.attr("x1", episode => xScale(getDate(episode.air_date)))
.attr("y1", dimensions.height)
.attr("x2", episode => xScale(getDate(episode.air_date)))
.attr("y2", episode => yScale(episode.characters.length));
// x-axis
const xAxis = axisBottom(xScale);
svg
.select(".x-axis")
.style("transform", `translateY(${dimensions.height}px)`)
.call(xAxis);
// draw the gauge
}, [data, dimensions, highlight]);
return (
<div ref={wrapperRef} style={{ marginBottom: "2rem" }}>
<svg ref={svgRef}>
<g className="x-axis" />
</svg>
</div>
);
}
export default BBTimeline;
Hope you like it!
Top comments (0)