решено! Огромное спасибо, Мехди!
Теперь все работает!
Получите полный исходный код, используя React JS:
import React, { useEffect, useRef, useState } from "react";
import {
select,
axisBottom,
min,
max,
scaleLinear,
axisLeft,
area,
line,
curveMonotoneX,
} from "d3";
import useResizeObserver from "./useResizeObserver";
const data = [
{ x: 0, low: 100, high: 245 },
{ x: 3, low: 97, high: 244 },
{ x: 5, low: 94, high: 243 },
{ x: 8, low: 92, high: 242 },
{ x: 10, low: 90, high: 240 },
{ x: 13, low: 88, high: 237 },
{ x: 16, low: 85, high: 234 },
{ x: 18, low: 83, high: 232 },
{ x: 20, low: 80, high: 230 },
{ x: 22, low: 79, high: 225 },
{ x: 25, low: 69, high: 220 },
{ x: 28, low: 49, high: 215 },
{ x: 30, low: 0, high: 210 },
{ x: 40, low: 0, high: 120 },
{ x: 49, low: 0, high: 0 },
];
const points = [
[
{ x: 0, y: 0 },
{ x: 10, y: 70 },
{ x: 20, y: 150 },
{ x: 25, y: 180 },
{ x: 30, y: 245 },
],
[
{ x: 14, y: 0 },
{ x: 27, y: 100 },
{ x: 30, y: 150 },
{ x: 38, y: 245 },
],
];
function StackedBarChart() {
const svgRef = useRef();
const wrapperRef = useRef();
const dimensions = useResizeObserver(wrapperRef);
const [init, setInit] = useState(false);
useEffect(() => {
if (data.length && points.length && !init) {
setInit(true);
const svg = select(svgRef.current);
const { width, height } =
dimensions || wrapperRef.current.getBoundingClientRect();
const xScale = scaleLinear()
.domain([min(data, (d) => d.x), max(data, (d) => d.x)])
.range([0, width]);
const yScale = scaleLinear()
.domain([0, max(data, (d) => d.high)])
.range([height, 0]);
const xAxis = axisBottom(xScale);
svg.append("g").attr("transform", `translate(0, ${height})`).call(xAxis);
const yAxis = axisLeft(yScale);
svg.append("g").call(yAxis);
const areaGenerator = area()
.defined((d) => true)
.x((d) => xScale(d.x))
.y0((d) => yScale(d.low))
.y1((d) => yScale(d.high))
.curve(curveMonotoneX);
const areaData1 = areaGenerator(data);
const lineGenerator = line()
.x((p) => xScale(p.x))
.y((p) => yScale(p.y));
const polygon1 = points.map((point) =>
point.map((item) => [item.x, item.y])
);
const arrPolygons = [...polygon1[0].reverse(), ...polygon1[1]];
const clip = svg.append("g").append("clipPath").attr("id", "clip");
clip
.selectAll("#pol1")
.data([arrPolygons])
.enter()
.append("polygon")
.attr("id", "pol1")
.attr("points", (d) => {
return d.map((i) => [xScale(i[0]), yScale(i[1])]).join(" ");
});
const areaChart1 = svg
.append("path")
.attr("id", "area1")
.attr("class", "layer1")
.style("fill", "orange")
.attr("d", areaData1);
const areaChart = svg
.append("path")
.attr("id", "area")
.attr("class", "layer")
.attr("clip-path", "url(#clip)")
.style("fill", "blue")
.attr("d", areaData1);
svg
.append("path")
.attr("class", "line1")
.attr("d", lineGenerator(points[0]));
svg
.append("path")
.attr("class", "line2")
.attr("d", lineGenerator(points[1]));
}
}, [data, dimensions, init, points]);
return (
<>
<div ref={wrapperRef} style={{ marginBottom: "2rem" }}>
<svg ref={svgRef} />
</div>
</>
);
}
export default StackedBarChart;