forked from CITKParus/P8-Panels
WEB APP: P8PSVG - поддержка групп, прозрачности заливки, верстка на Gridе
This commit is contained in:
parent
c61b8cc9c2
commit
46d078219f
@ -8,7 +8,7 @@
|
||||
//---------------------
|
||||
|
||||
import React, { useEffect, useRef, useState } from "react"; //Классы React
|
||||
import { IconButton, Icon } from "@mui/material"; //Интерфейсные элементы
|
||||
import { IconButton, Icon, Container, Grid } from "@mui/material"; //Интерфейсные элементы
|
||||
import PropTypes from "prop-types"; //Контроль свойств компонента
|
||||
|
||||
//---------
|
||||
@ -17,13 +17,13 @@ import PropTypes from "prop-types"; //Контроль свойств компо
|
||||
|
||||
//Стили
|
||||
const STYLES = {
|
||||
CANVAS: { width: "100%", height: "100%" },
|
||||
GRID_ITEM_CANVAS: { width: "100%", height: "100%" },
|
||||
CONTROLS: { justifyContent: "center", alignItems: "center", display: "flex" }
|
||||
};
|
||||
|
||||
//Структура элемента изображения
|
||||
const P8P_SVG_ITEM_SHAPE = PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
backgroundColor: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)])
|
||||
});
|
||||
|
||||
@ -32,7 +32,7 @@ const P8P_SVG_ITEM_SHAPE = PropTypes.shape({
|
||||
//-----------
|
||||
|
||||
//Интерактивные изображения SVG
|
||||
const P8PSVG = ({ data, items, onClick, onItemClick, canvasStyle }) => {
|
||||
const P8PSVG = ({ data, items, onClick, onItemClick, canvasStyle, fillOpacity }) => {
|
||||
//Собственное состояние
|
||||
const [state, setState] = useState({
|
||||
images: [],
|
||||
@ -47,8 +47,8 @@ const P8PSVG = ({ data, items, onClick, onItemClick, canvasStyle }) => {
|
||||
//Обработка нажатия на элемент изображения
|
||||
const handleClick = e => {
|
||||
let itemClickFired = false;
|
||||
if (e.target.id && items && onItemClick) {
|
||||
const item = items.find(item => item.id == e.target.id);
|
||||
if (items && onItemClick) {
|
||||
const item = items.find(item => item.id == e.target?.id || item.id == e.target?.parentElement?.id);
|
||||
if (item) {
|
||||
onItemClick({ item });
|
||||
itemClickFired = true;
|
||||
@ -62,11 +62,36 @@ const P8PSVG = ({ data, items, onClick, onItemClick, canvasStyle }) => {
|
||||
items.forEach(item => {
|
||||
const svgE = document.getElementById(item.id);
|
||||
if (svgE) {
|
||||
svgE.setAttribute("style", `${onItemClick ? "cursor: pointer" : ""}; ${item.backgroundColor ? `fill: ${item.backgroundColor}` : ""}`);
|
||||
//Запомним старый стиль элемента
|
||||
let styleOld = svgE.getAttribute("style") || "";
|
||||
if (styleOld && !styleOld.endsWith(";")) styleOld = `${styleOld};`;
|
||||
//Сформируем стиль для заливки
|
||||
let fillStyle = "";
|
||||
if (item.backgroundColor) fillStyle = `fill: ${item.backgroundColor}; ${fillOpacity ? `opacity: ${fillOpacity};` : ""}`;
|
||||
//Сформируем стиль для курсора
|
||||
let cursorStyle = "";
|
||||
if (onItemClick) cursorStyle = "cursor: pointer;";
|
||||
//Добавим элемент для всплывающей подсказки
|
||||
let titleE = null;
|
||||
if (item?.title) {
|
||||
const titleE = document.createElementNS("http://www.w3.org/2000/svg", "title");
|
||||
titleE = document.createElementNS("http://www.w3.org/2000/svg", "title");
|
||||
titleE.textContent = item.title;
|
||||
svgE.replaceChildren(titleE);
|
||||
svgE.appendChild(titleE);
|
||||
}
|
||||
//Если нем попалась группа
|
||||
if (svgE.tagName == "g") {
|
||||
//Установим ей новые стили
|
||||
svgE.setAttribute("style", `${styleOld}${cursorStyle}`);
|
||||
//И заливку всем дочерним элементам
|
||||
if (fillStyle)
|
||||
for (const child of svgE.children) {
|
||||
let childStyleOld = child.getAttribute("style") || "";
|
||||
if (childStyleOld && !childStyleOld.endsWith(";")) childStyleOld = `${childStyleOld};`;
|
||||
child.setAttribute("style", `${childStyleOld}${fillStyle}`);
|
||||
}
|
||||
} else {
|
||||
//Это простой элемент, не группа - просто выставляем стили
|
||||
svgE.setAttribute("style", `${styleOld}${cursorStyle}${fillStyle}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -121,16 +146,20 @@ const P8PSVG = ({ data, items, onClick, onItemClick, canvasStyle }) => {
|
||||
}, [state.images, state.currentImage, items]);
|
||||
|
||||
//При прокрутке изображений назад
|
||||
const handlePrevClick = () => switchImage(-1);
|
||||
const handlePrevClick = () => switchImage(1);
|
||||
|
||||
//При прокрутке изображений вперёд
|
||||
const handleNextClick = () => switchImage(1);
|
||||
const handleNextClick = () => switchImage(-1);
|
||||
|
||||
//Генерация содержимого
|
||||
return (
|
||||
<div>
|
||||
<div ref={svgContainerRef} style={{ ...STYLES.CANVAS, ...(canvasStyle ? canvasStyle : {}) }}></div>
|
||||
<Container>
|
||||
<Grid container direction="column" justifyContent="center" alignItems="center" spacing={0}>
|
||||
<Grid item xs={12} sx={STYLES.GRID_ITEM_CANVAS}>
|
||||
<div ref={svgContainerRef} style={{ ...(canvasStyle ? canvasStyle : {}) }}></div>
|
||||
</Grid>
|
||||
{state.imagesCount > 1 ? (
|
||||
<Grid item xs={12}>
|
||||
<div style={STYLES.CONTROLS}>
|
||||
<IconButton onClick={handlePrevClick}>
|
||||
<Icon>arrow_left</Icon>
|
||||
@ -139,8 +168,10 @@ const P8PSVG = ({ data, items, onClick, onItemClick, canvasStyle }) => {
|
||||
<Icon>arrow_right</Icon>
|
||||
</IconButton>
|
||||
</div>
|
||||
</Grid>
|
||||
) : null}
|
||||
</div>
|
||||
</Grid>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
@ -150,7 +181,8 @@ P8PSVG.propTypes = {
|
||||
items: PropTypes.arrayOf(P8P_SVG_ITEM_SHAPE),
|
||||
onClick: PropTypes.func,
|
||||
onItemClick: PropTypes.func,
|
||||
canvasStyle: PropTypes.object
|
||||
canvasStyle: PropTypes.object,
|
||||
fillOpacity: PropTypes.string
|
||||
};
|
||||
|
||||
//----------------
|
||||
|
@ -24,7 +24,7 @@ const STYLES = {
|
||||
CONTAINER: { textAlign: "center", paddingTop: "20px" },
|
||||
TITLE: { paddingBottom: "15px" },
|
||||
FORM: { justifyContent: "center", alignItems: "center" },
|
||||
SVG: { width: "95vw", height: "30vw", display: "flex", justifyContent: "center" }
|
||||
SVG: { height: "30vw", display: "flex", justifyContent: "center" }
|
||||
};
|
||||
|
||||
//-----------
|
||||
|
Loading…
x
Reference in New Issue
Block a user