/* * @Author: your name * @Date: 2022-04-22 15:23:10 * @Description: * @FilePath: /zl-large-screen/src/components/LargeScreenBoardBox/index.tsx */ import React, { useState, useEffect, useContext } from 'react'; import ReactDOM from 'react-dom'; import Moveable from 'react-moveable'; import Selecto from 'react-selecto'; import Icon from '../Icon/index'; // import ColorPick from 'zl-color-pick'; import LabelInputSelect from '../Unit/selectInput/index'; import VideoStream from '../VideoStream/index'; import H5Frame from '../H5Frame/index'; import DateAndTime from '../DateAndTime/index'; import ChartColorPicker from '../Unit/RegularColorPicker/ColorPicker'; import CustomizeMap from '../CustomizeMap/index'; import ClickButtonUpload from '../Unit/ClickButtonUpload/index'; import { Tooltip, Dropdown, Popover, Menu } from 'antd'; import { MoveableWrap } from './style'; import { ILargeScreenBoardBoxProps, IBoardItem, IContextMenus } from '../../type/LargeScreenBoard'; import { useRecoilState } from 'recoil'; import { currentMap } from '../../store/page'; import { Board } from '../LargeScreenBoard/index'; import { VideoJS } from '../VideoJS/index.jsx'; import 'zl-color-pick/dist/zl-color-pick.css'; import action from './action.svg'; // let dom = document; //避免多次监听 let getElementsTime = null; //监听dom渲染完没有 let clickTime; // 解决双击和拖拽事件冲突 const dom = document; // document const LargeScreenBoardBox: React.FC = (props) => { const { operationMenus, dragEnd, boardList: boardLists, UIBoardLists: UIBoardLists, boardMoveableList, targetList, changeCurrent, boardClick, boardMouseDown, elementClick, contextMenus, contextMenusEvent, boardEvent, updateKey, changeUpdateKey, groupMenus, mainBackgroundStyle = { backgroundSet: [], backgroundData: {}, backgroundTitle: '' }, // 当前页面配置 pageBackgroundStyle = { backgroundSet: [], backgroundData: {}, backgroundTitle: '' }, // 页面的页面配置 uiBackgroundStyle = { backgroundSet: [], backgroundData: {}, backgroundTitle: '' }, // ui的页面配置 pageList, uiList, theme, isPreviewShow, isScreening, backgroundSize, uiStateOn, scenceModelSrc, // 场景模型的src qiyong3D, // 是否启用3D pointEvent, // 是否禁用3D页面事件 ZLG, Line, Polygon, add3DType, add3DTypeList, hoverElement, PointLayer, PopupLayer, Popup, zoomValue, contextMenuId } = useContext(Board); let time = 0; const { scaleValue } = props; const [targets, setTargets] = useState([]); // 被框选的元素 const [otherClassList, setOtherClassList] = useState([]); // 被框选的元素 const [targetsData, setTargetsData] = useState([]); // 被框选的元素数据 const [boardList, setBoardList] = useState(boardLists); // 画布内元素的list const [UIBoardList, setUIBoardList] = useState(UIBoardLists); // 系统Ui内元素的list const [isSelectoDisabled, setIsSelectoDisabled] = useState(false); // 是否禁用selecto const [moveableKey, setMoveableKey] = useState(Math.random() * 100); // moveable的key const [moveableList, setMoveableList] = useState([]); // 所有的moveable const [boardMoveableListkeys, setBoardMoveableListkeys] = useState([]); //moveable更新完key的数据 const [hiddenContextMenu, setHiddenContextMenu] = useState(false); //隐藏右键菜单 const [showColorPickIndex, setShowColorPickIndex] = useState(null); //显示颜色拾取器 const [fontColorPick, setFontColorPick] = useState(false); //文字颜色拾取器 // const [canBeMove, setCanBeMove] = useState(false); //是否可以执行拖拽 const [moveTargets, setMoveTargets] = useState([]); //页面内设置框选的目标 const [elementStyle, setElementStyle] = useState({ width: 0, height: 0, x: 0, y: 0 }); //元素的宽高 const [showElementStyle, setShowElementStyle] = useState(false); //resize是不是显示数据 const [currentMapData, setCurrentMapData] = useRecoilState(currentMap); //记录当前地图 const moveableRef = React.useRef(null); // 移动框 // const moveTargetsRef = React.useRef([]); // 页面内设置框选的目标 const selectoRef = React.useRef(null); // 框选 const sceneBackgroundRef = React.useRef(''); // 3D背景,加载过一次就记住,不用每次都加载 const selectedGroupRef = React.useRef([]); // 被选中的组 // // moveable占位 useEffect(() => { // 根据targetList先生成空的元素数组。 const moveables = []; if (Array.isArray(targetList) && targetList.length > 0) { targetList.forEach(() => { moveables.push([]); }); } setMoveableList(moveables); dom.addEventListener('mousedown', isPopover); return () => { dom?.removeEventListener('mousedown', isPopover); }; }, []); //更新moveable的key useEffect(() => { let newBoardMoveableListkeys = boardMoveableList?.map((item) => { return { ...item, key: Math.random() }; }); setBoardMoveableListkeys(newBoardMoveableListkeys); }, [boardMoveableList]); // 监听组的右键事件 useEffect(() => { dom.addEventListener('contextmenu', groupContextMenu); return () => { dom.removeEventListener('contextmenu', groupContextMenu); }; }, [groupMenus, boardList, UIBoardLists]); // 切换选中系统UI useEffect(() => { setTargets([]); setTargetsData([]); }, [uiStateOn]); // 更新数据 useEffect(() => { setUIBoardList(UIBoardLists); }, [UIBoardLists]); // 更新数据 useEffect(() => { setBoardList(boardLists); }, [boardLists]); // 加载过一次就记住,减少重复加载 useEffect(() => { if (scenceModelSrc) { sceneBackgroundRef.current = scenceModelSrc; } }, [scenceModelSrc]); // 更新数据 useEffect(() => { const selectedData = []; const selected = []; let classNameList = []; selectedGroupRef.current = []; if (Array.isArray(boardList) && boardList.length > 0) { boardList.forEach((item, index) => { let isParentSelected = false; // 如果他是组,并且selected为true,则push if ( item?.type === 'group' && item?.selected && !item?.isLock && item?.isShow && !item?.isGroupLock && !item?.isGroupHidden && !selectedGroupRef?.current?.includes(item?.key) ) { selectedGroupRef.current.push(item?.key); } // 判断上层组有没有被选中,如果上层组选中了,即使lock/hidden也选中 if (item?.parentGroupIndex) { const parentIds = (item?.parentGroupIndex as String).split('-'); // 从后往前遍历parentIds,如果发现selectedGroupRef.current 包含此id,则当前元素要被选中 const len = parentIds.length; for(let i = len - 1;i > -1; i--){ if(!isParentSelected && selectedGroupRef.current.includes(parentIds?.[i])){ isParentSelected = true; } } } if ( isParentSelected || (item?.selected && !item?.isLock && item?.isShow && !item?.isGroupLock && !item?.isGroupHidden) ) { selected.push( document.querySelector(`.zl-${item?.key}`)?.parentElement ); selectedData.push({ index, item }); } if (!item?.selected) { classNameList.push(`.zl-${item?.key}`); } }); setOtherClassList(classNameList); setTargets(selected); setTargetsData(selectedData); // setMoveTargets(selected); } // 如果需要更新key // if (updateKey) { setMoveableKey(Math.random() * 100); changeUpdateKey(); // } setHiddenContextMenu(false); }, [boardList]); // 更新系统UI数据 useEffect(() => { const selectedData = []; const selected = []; let classNameList = []; if (Array.isArray(UIBoardList) && UIBoardList.length > 0) { UIBoardList.forEach((item, index) => { let isParentSelected = false; // 如果他是组,并且selected为true,则push if ( item?.type === 'group' && item?.selected && !item?.isLock && item?.isShow && !selectedGroupRef?.current?.includes(item?.key) ) { selectedGroupRef.current.push(item?.key); } // 判断上层组有没有被选中,如果上层组选中了,即使lock/hidden也选中 if (item?.parentGroupIndex) { const parentIds = (item?.parentGroupIndex as String).split('-'); if (selectedGroupRef.current.includes(parentIds?.[0])) { isParentSelected = true; } } if ( isParentSelected || (item?.selected && !item?.isLock && item?.isShow && !item?.isGroupLock && !item?.isGroupHidden) ) { selected.push( document.querySelector(`.zl-ui-${item?.key}`)?.parentElement ); selectedData.push({ index, item }); } if (!item?.selected) { classNameList.push(`.zl-ui-${item?.key}`); } }); setOtherClassList(classNameList); setTargets(selected); setTargetsData(selectedData); // setMoveTargets(selected); } // 如果需要更新key // if (updateKey) { setMoveableKey(Math.random() * 100); changeUpdateKey(); // } setHiddenContextMenu(false); }, [UIBoardList]); // 更新选中数据 useEffect(() => { setMoveableKey(Math.random() * 100); // changeUpdateKey(); const selectedData = []; const selected = []; const layerIndexs = []; let classNameList = []; // 遍历movetargets里的layerIndex moveTargets?.forEach((target) => { layerIndexs.push(target?.dataset?.layerIndex?.split('zl-ls-')[1]); }); if (!uiStateOn && Array.isArray(boardList) && boardList.length > 0) { boardList.forEach((item, index) => { if (layerIndexs.indexOf(item?.layerIndex) > -1) { selected.push( document.querySelector(`.zl-${item?.key}`)?.parentElement ); selectedData.push({ index, item }); } if (!item?.selected) { classNameList.push(`.zl-${item?.key}`); } }); setOtherClassList(classNameList); setTargets(selected); setTargetsData(selectedData); } else if ( uiStateOn && Array.isArray(UIBoardList) && UIBoardList.length > 0 ) { UIBoardList.forEach((item, index) => { if (layerIndexs.indexOf(item?.layerIndex) > -1) { selected.push( document.querySelector(`.zl-ui-${item?.key}`)?.parentElement ); selectedData.push({ index, item }); } if (!item?.selected) { classNameList.push(`.zl-ui-${item?.key}`); } }); setOtherClassList(classNameList); setTargets(selected); setTargetsData(selectedData); } }, [moveTargets]); // 更新数据 useEffect(() => { getElements(); }, [targetList]); // 控制颜色弹窗 const isPopover = (e) => { if ( !elementContains( document.querySelector('.zl-ls-board-content-group-menus'), e.target ) ) { let menuDOM = dom.querySelector('.zl-ls-board-content-group-menus'); if (menuDOM) { menuDOM.remove(); } } if ( !( elementContains(document.querySelector('.colorPopover'), e.target) || elementContains( document.querySelector('.zl-ls-board-font-color'), e.target ) ) ) { setFontColorPick(false); } }; const groupContent = (groupMenusList, index) => { return (
    {groupMenusList?.length > 0 && groupMenusList.map((item, indexs) => { if (item?.type === 'element') { return item?.label; } else { if (item?.children && item?.children?.length > 0) { return ( node.parentNode || document.body } destroyTooltipOnHide={true} >
  • {item?.label}
  • ); } else { return (
  • { if (item?.disabled) { return false; } else { contextMenusEvent(item?.key); setTimeout(() => { let menuDOM = dom.querySelector( '.zl-ls-board-content-group-menus' ); if (menuDOM) { menuDOM.remove(); } }, 200); } }} > {item?.label}
  • ); } } })}
); }; // // 组的右键事件 const groupContextMenu = (e) => { e && e.preventDefault(); // 如果存在多个父id数据为空的数据,显示组的右键,如果只有一个,不显示 let num = 0; let id; boardList.forEach((item) => { if (!item?.parentGroupIndex && item?.selected) { num++; id = item?.key; } }); //只能存在一个菜单 let menuDOM = dom.querySelector('.zl-ls-board-content-group-menus'); if (num > 1) { // 多个元素 if ( e?.target?.className && typeof e?.target?.className === 'string' && e?.target?.className?.includes('moveable-area') && !menuDOM ) { // 创建一个菜单,然后定位到body上 // const { x, y, width } = e.target?.getBoundingClientRect(); // const left = x + width; const left = e.clientX - 10; // const top = y; const top = e.clientY; let div = document.createElement('div'); div.className = 'context-menus'; div.style.position = 'fixed'; div.style.left = left + 'px'; div.style.top = top + 'px'; div.style.zIndex = '1100'; const menu = (
{groupContent(groupMenus, -1)}
); ReactDOM.render(menu, div); document.body.appendChild(div); } } else { // 组 if ( e?.target?.className && typeof e?.target?.className === 'string' && e?.target?.className?.includes('moveable-area') && !menuDOM ) { boardEvent('groupContextMenu', id); } } }; // 放置 const drop = (e) => { e.preventDefault(); let target = e.target; // 判断放置的元素是不是画布,不是的话向上查找 target = document.querySelector('.zl-ls-board-content-active-area'); const xY = { x: Math.ceil( (e.clientX - target?.getBoundingClientRect().left) / scaleValue ), y: Math.ceil( (e.clientY - target?.getBoundingClientRect().top) / scaleValue ) }; const data = e?.dataTransfer?.getData('text/plain'); if (data[0] === '{' && data[data.length - 1] === '}') { dragEnd?.(JSON.parse(e?.dataTransfer?.getData('text/plain')), xY); setCurrentMapData(-1); } }; // 放置 const dropUI = (e) => { e.preventDefault(); let target = e.target; // 判断放置的元素是不是画布,不是的话向上查找 target = document.querySelector('.zl-ls-board-content-active-area'); const xY = { x: Math.ceil( (e.clientX - target?.getBoundingClientRect().left) / scaleValue ), y: Math.ceil( (e.clientY - target?.getBoundingClientRect().top) / scaleValue ) }; const data = e?.dataTransfer?.getData('text/plain'); if (data[0] === '{' && data[data.length - 1] === '}') { dragEnd?.(JSON.parse(e?.dataTransfer?.getData('text/plain')), xY); setCurrentMapData(-1); } }; // 点击元素 const onClick = (item: IBoardItem, type: string) => { setFontColorPick(false); setShowColorPickIndex(-1); if (type !== 'clickCurrent') { changeCurrent(type, [item]); } setElementStyle({ x: item?.x + item?.width, y: item?.y + item?.height, height: item?.height, width: item?.width }); }; // 点击moveable获取元素 const onMoveableClick = (e, item) => { elementClick({ type: 'element', e, item }); }; // // 点击moveable组获取元素 // const onMoveableGroupClick = (e, item) => { // elementClick({ type: 'group', e, item }); // }; // 开始拖拽 const onDragStart = (e: MouseEvent) => { setHiddenContextMenu(true); // 切换右键菜单 boardEvent('dragElementStart', { e, items: targetsData }); }; // 拖拽中 const onDrag = (e: any) => { !isSelectoDisabled && setIsSelectoDisabled(true); // 切换选择框 boardEvent('dragElement', { e, items: targetsData }); }; // 拖拽结束 const onDragEnd = (e: MouseEvent) => { setIsSelectoDisabled(false); boardEvent('dragElementEnd', { e, items: targetsData }); }; // 拖拽组开始 const onDragGroupStart = (e: MouseEvent) => { setIsSelectoDisabled(true); boardEvent('dragGroupStart', { e, items: targetsData }); }; // 拖拽组中 const onDragGroup = (e: MouseEvent) => { boardEvent('dragGroup', { e, items: targetsData }); }; // 拖拽组结束 const onDragGroupEnd = (e: MouseEvent) => { setIsSelectoDisabled(false); boardEvent('dragGroupEnd', { e, items: targetsData }); }; // resize开始 const onResizeStart = (e: MouseEvent) => { setIsSelectoDisabled(true); boardEvent('resizeElementStart', { e, items: targetsData }); }; // resize中 const onResize = (e: MouseEvent) => { boardEvent('resizeElement', { e, items: targetsData }); }; // resize结束 const onResizeEnd = (e: MouseEvent) => { setIsSelectoDisabled(false); boardEvent('resizeElementEnd', { e, items: targetsData }); }; // resize开始 const onResizeGroupStart = (e: MouseEvent) => { setIsSelectoDisabled(true); boardEvent('resizeGroupStart', { e, items: targetsData }); }; // resize中 const onResizeGroup = (e: MouseEvent) => { boardEvent('resizeGroup', { e, items: targetsData }); }; // resize结束 const onResizeGroupEnd = (e: MouseEvent) => { setIsSelectoDisabled(false); boardEvent('resizeGroupEnd', { e, items: targetsData }); }; // 双击结束 const onDoubleClick = (item, type) => { clearTimeout(clickTime); setIsSelectoDisabled(false); if (!item?.selected) { changeCurrent(type, [item]); } }; const isMenuCanUse = (statusArr: string | string[], item: IBoardItem) => { if (statusArr) { if (typeof statusArr === 'string') { statusArr = [statusArr]; } if (Array.isArray(statusArr) && statusArr?.length > 0) { return statusArr.some((arrItem) => { if (arrItem.indexOf('!') === -1) { return item[arrItem]; } else { return !item[arrItem.slice(1)]; } }); } } return false; }; // 左上角菜单事件 const operationClick = (type, item, data, e) => { if (!item?.disabled && !item?.options) { boardEvent('operationChange', { key: type, data }); } if ( typeof e?.target?.className === 'string' && e?.target?.className?.includes('zl-ls-board-operation-menu-color') ) { if (type === 'fontColor') { setFontColorPick(!fontColorPick); } else { setFontColorPick(false); } if (type !== 'chartColor') { setShowColorPickIndex(-1); } } else if (type !== 'fontColor' && type !== 'chartColor') { setFontColorPick(false); setShowColorPickIndex(-1); } }; // 左上角菜单的下拉项 const overlayOperationMenus = (options) => { const menus = options.map((item) => { const { title, key, icon, disabled } = item; if (!item?.hidden) { return { label: (

boardEvent('operationChange', { key, item })} > {title}

), key }; } }); return ; }; // // 阻止颜色选择器点击事件影响选区 // const pickColor = (e) => { // // e.preventDefault(); // }; const hex2Rgba = (bgColor, alpha = 1) => { let color = bgColor.slice(1); // 去掉'#'号 let rgba = [ parseInt('0x' + color.slice(0, 2)), parseInt('0x' + color.slice(2, 4)), parseInt('0x' + color.slice(4, 6)), alpha ]; return 'rgba(' + rgba.toString() + ')'; }; // 改变字体颜色 const changeFontColor = ({ color }) => { boardEvent('fontColorChange', { color: hex2Rgba(color) }); }; // 改变字体大小 const changeFontSize = (size: number, type: string) => { boardEvent('fontSizeChange', { size, type }); }; // // 文本颜色弹层 // const pickContent = (value: string) => ( //
// changeFontColor(params)} // handleCancel={(_) => {}} // handleParams={() => { // setFontColorPick(false); // }} // /> //
// ); // 切换显示 const changeColorPickIndex = (index) => { if (showColorPickIndex === index) { setShowColorPickIndex(-1); } else { setShowColorPickIndex(index); } }; // 回调函数,更新最终返回参数 const handleParams = (params) => { if (!params?.visible) { setShowColorPickIndex(-1); setFontColorPick(false); } }; // 回调函数,更新最终返回参数 const handleChange = (params, index) => { setShowColorPickIndex(-1); setFontColorPick(false); boardEvent('chartColorChange', { value: params, index }); }; // 生成颜色 const buildBgColor = (colors: string | object) => { if (typeof colors === 'string') { return colors; } else { return commonGradientStyle(colors); } }; // 更加渐变色对象生成button样式 const commonGradientStyle = (colors) => { const { colorStops, angle = 0 } = colors || {}; const [start, end] = colorStops || ['', '']; return `linear-gradient(${angle + 90}deg, ${start?.color || start} , ${ end?.color || end } )`; }; // 打开颜色设置面板 const openSettingCard = () => { boardEvent('openSettingCard'); }; // 图表系列颜色弹层 const pickChartContent = ( fillType: string, isPure: boolean, color: any, index: number ) => { if (typeof color !== 'string') { color.colorGroups = []; color.colorGroups[0] = color?.colorStops[0]?.color || color?.colorStops[0] || color[0]; color.colorGroups[1] = color?.colorStops[1]?.color || color?.colorStops[1] || color[1]; } return (
{ if (index > -1) { handleChange(params, index); } else { changeFontColor(params); } }} handleCancel={(_) => {}} handleParams={handleParams} />
); }; // 渲染菜单内容 const menuContent = (item, data) => { if (item?.fontSize) { return ( ); } else if (Array.isArray(item?.options) && item?.options.length > 0) { return ( overlayOperationMenus(item?.options)} placement="bottomLeft" trigger="click" align={{ offset: [0, 14] }} > ); } else if (item?.color) { return (
); } else if (item?.chartColors) { if (item?.chartColors?.length > 0) { return item?.chartColors?.map((item2, index) => { if (index < 3) { const styleName = typeof item2?.color === 'string' ? 'background' : 'backgroundImage'; return (
changeColorPickIndex(index)} >
); } else if (index === 3) { return (
); } else { return <>; } }); } else { return <>; } } else { return (
); } }; // 点击菜单 const operation = (type, data) => { // 获取要渲染的菜单类型 const menus = operationMenus[type] ?? []; return (
{menus.map((item) => { if (item?.hidden) { return <>; } else { return (
operationClick?.(item?.key, item, data, e)} > {menuContent(item, data)}
); } })}
); }; // 右键菜单 const content = (list: IContextMenus[], itemValue: IBoardItem) => { return (
    {list?.length > 0 && list.map((item) => { if (item?.type === 'element') { const hidden = isMenuCanUse(item?.hidden, itemValue); if (hidden) { return <>; } else { return item?.label; } } else if (item?.type === 'uploadElement') { let disabled = typeof item?.disabled === 'boolean' ? item?.disabled : isMenuCanUse(item?.disabled, itemValue); let hidden = typeof item?.hidden === 'boolean' ? item?.hidden : isMenuCanUse(item?.hidden, itemValue); if (hidden) { return null; } // 如果有二级菜单 if (item?.children?.length > 0) { return (
  • { e.preventDefault(); e.stopPropagation(); // 关闭上传弹窗打开时的当前右键弹窗 contextMenusEvent('closeCurEleAllModal'); }} > { contextMenusEvent(item?.key, { value: rest }); }} labelIcon={ } style={{ width: item?.fileStyle?.width, color: disabled ? item?.fileStyle?.disableColor : item?.fileStyle?.color, fontSize: item?.fileStyle?.fontSize, marginLeft: item?.fileStyle?.marginLeft // padding: item?.fileStyle?.padding }} labelWarpStyle={{ display: 'flex', alignItems: 'center' }} {...item} />
  • ); } else { return (
  • { e.preventDefault(); e.stopPropagation(); // 关闭上传弹窗打开时的当前右键弹窗 contextMenusEvent('closeCurEleAllModal'); }} > { contextMenusEvent(item?.key, { value: rest }); }} labelIcon={ } style={{ width: item?.fileStyle?.width, color: disabled ? item?.fileStyle?.disableColor : item?.fileStyle?.color, fontSize: item?.fileStyle?.fontSize, marginLeft: item?.fileStyle?.marginLeft // padding: item?.fileStyle?.padding }} labelWarpStyle={{ display: 'flex', alignItems: 'center' }} {...item} />
  • ); } } else { let disabled = typeof item?.disabled === 'boolean' ? item?.disabled : isMenuCanUse(item?.disabled, itemValue); let hidden = typeof item?.hidden === 'boolean' ? item?.hidden : isMenuCanUse(item?.hidden, itemValue); if (hidden) { return null; } // 如果有二级菜单 if (item?.children?.length > 0) { return (
  • contextMenusEvent(item?.key)} > {item.label}
  • ); } else { return (
  • { if (!disabled) { contextMenusEvent(item?.key); } }} > {item.label}
  • ); } } })}
); }; // 组装className const joinClassName = ( key: string | number, isShow: string | number | boolean | object, isLock: string | number | boolean | object, isGroupLock: string | number | boolean | object, isGroupHidden: string | number | boolean | object, isSelect: boolean, isUi: boolean, pId: any, cId: any ) => { let name = `zl-ls-board-moveable-wrap zl-ls-moveable-${key}`; if (!isShow || isGroupHidden) { name += ' zl-ls-board-moveable-wrap-hidden'; } if (isLock || isGroupLock) { name += ' zl-ls-board-moveable-wrap-lock'; } if (isSelect) { name += ' zl-ls-board-moveable-wrap-select'; } if (key === hoverElement && isUi === uiStateOn) { name += ' zl-ls-board-moveable-wrap-hover'; } if (pId) { name += ` zl-ls-board-moveable-wrap-parent-${pId}`; } if (cId) { name += ` zl-ls-board-moveable-wrap-group`; } return name; }; // 框选结束 const onSelectStart = () => { boardEvent('selectElementStart'); }; // 框选结束 const onSelectEnd = (e: any, isShift: boolean) => { const canBeSelect = []; if (e.selected?.length > 0) { const indexs = []; e.selected.forEach((el, index) => { const classList = el.className; // 排除锁定和隐藏 if ( !classList?.includes('zl-ls-board-moveable-wrap-hidden') && !classList?.includes('zl-ls-board-moveable-wrap-lock') ) { // 获取被选中的layerIndex,添加selected indexs.push(el.dataset.layerIndex); canBeSelect.push(el); // 设置框选样式 el.classList.add('zl-ls-board-moveable-wrap-choose'); } }); canBeSelect?.length > 0 && setTargets(canBeSelect); } else { // 没选中任意一个,则清空选中状态。 document .querySelectorAll('.zl-ls-board-moveable-wrap-choose') .forEach((item) => { item.classList.remove('zl-ls-board-moveable-wrap-choose'); }); setTargets([]); } e.afterRemoved.forEach((el) => { el.classList.remove('zl-ls-board-moveable-wrap-choose'); }); boardEvent('selectElementEnd', { selectElements: canBeSelect, isShift }); }; // 获取可以动的元素,添加moveable框 const getElements = () => { clearTimeout(getElementsTime); if (Array.isArray(targetList) && targetList.length > 0) { // 当最后一个元素加载完成了 let lastKey; const lastItem = targetList[targetList.length - 1]; if (Array.isArray(lastItem)) { lastKey = lastItem[lastItem.length - 1]; } else { lastKey = targetList[targetList.length - 1]; } if (document.querySelector(`.zl-ls-moveable-${lastKey}`)) { // 根据targetList先生成真的元素数组。 const moveables = []; targetList.forEach((target) => { if (Array.isArray(target) && target.length > 0) { const moveableGroup = []; target.forEach((item) => { moveableGroup.push( document.querySelector(`.zl-ls-moveable-${item}`) ); }); moveables.push(moveableGroup); } else { moveables.push(document.querySelector(`.zl-ls-moveable-${target}`)); } }); setMoveableList(moveables); } else { getElementsTime = setTimeout(() => { getElements(); }, 100); } } }; // 点击画板 const clickBoard = (e) => { const { backgroundSet } = mainBackgroundStyle; if ( e?.target?.classList?.contains('zl-ls-board-content-box') || e?.target?.classList?.contains('zl-ls-board-content-active-area') ) { boardClick?.({ e, backgroundSet }); setCurrentMapData(-1); } }; // 画板鼠标按下 const mouseDownBoard = (e) => { const { backgroundSet } = mainBackgroundStyle; if ( e?.target?.classList?.contains('zl-ls-board-content-box') || e?.target?.classList?.contains('zl-ls-board-content-active-area') ) { setMoveTargets([]); // moveTargetsRef.current = []; boardMouseDown?.({ e, backgroundSet }); setCurrentMapData(-1); } }; //渲染元素 const renderElement = (item, index) => { if (item?.type === 'video') { return ( boardEvent('videoChange', rest)} isPreviewShow={isPreviewShow} isScreening={isScreening} /> ); } else if (item?.type === 'videoStream') { return ( ); } else if (item?.type === 'h5Frame') { return ( ); } else if (item?.type === 'dateAndTime') { return ( ); } else if (item?.type === 'gis') { time += 500; return ( boardEvent('gisZoom', value)} time={time} isPreviewShow={isPreviewShow} Line={Line} Polygon={Polygon} gisChildren={item?.gisChildren} isUpdateChildren={item?.isUpdateChildren} PointLayer={PointLayer} imgs={item?.imgs} PopupLayer={PopupLayer} Popup={Popup} zoomValue={zoomValue} /> ); } else { return item?.element; } }; const selectElement = (e) => { return ( document.querySelector('.zl-ls-board-content-menu') && e?.target && elementContains( document.querySelector('.zl-ls-board-content-menu'), e.target ) ); }; // 判断父元素是否包含某个元素 const elementContains = (parent, child) => { return parent !== child && parent?.contains(child); }; return (
{add3DType ? (
{add3DTypeList[add3DType]} { e.preventDefault(); e.stopPropagation(); boardEvent('exitEditStatus'); }} >
) : ( <> )} {/* 页面不显示,强制父级div重绘 */}
{scaleValue}
{/* 保持锚点大小 */} {uiStateOn && uiList && uiList?.length > 0 ? ( { // 控制selecto框选插件是否启用 return !isSelectoDisabled; }} hitRate={0} selectByClick={true} selectFromInside={true} toggleContinueSelect={['shift']} ratio={0} onDragStart={(e) => { const moveable = moveableRef.current; const target = e.inputEvent.target; if ( (moveable && moveable.isMoveableElement(target)) || targets.some((t) => t === target || (t as any).contains(target)) ) { e.stop(); } }} onSelectStart={(e) => { onSelectStart(); }} onSelect={(e) => { //点击导航栏 不走selectEnd if (selectElement(e?.inputEvent)) { return false; } const selected = []; e.selected?.forEach((item) => { if ( !( item?.className?.includes( 'zl-ls-board-moveable-wrap-lock' ) || item?.className?.includes( 'zl-ls-board-moveable-wrap-hidden' ) ) ) { selected.push(item); } }); setMoveTargets(selected); // moveTargetsRef.current = e.selected; e.added.forEach((el) => { el.classList.add('zl-ls-board-moveable-wrap-choose'); }); e.removed.forEach((el) => { el.classList.remove('zl-ls-board-moveable-wrap-choose'); }); }} onSelectEnd={(e) => { //点击导航栏 不走selectEnd if (selectElement(e?.inputEvent)) { return false; } const moveable = moveableRef.current; if (e.isDragStart) { e.inputEvent.preventDefault(); setTimeout(() => { moveable.dragStart(e.inputEvent); }); } onSelectEnd(e, e?.inputEvent?.shiftKey); }} /> ) : ( <> )} {uiList && uiList?.length > 0 ? (
e.preventDefault()} onDrop={dropUI} onDragOver={(e) => e.preventDefault()} style={{ position: 'absolute', zIndex: 1010, transform: `scale(${scaleValue})`, background: 'transparent', width: uiBackgroundStyle?.backgroundData?.width, height: uiBackgroundStyle?.backgroundData?.height, pointerEvents: uiStateOn ? 'auto' : 'none' }} > {showElementStyle ? ( {elementStyle?.width + ' X ' + elementStyle?.height} ) : ( <> )} {Array.isArray(UIBoardLists) && UIBoardLists?.length > 0 && UIBoardLists?.map((item, index) => { return (
onClick(item, 'contextMenuCurrent')} onMouseEnter={() => boardEvent('enterElement', item?.key)} onMouseLeave={() => boardEvent('leaveElement', item?.key)} > operation(item?.type, item)} trigger="click" overlayClassName="zl-ls-board-content-menu" visible={ item?.boxOperationVisible && scaleValue && !isSelectoDisabled && targets?.length === 1 } getPopupContainer={(triggerNode) => triggerNode.parentNode.parentNode.parentNode } destroyTooltipOnHide={true} >
{ e.preventDefault(); // 阻止内部元件拖拽事件 e.stopPropagation(); }} // onDoubleClick={() => // onDoubleClick(item, 'clickCurrent') // } className={`zl-ls-board-moveable-element ${ 'zl-ui-' + item?.key }`} style={{ width: item?.width, height: item?.height }} onMouseDown={() => onClick(item, 'clickCurrent')} > {item?.interactionList?.[1]?.compoentList?.[1]?.list ?.length > 0 ? (
事件动作
) : ( <> )} {renderElement(item, index)}
); })} {uiStateOn && targets?.length > 0 && UIBoardLists?.length > 0 ? ( -1 ? false : true} // 可拖拽 地图在编辑状态 禁止元素的拖拽事件 keepRatio={ targets?.length > 1 ? false : targetsData?.[0]?.item.keepRatio } // 保持宽高比 resizable={true} snappable={true} isDisplaySnapDigit={true} isDisplayInnerSnapDigit={false} snapDirections={{ top: true, left: true, bottom: true, right: true, center: true, middle: true }} elementSnapDirections={{ top: true, left: true, bottom: true, right: true, center: true, middle: true }} snapThreshold={5} maxSnapElementGuidelineDistance={null} elementGuidelines={otherClassList} throttleResize={0} throttleDrag={0} onClickGroup={(e) => { targets?.length > 1 && selectoRef.current.clickTarget(e.inputEvent, e.inputTarget); }} onDragStart={(e) => { onDragStart(e); }} onDrag={(e) => { const { target, beforeTranslate } = e; target.style.transform = `translate(${beforeTranslate[0]}px, ${beforeTranslate[1]}px)`; onDrag(e); }} onDragEnd={(e) => { const { target, lastEvent } = e; target.style.transform = `translate(0px, 0px)`; if (lastEvent) { const { beforeTranslate } = lastEvent; setElementStyle({ x: parseInt(target?.style.left) + parseInt(target?.style?.width) + beforeTranslate[0], y: parseInt(target?.style?.top) + parseInt(target?.style?.height) + beforeTranslate[1], height: parseInt(target?.style?.height), width: parseInt(target?.style?.width) }); } onDragEnd(e); }} onDragGroupStart={(e) => { onDragGroupStart(e); }} onDragGroup={(e) => { e.events.forEach((ev) => { ev.target.style.transform = ev.transform; }); onDragGroup(e); }} onDragGroupEnd={(e) => { e.events.forEach((ev) => { ev.target.style.transform = `translate(0px, 0px)`; }); onDragGroupEnd(e); }} onResizeStart={(e) => { onResizeStart(e); setShowElementStyle(true); }} onResize={(e) => { const newElementStyle = { ...elementStyle }; const { target, width, height, drag } = e; const beforeTranslate = drag.beforeTranslate; target.style.width = `${width}px`; target.style.height = `${height}px`; target.style.transform = `translate(${beforeTranslate[0]}px, ${beforeTranslate[1]}px)`; newElementStyle.width = parseInt(width); newElementStyle.height = parseInt(height); newElementStyle.x = width + drag?.left; newElementStyle.y = height + drag?.top; setElementStyle(newElementStyle); onResize(e); }} onResizeEnd={(e) => { const { target } = e; target.style.transform = `translate(0px, 0px)`; onResizeEnd(e); setShowElementStyle(false); }} onResizeGroupStart={(e) => { onResizeGroupStart(e); }} onResizeGroup={(e) => { const { events } = e; events.forEach((ev, i) => { ev.target.style.width = `${ev.width}px`; ev.target.style.height = `${ev.height}px`; ev.target.style.transform = `translate(${ev.drag.beforeTranslate[0]}px, ${ev.drag.beforeTranslate[1]}px)`; }); onResizeGroup(e); }} onResizeGroupEnd={(e) => { const { events } = e; events.forEach((ev) => { ev.target.style.transform = `translate(0px, 0px)`; }); onResizeGroupEnd(e); }} /> ) : ( <> )}
) : (
boardEvent('boardBoxAddPage')}> {mainBackgroundStyle?.backgroundTitle}
)}
{/* 系统UI层 */} {uiStateOn ? (
e.preventDefault()} onDrop={dropUI} onDragOver={(e) => e.preventDefault()} style={{ width: document?.querySelector('#contentBox')?.getBoundingClientRect() ?.width > Math.max( mainBackgroundStyle?.backgroundData?.width * scaleValue, pageBackgroundStyle?.backgroundData?.width * scaleValue ) ? '100%' : Math.max( mainBackgroundStyle?.backgroundData?.width * scaleValue, pageBackgroundStyle?.backgroundData?.width * scaleValue ), height: document?.querySelector('#contentBox')?.getBoundingClientRect() ?.height > Math.max( mainBackgroundStyle?.backgroundData?.height * scaleValue, pageBackgroundStyle?.backgroundData?.height * scaleValue ) ? '100%' : Math.max( mainBackgroundStyle?.backgroundData?.height * scaleValue, pageBackgroundStyle?.backgroundData?.height * scaleValue ) }} >
) : ( <> )} {/* 保持锚点大小 */} {pageList && pageList?.length > 0 ? (
e.preventDefault()} onDrop={drop} onDragOver={(e) => e.preventDefault()} style={{ ...pageBackgroundStyle?.backgroundData, transform: `scale(${scaleValue})`, backgroundRepeat: 'repeat', width: pageBackgroundStyle?.backgroundData?.width, height: pageBackgroundStyle?.backgroundData?.height, pointerEvents: add3DType ? 'none' : 'auto' }} > {showElementStyle ? ( {elementStyle?.width + ' X ' + elementStyle?.height} ) : ( <> )} {Array.isArray(boardList) && boardList?.length > 0 && boardList?.map((item, index) => { return (
onClick(item, 'contextMenuCurrent')} onMouseEnter={() => boardEvent('enterElement', item?.key)} onMouseLeave={() => boardEvent('leaveElement', item?.key)} > operation(item?.type, item)} trigger="click" overlayClassName="zl-ls-board-content-menu" visible={ item?.boxOperationVisible && scaleValue && !isSelectoDisabled && targets?.length === 1 } getPopupContainer={(triggerNode) => triggerNode.parentNode.parentNode.parentNode } destroyTooltipOnHide={true} >
{ e.preventDefault(); // 阻止内部元件拖拽事件 e.stopPropagation(); }} // onDoubleClick={() => // onDoubleClick(item, 'clickCurrent') // } className={`zl-ls-board-moveable-element ${ 'zl-' + item?.key }`} style={{ width: item?.width, height: item?.height }} onMouseDown={() => onClick(item, 'clickCurrent')} > {item?.interactionList?.[1]?.compoentList?.[1]?.list ?.length > 0 ? (
事件动作
) : ( <> )} {renderElement(item, index)}
); })} {!uiStateOn && targets?.length > 0 && boardList?.length > 0 ? ( -1 ? false : true} // 可拖拽 地图在编辑状态 禁止元素的拖拽事件 keepRatio={ targets?.length > 1 ? false : targetsData?.[0]?.item.keepRatio } // 保持宽高比 resizable={true} snappable={true} isDisplaySnapDigit={true} isDisplayInnerSnapDigit={false} snapDirections={{ top: true, left: true, bottom: true, right: true, center: true, middle: true }} elementSnapDirections={{ top: true, left: true, bottom: true, right: true, center: true, middle: true }} snapThreshold={5} maxSnapElementGuidelineDistance={null} elementGuidelines={otherClassList} throttleResize={0} throttleDrag={0} onClickGroup={(e) => { targets?.length > 1 && selectoRef.current.clickTarget(e.inputEvent, e.inputTarget); }} onDragStart={(e) => { onDragStart(e); }} onDrag={(e) => { const { target, beforeTranslate } = e; target.style.transform = `translate(${beforeTranslate[0]}px, ${beforeTranslate[1]}px)`; onDrag(e); }} onDragEnd={(e) => { const { target, lastEvent } = e; target.style.transform = `translate(0px, 0px)`; if (lastEvent) { const { beforeTranslate } = lastEvent; setElementStyle({ x: parseInt(target?.style.left) + parseInt(target?.style?.width) + beforeTranslate[0], y: parseInt(target?.style?.top) + parseInt(target?.style?.height) + beforeTranslate[1], height: parseInt(target?.style?.height), width: parseInt(target?.style?.width) }); } onDragEnd(e); }} onDragGroupStart={(e) => { onDragGroupStart(e); }} onDragGroup={(e) => { e.events.forEach((ev) => { ev.target.style.transform = ev.transform; }); onDragGroup(e); }} onDragGroupEnd={(e) => { e.events.forEach((ev) => { ev.target.style.transform = `translate(0px, 0px)`; }); onDragGroupEnd(e); }} onResizeStart={(e) => { onResizeStart(e); setShowElementStyle(true); }} onResize={(e) => { const newElementStyle = { ...elementStyle }; const { target, width, height, drag } = e; const beforeTranslate = drag.beforeTranslate; target.style.width = `${width}px`; target.style.height = `${height}px`; target.style.transform = `translate(${beforeTranslate[0]}px, ${beforeTranslate[1]}px)`; newElementStyle.width = parseInt(width); newElementStyle.height = parseInt(height); newElementStyle.x = width + drag?.left; newElementStyle.y = height + drag?.top; setElementStyle(newElementStyle); onResize(e); }} onResizeEnd={(e) => { const { target } = e; target.style.transform = `translate(0px, 0px)`; onResizeEnd(e); setShowElementStyle(false); }} onResizeGroupStart={(e) => { onResizeGroupStart(e); }} onResizeGroup={(e) => { const { events } = e; events.forEach((ev, i) => { ev.target.style.width = `${ev.width}px`; ev.target.style.height = `${ev.height}px`; ev.target.style.transform = `translate(${ev.drag.beforeTranslate[0]}px, ${ev.drag.beforeTranslate[1]}px)`; }); onResizeGroup(e); }} onResizeGroupEnd={(e) => { const { events } = e; events.forEach((ev) => { ev.target.style.transform = `translate(0px, 0px)`; }); onResizeGroupEnd(e); }} /> ) : ( <> )} {sceneBackgroundRef?.current ? (