Files
uni-web-site/labs/lab5/src/components/ChartDraw.jsx
2026-04-10 14:33:23 +10:00

144 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import * as d3 from "d3";
import { useEffect, useRef, useState } from "react";
function drawGraph(data, keyX, drawMin, drawMax, graphtype) {
// значения по оси ОХ
// создаем массив для построения графика
// console.log(keyX)
if(keyX=="Год"){
data = d3.sort(data, (x,y)=>Number(x["labelX"])-Number(y["labelX"]));
}
const svg = d3.select("svg")
svg.selectAll('*').remove();
// создаем словарь с атрибутами области вывода графика
const attr_area = {
width: parseFloat(svg.style('width')),
height: parseFloat(svg.style('height')),
marginX: 50,
marginY: 50
}
// создаем шкалы преобразования и выводим оси
const [scX, scY] = createAxis(svg, data, attr_area,[drawMin,drawMax]);
// рисуем график
const scaleYDomain = d3.extent(data.map(d => d.values[1]));
if (drawMin && drawMax){
createChart(svg, data, scX, scY, attr_area, "blue", 0,graphtype,0,scaleYDomain)
createChart(svg, data, scX, scY, attr_area, "red", 1,graphtype,0,scaleYDomain)
}
else if (drawMin) {
createChart(svg, data, scX, scY, attr_area, "blue", 0,graphtype,1,scaleYDomain)
}
else if (drawMax) {
createChart(svg, data, scX, scY, attr_area, "red", 1,graphtype,1,scaleYDomain)
}
}
function createAxis(svg, data, attr_area, selections) {
// находим интервал значений, которые нужно отложить по оси OY
// максимальное и минимальное значение и максимальных высот по каждой стране
const max = d3.max(data,d => d.values[Number(selections[1])]);
const min = d3.min(data,d => d.values[Number(selections[0])]);
// console.log(max,min,data)
// функция интерполяции значений на оси
// по оси ОХ текстовые значения
const scaleX = d3.scaleBand()
.domain(data.map(d => d.labelX))
.range([0, attr_area.width - 2 * attr_area.marginX]);
const scaleY = d3.scaleLinear()
.domain([min * 0.85, max * 1.1])
.range([attr_area.height - 2 * attr_area.marginY, 0]);
// создание осей
const axisX = d3.axisBottom(scaleX); // горизонтальная
const axisY = d3.axisLeft(scaleY); // вертикальная
// отрисовка осей в SVG-элементе
svg.append("g")
.attr("transform", `translate(${attr_area.marginX},
${attr_area.height - attr_area.marginY})`)
.call(axisX)
.selectAll("text") // подписи на оси - наклонные
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", d => "rotate(-45)");
svg.append("g")
.attr("transform", `translate(${attr_area.marginX}, ${attr_area.marginY})`)
.call(axisY);
return [scaleX, scaleY]
}
function createChart(svg, data, scaleX, scaleY, attr_area, color, valueIdx,isHistogram,horisontalScale,scaleYDomain) {
if (isHistogram){
svg.selectAll(".dot")
.data(data)
.enter()
.append("rect")
.attr("x", d => scaleX(d.labelX)+valueIdx*6)
.attr("y", d => scaleY(d.values[valueIdx]))
.attr("width",6*(horisontalScale+1))
.attr("height",d => scaleY(scaleYDomain[0]*0.85)-scaleY(d.values[valueIdx]))
.attr("transform", `translate(${attr_area.marginX}, ${attr_area.marginY})`)
.style("fill", color)
}
else{
const r = 4;
svg.selectAll(".dot")
.data(data)
.enter()
.append("circle")
.attr("r", r)
.attr("cx", d => scaleX(d.labelX) + scaleX.bandwidth() / 2+valueIdx*4)
.attr("cy", d => scaleY(d.values[valueIdx]))
.attr("transform", `translate(${attr_area.marginX}, ${attr_area.marginY})`)
.style("fill", color)
}
}
const ChartDraw = (props) => {
const chartRef = useRef(null);
const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0);
// заносим в состояния ширину и высоту svg-элемента
useEffect(() => {
const svg = d3.select(chartRef.current);
setWidth(parseFloat(svg.style('width')));
setHeight(parseFloat(svg.style('height')));
});
// задаем отступы в svg-элементе
const margin = {
top:10,
bottom:60,
left:40,
right:10
};
// вычисляем ширину и высоту области для вывода графиков
useEffect(() => {
// console.log(props)
drawGraph(props.data,props.ox,props.minMax[0],props.minMax[1],Number(props.graphType))
});
return (
<svg ref={chartRef} > </svg>
)
}
export default ChartDraw;