网站给他人做付刑事责任,建立网站就是制作网页吗,今天体育新闻最新消息,近期新闻在之前的弹窗的设计中#xff0c;有两处地方现在做一点小小的优化#xff0c;就是把_Draggable.jsx中的 onPointerEnter 事件 用 useLayoutEffect来规换#xff0c;效果更佳#xff0c;同样的#xff0c;在_ModelContainer.jsx中也是一样。如下所示#xff1a; _Draggabl…在之前的弹窗的设计中有两处地方现在做一点小小的优化就是把_Draggable.jsx中的 onPointerEnter 事件 用 useLayoutEffect来规换效果更佳同样的在_ModelContainer.jsx中也是一样。如下所示 _Draggable.jsx
/** jsxImportSource emotion/react */
import { css, keyframes } from emotion/react
import React, { useEffect, useLayoutEffect, useRef, useState } from react;
import Box from mui/material/Box;
import { useOutsideClick } from ./_useOutsideClick;
import { useWindowSize } from ./_useWindowSize;
import { minHeight, minWidth } from ./_ModelConfigure;//弹窗的动画
const attentionKeyframes keyframesfrom,to {transform: scale(1);}50% {transform: scale(1.03);}
;//弹窗的开始时动画
const anim cssanimation: ${attentionKeyframes} 400ms ease;
;//弹窗的结束时动画
const stopAnim cssanimation: null;
;const draggableHandler .model-handler; // 拖动句柄的类名/*** 拖动组件使被包裹的组件可以拖动支持拖动句柄* param {是否启用拖动句柄 } enableHandler * param {拖动句柄的类名} draggableHandler* param {外部点击事件} onOutsideClick*/
export default function Draggable({children, // 子组件enableDragging true,enableHandler false, // 是否启用拖动句柄stateMode
}) {const [attentionStyle, setAttentionStyle] useState(anim); // 弹窗动画,当点击外部时弹窗会有一个动画效果const [isDragging, setIsDragging] useState(false); // 是否正在拖动const [canDrag, setCanDrag] useState(true); // 是否可以触发拖动操作改变鼠标样式const normalPos useRef({ x: 0, y: 0 }); // 正常模式下弹窗的位置translate的值const minPos useRef({ x: 0, y: 0 }); // 最小化时的位置const maxPos { x: 0, y: 0 }; // 最大化时的位置因为最大化时弹窗的位置是固定的所以不需要ref// 当所有模式下的位置变化都是通过position来反映到UI上的所以position是唯一的位置状态const [position, setPosition] useState({x: 0, y: 0}); // 弹窗的位置translate的值// 当鼠标按下时记录鼠标的位置并以当前位置为基准进行拖动相对位置与position的差值为偏移量position为上一次的偏移量。// 因为采用的是translate的方式进行拖动这种方式下是以组件第一次渲染的位置为基准参考点也就是相对0,0的位置进行拖动的.// 正常模式下的偏移量const normalOffsetX useRef(0); // x轴偏移量const normalOffsetY useRef(0); // y轴偏移量// 最小化时的偏移量const minOffsetX useRef(0); // x轴偏移量const minOffsetY useRef(0); // y轴偏移量const initedRect useRef(0); // 初始化后的弹窗大小const wrapperRef useRef(null);const windowSize useWindowSize();// 当点击外部时弹窗会有一个注目动画效果useOutsideClick(wrapperRef, () {setAttentionStyle(anim);});// 弹窗注目动画的监听useEffect(function () {// 弹窗动画监听事件const listener (e) {if (e.type animationend) {setAttentionStyle(stopAnim);}};if (wrapperRef.current ! null) {wrapperRef.current.addEventListener(animationend, listener, true);}return () {if (wrapperRef.current ! null) {wrapperRef.current.removeEventListener(animationend, listener);}};}, []);// document的鼠标移动事件和鼠标抬起事件监听useEffect(() {// 鼠标移动事件const handleMouseMove (e) {if (isDragging) {switch (stateMode) {case 0:const xt e.clientX - minOffsetX.current;const yt e.clientY - minOffsetY.current;const xtMinTop -((windowSize.height - minHeight) / 2 - 10);const xtMaxTop (windowSize.height - minHeight) / 2 - 10;const xtMinLeft -((windowSize.width - minWidth) / 2 - 10);const xtMaxLeft (windowSize.width - minWidth) / 2 - 10;const xm xt xtMinLeft ? xtMinLeft : xt xtMaxLeft ? xtMaxLeft : xt;const ym yt xtMinTop ? xtMinTop : yt xtMaxTop ? xtMaxTop : yt;minPos.current { x: xm, y: ym};setPosition({ ...minPos.current });break;case 2:break;default:const xTmp e.clientX - normalOffsetX.current;const yTmp e.clientY - normalOffsetY.current;const minLetf -(windowSize.width - initedRect.current.width) / 2; const minTop -(windowSize.height - initedRect.current.height) / 2;const maxLeft (windowSize.width - initedRect.current.width) / 2;const maxTop (windowSize.height - initedRect.current.height) / 2;const x xTmp minLetf ? minLetf : xTmp maxLeft ? maxLeft : xTmp;const y yTmp minTop ? minTop : yTmp maxTop ? maxTop : yTmp;normalPos.current { x, y };setPosition({ ...normalPos.current });break;}}};// 鼠标抬起事件const handleMouseUp (e) {if (e.button ! 0) return;setIsDragging(false);};// 在相关的事件委托到document上if (isDragging) {document.addEventListener(mousemove, handleMouseMove);document.addEventListener(mouseup, handleMouseUp);} else {document.removeEventListener(mousemove, handleMouseMove);document.removeEventListener(mouseup, handleMouseUp);}// 组件卸载时移除事件return () {document.removeEventListener(mousemove, handleMouseMove);document.removeEventListener(mouseup, handleMouseUp);};}, [isDragging]);// 弹窗位置的监听, 每当弹窗状态改变时都会重新设置弹窗的位置, 将相应状态下的最后位置设置为当前位置// 但最小化状态下的位置有所不同因为最小化状态下的初始位置为左下角每次从其它状态切换到最小化状态时都要进行相同的设置。useEffect(() {switch (stateMode) {case 0:const initX -((windowSize.width - minWidth - 20) / 2);const initY windowSize.height / 2 - minHeight 10;setPosition({ x: initX, y: initY });minPos.current { x: initX, y: initY };break;case 2:setPosition({...maxPos.current});break;default:setPosition({ ...normalPos.current });break;}}, [stateMode]);// ref对象的鼠标移动事件用于判断是否在拖动句柄上const onMouseMove (e) {if (!enableDragging) {setCanDrag(false);return;}if (enableHandler) {const clickedElement e.target;// 检查鼠标点击的 DOM 元素是否包含特定类名if (clickedElement.classList.contains(draggableHandler)) {setCanDrag(true);} else {setCanDrag(false);}}}// ref对象的鼠标按下事件用于触发拖动操作// 如果启用了拖动句柄那么只有在拖动句柄上按下鼠标才会触发拖动操作// 否则直接按下鼠标就会触发拖动操作const handleMouseDown (e) {if (!enableDragging) return;switch (stateMode) {case 0:if (enableHandler) {// 判断是否在拖动句柄上const curElement e.target;// 检查鼠标点击的 DOM 元素是否包含特定类名if (curElement.classList.contains(draggableHandler)) {if (e.button ! 0) return;setIsDragging(true);minOffsetX.current e.clientX - minPos.current.x;minOffsetY.current e.clientY - minPos.current.y;} else {setCanDrag(false);}} else {if (e.button ! 0) return;setIsDragging(true);minOffsetX.current e.clientX - minPos.current.x;minOffsetY.current e.clientY - minPos.current.y;}return;case 2:return; default:if (enableHandler) {// 判断是否在拖动句柄上const curElement e.target;// 检查鼠标点击的 DOM 元素是否包含特定类名if (curElement.classList.contains(draggableHandler)) {if (e.button ! 0) return;setIsDragging(true);normalOffsetX.current e.clientX - normalPos.current.x;normalOffsetY.current e.clientY - normalPos.current.y;} else {setCanDrag(false);}} else {if (e.button ! 0) return;setIsDragging(true);normalOffsetX.current e.clientX - normalPos.current.x;normalOffsetY.current e.clientY - normalPos.current.y;}return;}};// 初始化时获取弹窗的大小此方法替代了onPointerEnter事件效果要好一些useLayoutEffect(() {if (wrapperRef.current) {const rect wrapperRef.current.getBoundingClientRect();initedRect.current {width: rect.width,height: rect.height,};}}, []);return (Boxref{wrapperRef}sx{{transform: translate(${position.x}px, ${position.y}px),cursor: canDrag ? isDragging ? grabbing : grab : default,transition: isDragging ? null : transform 200ms ease-in-out,}}onMouseDown{handleMouseDown}onMouseMove{onMouseMove}onClick{(e) { e.preventDefault(); e.stopPropagation(); }}// onPointerEnter{() {// if (initedRect.current 0 wrapperRef.current ! null) {// const rect wrapperRef.current.getBoundingClientRect();// initedRect.current {// width: rect.width,// height: rect.height,// };// }// }}Boxsx{{transform: ${isDragging ? scale(1.03) : scale(1)},transition: transform 200ms ease-in-out,}}css{attentionStyle}{children}/Box/Box);
}在 _ModelContainer.jsx中做如下更改 _ModelContainer.jsx
/** jsxImportSource emotion/react */
import { css } from emotion/react
import { useLayoutEffect, useRef, useState } from react;
import { Paper } from mui/material;
import { useModelState } from ./useModel;
import { infoLevel } from ./_ModelConfigure;// 计算不同状态下的高度
const calHeight (sizeMode, normalHeight) {switch (sizeMode) {case 0:return 45px;case 1:return normalHeight 0 ? normalHeight px : auto;case 2:return 100vh;default:return auto;}
}// 最大化时的固定样式
const maxSizeCss csswidth: 100vw;height: 100vh;top: 0;left: 0;;/*** 弹窗容器* param {*} param0 * returns */
const ModelContainer ({ children }) {const modelState useModelState();const {stateMode, // 弹窗的状态0: 最小化, 1: 正常, 2: 最大化level, // 弹窗的类型(主要是颜色类型)选项有default, error, warning, success, infoisDark, //是否是暗黑模式 } modelState;const [nomalSize, setNormalSize] useState({ width: 0, height: 0 });const containerRef useRef(null);useLayoutEffect(() {if (containerRef.current ! null) {const rect containerRef.current.getBoundingClientRect();setNormalSize({width: rect.width,height: rect.height,});}}, []);return (Paperref{containerRef}css{cssborder: 1px solid #A0A0A0;border-radius: 5px;width: ${ stateMode 2 ? 100vw : stateMode 0 ? 300px : 576px };height: ${ calHeight(stateMode, nomalSize.height) };overflow: hidden;max-width: 100%;max-height: 100vh;display: flex;flex-direction: column;background-color: ${isDark ? #333 : infoLevel[level] ? infoLevel[level].color : white };${stateMode 2 ? maxSizeCss : null};transition: all 0.3s;}{children}/Paper);
};export default ModelContainer;
以上两点做个补充。