diff --git a/labs/lab5/src/App.jsx b/labs/lab5/src/App.jsx
index ded1a2d..6587242 100644
--- a/labs/lab5/src/App.jsx
+++ b/labs/lab5/src/App.jsx
@@ -2,6 +2,7 @@ import { useState } from 'react'
import Table from './components/Table.jsx';
import buildings from './data.js';
import './CSS/App.css'
+import Chart from './components/Chart.jsx'
import Task from './Task.jsx'
function App() {
const [count, setCount] = useState(0)
@@ -9,7 +10,7 @@ function App() {
return (
Самые высокие здания и сооружения
-
+
{/*
*/}
diff --git a/labs/lab5/src/CSS/App.css b/labs/lab5/src/CSS/App.css
index f716aeb..f6c127e 100644
--- a/labs/lab5/src/CSS/App.css
+++ b/labs/lab5/src/CSS/App.css
@@ -32,3 +32,25 @@ span:hover,.selected {
background-color: blue;
color:white;
}
+
+
+
+svg {
+ width: 800px;
+ height: 400px;
+}
+
+svg path, line {
+ fill: none;
+ stroke: black;
+ width: 1px;
+}
+
+svg text {
+ font: 8px Verdana;
+}
+
+.bad-selection{
+ color: red;
+ border: solid thin red;
+}
\ No newline at end of file
diff --git a/labs/lab5/src/components/Chart.jsx b/labs/lab5/src/components/Chart.jsx
index 883a07a..19d537e 100644
--- a/labs/lab5/src/components/Chart.jsx
+++ b/labs/lab5/src/components/Chart.jsx
@@ -1,32 +1,69 @@
-const Chart = (props) => {
+import { useState } from "react";
+import ChartDraw from './ChartDraw.jsx';
+import * as d3 from "d3";
- return (
+
+const Chart = (props) => {
+ const [ox, setOx] = useState("Страна");
+ const [oy, setOy] = useState([true, false]);
+ const [graphType, setGraphType] = useState(0);
+
+ const handleSubmit = (event) => {
+ event.preventDefault();
+ setOx(event.target["ox"].value);
+ setOy([event.target["oy"][0].checked, event.target["oy"][1].checked]);
+ setGraphType(event.target["graphType"].value);
+ }
+
+ const createArrGraph = (data, key) => {
+ const groupObj = d3.group(data, d => d[key]);
+ let arrGraph = [];
+ for (let entry of groupObj) {
+ let minMax = d3.extent(entry[1].map(d => d['Высота']));
+ arrGraph.push({ labelX: entry[0], values: minMax });
+ }
+ return arrGraph;
+ }
+
+ return (
<>
Визуализация
-
- >
- )
+
+
+ >
+ )
}
export default Chart;
\ No newline at end of file
diff --git a/labs/lab5/src/components/ChartDraw.jsx b/labs/lab5/src/components/ChartDraw.jsx
new file mode 100644
index 0000000..c7f5b26
--- /dev/null
+++ b/labs/lab5/src/components/ChartDraw.jsx
@@ -0,0 +1,157 @@
+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
+ };
+
+ // вычисляем ширину и высоту области для вывода графиков
+ const boundsWidth = width - margin.left - margin.right;
+ const boundsHeight = height - margin.top - margin.bottom;
+
+ useEffect(() => {
+ if(boundsWidth<0||boundsHeight<0){
+ return;
+ }
+ const svg = d3.select(chartRef.current);
+ // выводим прямоугольник,
+ svg
+ .append("rect")
+ .attr("x", margin.left)
+ .attr("y", margin.top)
+ .attr("width", boundsWidth)
+ .attr("height", boundsHeight)
+ .style("fill", "lightgrey");
+ console.log(props)
+ drawGraph(props.data,props.ox,props.minMax[0],props.minMax[1],Number(props.graphType))
+ });
+
+ return (
+
+ )
+}
+
+export default ChartDraw;
\ No newline at end of file
diff --git a/labs/lab5/src/components/TableRow.jsx b/labs/lab5/src/components/TableRow.jsx
index 2446adf..567a60c 100644
--- a/labs/lab5/src/components/TableRow.jsx
+++ b/labs/lab5/src/components/TableRow.jsx
@@ -12,7 +12,7 @@ const TableRow = (props) => {
: props.row.map((item, index) => {item} | );
return(
- <> {cells} >
+ <>{cells}>
)
}