/* Парус 8 - Панели мониторинга Компонент: Интерактивные изображения SVG */ //--------------------- //Подключение библиотек //--------------------- import React, { useEffect, useRef, useState } from "react"; //Классы React import { IconButton, Icon } from "@mui/material"; //Интерфейсные элементы import PropTypes from "prop-types"; //Контроль свойств компонента //--------- //Константы //--------- //Стили const STYLES = { CANVAS: { width: "100%", height: "100%" }, CONTROLS: { justifyContent: "center", alignItems: "center", display: "flex" } }; //Структура элемента изображения const P8P_SVG_ITEM_SHAPE = PropTypes.shape({ id: PropTypes.string.isRequired, backgroundColor: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]) }); //----------- //Тело модуля //----------- //Интерактивные изображения SVG const P8PSVG = ({ data, items, onClick, onItemClick, canvasStyle }) => { //Собственное состояние const [state, setState] = useState({ images: [], currentImage: 0, imagesCount: 0 }); //Ссылки на DOM const svgContainerRef = useRef(null); const svgRef = useRef(null); //Обработка нажатия на элемент изображения const handleClick = e => { let itemClickFired = false; if (e.target.id && items && onItemClick) { const item = items.find(item => item.id == e.target.id); if (item) { onItemClick({ item }); itemClickFired = true; } } if (!itemClickFired && onClick) onClick(e); }; //Формирование интерактивных элементов изображения const makeSVGItems = () => { items.forEach(item => { const svgE = document.getElementById(item.id); if (svgE) { svgE.setAttribute("style", `${onItemClick ? "cursor: pointer" : ""}; ${item.backgroundColor ? `fill: ${item.backgroundColor}` : ""}`); if (item?.title) { const titleE = document.createElementNS("http://www.w3.org/2000/svg", "title"); titleE.textContent = item.title; svgE.replaceChildren(titleE); } } }); }; //Загрузка изображения const loadSVG = () => { const images = data .split("") .filter(i => i) .map(i => i + ""); setState(pv => ({ ...pv, images, imagesCount: images.length, currentImage: 0 })); }; //Отображение текущего изображения const showSVG = () => { if (state.imagesCount > 0) { const parser = new DOMParser(); const doc = parser.parseFromString(state.images[state.currentImage], "image/svg+xml"); svgRef.current = doc.documentElement; svgRef.current.onclick = handleClick; svgContainerRef.current.replaceChildren(svgRef.current); if (items) makeSVGItems(items); } }; //Переключение текущего изображения const switchImage = direction => { setState(pv => ({ ...pv, currentImage: direction > 0 ? pv.currentImage + 1 >= pv.imagesCount ? 0 : pv.currentImage + 1 : pv.currentImage - 1 < 0 ? pv.imagesCount - 1 : pv.currentImage - 1 })); }; //При обновлении данных useEffect(() => { loadSVG(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [data]); //При загрузке изображения useEffect(() => { showSVG(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [state.images, state.currentImage, items]); //При прокрутке изображений назад const handlePrevClick = () => switchImage(-1); //При прокрутке изображений вперёд const handleNextClick = () => switchImage(1); //Генерация содержимого return (