企业网站建设需要哪些步骤,古代中国建筑网站,广州市公司网站建设报价,海外贸易网站我在上次的Draggable组件的设计中给了一个简化的方法#xff0c;今天我来完善一下这个组件#xff0c;可用于任何可移动组件的包裹。完善后的效果如下所示#xff1a; 这个优化中#xff0c;增加了一个注目的效果#xff0c;还增加了触发可拖动区域的指定功能#xff0c;…我在上次的Draggable组件的设计中给了一个简化的方法今天我来完善一下这个组件可用于任何可移动组件的包裹。完善后的效果如下所示 这个优化中增加了一个注目的效果还增加了触发可拖动区域的指定功能这样我们对可拖动组件有更大的自由掌控。
在 Draggable 中增加以下两个Props enableHandler 是否启用可拖动句柄 draggableHandler 可拖动句柄字符
上面的draggableHandler就是一个类名如果 enableHandler 为true的情况下可拖动组件中含有 draggableHandler 指定的类名的子组件的 mouseDown 事件会触发拖动的移动效果。其实触发事件是通过Draggable代理实现的。
import React, { useEffect, useRef, useState } from react;
import Box from mui/material/Box;/*** 拖动组件* param {是否启用拖动句柄 } enableHandler * param {拖动句柄的类名} draggableHandler*/
export default function Draggable({children, // 子组件enableHandler false, // 是否启用拖动句柄draggableHandler .modelHandler // 拖动句柄的类名
}) {const [isDragging, setIsDragging] useState(false); // 是否正在拖动const [canDrag, setCanDrag] useState(!enableHandler); // 是否可以拖动const [position, setPosition] useState({ x: 0, y: 0 }); // 位置const offsetX useRef(0); // x轴偏移量const offsetY useRef(0); // y轴偏移量useEffect(() {// 鼠标移动事件const handleMouseMove (e) {if (isDragging) {setPosition({x: e.clientX - offsetX.current,y: e.clientY - offsetY.current});}};// 鼠标抬起事件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]);const onMouseMove (e) {if (enableHandler) {// 判断是否在拖动句柄上if (document.elementFromPoint(e.clientX, e.clientY).className.includes(draggableHandler)) {setCanDrag(true);} else {setCanDrag(false);}}}const handleMouseDown (e) {e.preventDefault();e.stopPropagation();if (enableHandler) {// 判断是否在拖动句柄上if (document.elementFromPoint(e.clientX, e.clientY).className.includes(draggableHandler)) {if (e.button ! 0) return;setIsDragging(true);offsetX.current e.clientX - position.x;offsetY.current e.clientY - position.y;}} else {if (e.button ! 0) return;setIsDragging(true);offsetX.current e.clientX - position.x;offsetY.current e.clientY - position.y;}};return (Boxsx{{position: relative,transform: translate(${position.x}px, ${position.y}px),cursor: canDrag ? isDragging ? grabbing : grab : default,transition: transform:,}}onMouseDown{handleMouseDown}onMouseMove{onMouseMove}Boxsx{{transform: ${isDragging ? scale(1.03) : scale(1)},transition: transform 200ms ease-in-out,}}{children}/Box/Box);
}上面的逻辑并不复杂通过过下面的语句可以找到含有指定类名的组件
document.elementFromPoint(e.clientX, e.clientY).className.includes(draggableHandler)这样就能判断当前鼠标是否处于指定的组件上并启动移动效果。 由于我们要实现抓取注目动画和移动动画都是通过 transform实现的但是我们只要缩放动画所以我用了两层Box包裹来分割transform属性。
为了测试这个Draggable, 我来做个小组件测试 draggableHandler 的作用。
/** jsxImportSource emotion/react */
import { css, jsx } from emotion/react
import Box from mui/material/Box;const titleBarCss cssbackground-color: #BDBDBD;padding: 8px;;const modelContentCss csspadding: 16px;;const ModalTest ({width 400, height 300, bgColor white}) {return (Box css{cssposition: relative;background-color: ${bgColor};border: 1px solid #ccc;border-radius: 5px;overflow: hidden;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);width: ${width}px;height: ${height}px;}Boxcss{titleBarCss}className.modelHandler这是标题/BoxBox css{modelContentCss}这是弹窗内容/Box/Box);
};export default ModalTest;上面的组件中我们在标题栏上增加了类名 modelHandler。很简单是不是。接下来我们来完整的测试
import React from react;
import Stack from mui/material/Stack;
import Draggable from ../../framework-kakaer/SModel/_Draggable;
import ModelTest from ../../framework-kakaer/SModel/_DraggableContent;export default function DraggableTest() {return (Stack spacing{3}Stack directionrow spacing{2}Draggablediv style{{ width: 200, height: 200, backgroundColor: red }}Draggable/div/DraggableDraggablediv style{{ width: 200, height: 200, backgroundColor: green }}Draggable/div/DraggableDraggablediv style{{ width: 200, height: 200, backgroundColor: blue }}Draggable/div/Draggable/StackStack directionrow spacing{2}Draggable enableHandler{true}ModelTest width{200} height{200} bgColoryellow //DraggableDraggableModelTest width{200} height{200} bgColor#FF9500 //DraggableDraggableModelTest width{200} height{200} bgColor#5AC8FA //Draggable/Stack/Stack);
}这样就有了开头的效果了。相当的完美是不是。