当前位置: 首页 > article >正文

拖拽移动(Semi Design)

一、使用场景

用于设置元素可被拖动改变位置,支持限制拖拽范围,支持自定义触发拖动的元素。

二、使用方式

可通过 customMove 自定义拖动后的位置处理,该参数设置后,DragMove 组件内部将仅通过参数返回计算后的位置,不做设置,用户按需自行设置新位置。

三、代码实现逻辑

  •   定义组件
    • 创建一个名为CustomMove的函数组件。       

  • 使用useRef创建引用
    • containerRef:用于引用容器元素,以便获取容器的尺寸信息。

    • elementRef:用于引用可拖动的元素,以便直接操作DOM元素。
    • startPoint:用于存储鼠标按下时的起始点坐标,以便判断是否为点击事件。
  • 使用useCallback定义事件处理函数
    • customMove:自定义拖动逻辑,确保元素不会超出容器边界。

    • onMouseDown:处理鼠标按下事件,记录起始点坐标。

    • onMouseUp:处理鼠标释放事件,判断是否为点击事件并切换元素宽度。

  • 提示信息
    • 在组件顶部渲染一个提示信息,说明蓝色色块的功能。

  • 容器元素
    • 渲染一个div作为容器,设置其样式和引用。

  • 可拖动元素
    • 使用DragMove组件包裹一个div,设置其样式和事件处理函数,并绑定引用。

  • 容器样式
    • 设置容器的背景色、宽度、高度、定位方式等样式。

  • 可拖动元素样式
    • 设置元素的背景色、宽度、高度、定位方式、圆角等样式。

  • 鼠标按下事件
    • 记录鼠标按下时的坐标。
  • 鼠标释放事件
    • 判断鼠标移动距离,如果小于5像素则认为是点击事件,切换元素宽度。

  • 导出CustomMove组件
    • 使用export default导出组件,以便在其他地方使用。

四、代码展示 

import React, { useCallback, useRef } from 'react'; // Import useCallback and useRef from react
import { DragMove } from '@douyinfe/semi-ui'; // Only import DragMove from semi-ui

/**
 * 自定义拖动组件 CustomMove
 * 该组件实现了一个可拖动的元素,并且可以通过点击来切换元素的宽度。
 * 拖动时,元素不会超出其容器的边界。
 */
function CustomMove() {
  // 创建容器元素的引用,用于获取容器的尺寸信息
  const containerRef = useRef();
  // 创建可拖动元素的引用,用于直接操作DOM元素
  const elementRef = useRef();
  // 存储鼠标按下时的起始点坐标,用于判断是否为点击事件
  const startPoint = useRef();

  /**
   * 自定义拖动逻辑
   * @param {HTMLElement} element - 拖动的元素
   * @param {number} top - 元素相对于容器顶部的距离
   * @param {number} left - 元素相对于容器左边的距离
   */
  const customMove = useCallback((element, top, left) => {
    // 如果元素超出容器右侧边界,则调整为右侧对齐
    if (left + element.offsetWidth > containerRef.current.offsetWidth) {
      element.style.right = `${containerRef.current.offsetWidth - left - element.offsetWidth}px`;
      element.style.left = 'auto'; // 将 left 设置为 auto,以便 right 生效
    } else {
      element.style.left = `${left}px`; // 否则,正常设置 left
    }
    // 设置元素的 top 样式
    element.style.top = `${top}px`;
  }, []);

  /**
   * 鼠标按下事件处理函数
   * @param {MouseEvent} e - 鼠标事件对象
   */
  const onMouseDown = useCallback((e) => {
    // 记录鼠标按下时的坐标
    startPoint.current = {
      x: e.clientX,
      y: e.clientY,
    };
  }, []);

  /**
   * 鼠标释放事件处理函数
   * @param {MouseEvent} e - 鼠标事件对象
   */
  const onMouseUp = useCallback((e) => {
    if (startPoint.current) {
      const { x, y } = startPoint.current;
      // 如果鼠标移动距离小于5像素,认为是点击事件
      if (Math.abs(e.clientX - x) < 5 && Math.abs(e.clientY - y) < 5) {
        // 切换元素宽度
        if (elementRef.current.style.width === '60px') {
          elementRef.current.style.width = '100px'; // 如果当前宽度是60px,则设置为100px
        } else {
          elementRef.current.style.width = '60px'; // 否则,设置为60px
        }
      }
    }
    // 清空起始点坐标
    startPoint.current = null;
  }, []);

  return (
    <>
      {/* 提示信息 */}
      <span style={
  
  { margin: '0 0 0 170px' }}>蓝色色块点击可改变宽度,改变前后蓝色色块均不会超出范围限制</span>
      <br /><br />
      {/* 容器 div */}
      <div
        style={
  
  {
          backgroundColor: 'rgba(var(--semi-grey-2), 1)', // 容器背景色
          width: 300, // 容器宽度
          height: 300, // 容器高度
          position: 'relative', // 相对定位,用于子元素的绝对定位
          padding: 10, // 内边距
          color: 'rgba(var(--semi-white), 1)', // 文字颜色
          fontWeight: 500, // 文字粗细
          margin: '0 0 0 170px'
        }}
        ref={containerRef} // 绑定容器引用
      >
        <span>Constrainer</span> {/* 容器内的文字 */}
        {/* 可拖动元素 */}
        <DragMove
          constrainer={() => containerRef.current} // 设置约束容器
          customMove={customMove} // 自定义拖动逻辑
        >
          <div
            style={
  
  {
              backgroundColor: 'var(--semi-color-primary)', // 元素背景色
              width: 60, // 元素初始宽度
              height: 50, // 元素高度
              display: 'flex',
              alignItems: 'center', // 垂直居中
              justifyContent: 'center', // 水平居中
              position: 'absolute', // 绝对定位
              top: 50, // 初始 top 位置
              left: 50, // 初始 left 位置
              borderRadius: 10, // 圆角
              padding: 5 // 内边距
            }}
            onMouseDown={onMouseDown} // 绑定鼠标按下事件
            onMouseUp={onMouseUp} // 绑定鼠标释放事件
            ref={elementRef} // 绑定元素引用
          >
            拖动 {/* 元素内的文字 */}
          </div>
        </DragMove>
      </div>
    </>
  );
}

export default CustomMove;

五、效果展示


http://www.kler.cn/a/521165.html

相关文章:

  • 系统思考—心智模式
  • 【阅读笔记】New Edge Diected Interpolation,NEDI算法,待续
  • 【Rust自学】16.3. 共享状态的并发
  • 在做题中学习(81):替换后的重复字符
  • 【cran Archive R包的安装方式】
  • LiteFlow Spring boot使用方式
  • 《一起做很甜的梦!》
  • sqlite3 学习笔记
  • 数据分箱 baggingboosting onehot独热编码 woe编码 sklearn的ensemble(集成学习)
  • python:taichi 高性能可视化 Demo 展览
  • 基于SpringBoot的母婴护理知识共享管理系统
  • 代码随想录算法【Day32】
  • Go中的Context(上下文)
  • ESP8266基于WiFiManager设置页面添加参数并且掉电不丢失
  • GIT管理指令
  • Object类(1)
  • Qt Enter和HoverEnter事件
  • 硬件学习笔记--36 TTL、RS232、RS485相关介绍
  • Linux相关概念和易错知识点(26)(命名管道、共享内存)
  • PostGIS笔记:PostgreSQL 数据库与用户 基础操作
  • 使用ensp进行ppp协议综合实验
  • API接口开发淘宝商品数据一键解析获取商品信息编写
  • Linux Ubuntu 18.04下创建桌面快捷方式
  • 云原生:构建现代化应用的基石
  • 在亚马逊云科技上用Stable Diffusion 3.5 Large生成赛博朋克风图片(上)
  • 【深入理解FFMPEG】命令行阅读笔记