react可视化编辑器 第一章 拖拽

效果:

实现可视化编辑器,第一步难点 是 拖拽

提示:链接和图片默认是可拖动的,不需要draggable属性。

在拖放操作的不同阶段使用并可能发生许多事件属性:

  • 在可拖动目标上触发的事件(源元素):
    ondragstart - 当用户开始拖动元素时触发
    ondrag - 拖动元素时触发
    ondragend - 在用户完成拖动元素时触发

  • 在放置目标上触发的事件:
    ondragenter - 当被拖动的元素进入放置目标时触发
    ondragover - 当被拖动的元素超过放置目标时触发
    ondragleave - 当被拖动的元素离开放置目标时触发
    ondrop - 当被拖动的元素放在放置目标上时触发

react可视化编辑器 第一章 拖拽_第1张图片

这种代码结构更加清楚, demo 和content是俩个完全没有关系的兄弟div

现在需求的 红色拖拽到蓝色中, 这里的方法是定位

情况一:

  • demo的操作逻辑代码
      
handleDragStart(e, 1)} style={{ width: '100px', height: '100px', backgroundColor: 'red', margin: '30px', }} > demo2
  const handleDragStart = (e: DragEvent, id: number) => {
    e.dataTransfer.setData('text/plain', id.toString());  // 存储id, 和 data-XX一个道理
  };
  • content 的逻辑代码
   
content {demos.map((demo) => (
demo {demo.id}
))}
  const handleDrop = (e: DragEvent) => {
    e.preventDefault();
    const clientX = e.clientX;
    const clientY = e.clientY;
    const contentStyle = document
      .getElementById('content')
      .getBoundingClientRect();

    const x = clientX - contentStyle.left
    const y = clientY - contentStyle.top;
    const newDemo: Demo = { x, y, id: +new Date() };
    setDemos([...demos, newDemo]);
  };

上面代码测试结果:

代码测试 ,会有一些偏差,原因是 鼠标拖拽的位置的不是红色div的左上角顶点, 这样的就不会发生偏移, 但是实际情况无法保证每次都是拖拽顶点, 那需要在开始拖拽的计算的鼠标相对于红色div的偏移值

情况二:完整的代码

import React, { useState, DragEvent, useEffect, MouseEvent } from 'react';

interface Demo {
  id: number;
  x: number;
  y: number;
}

const App: React.FC = () => {
  const [demos, setDemos] = useState([]);

  const handleDragStart = (e: DragEvent, id: number) => {
    e.dataTransfer.setData('text/plain', id.toString());

    const offsetX = e.clientX - e.currentTarget.getBoundingClientRect().left;
    const offsetY = e.clientY - e.currentTarget.getBoundingClientRect().top;
    e.dataTransfer.setData('offsetX', offsetX.toString());
    e.dataTransfer.setData('offsetY', offsetY.toString());
  };

  const handleDrop = (e: DragEvent) => {
    e.preventDefault();
    const clientX = e.clientX;
    const clientY = e.clientY;
    const contentStyle = document
      .getElementById('content')
      .getBoundingClientRect();
    const offsetX = e.dataTransfer.getData('offsetX');
    const offsetY = e.dataTransfer.getData('offsetY');
    const x = clientX - contentStyle.left - offsetX;
    const y = clientY - contentStyle.top - offsetY;
    const newDemo: Demo = { x, y, id: +new Date() };
    setDemos([...demos, newDemo]);
  };

  const handleDragOver = (e: DragEvent) => {
    e.preventDefault();
  };

  const onMouseDown = (e: MouseEvent) => {
    console.info('onMouseDown', e);
  };

  const onMouseUp = (e: MouseEvent) => {
    console.info('onMouseUp', e);
  };

  const onDragEnd = (e: MouseEvent) => {
    console.info('onDragEnd', e);
  };

  return (
    
handleDragStart(e, 1)} onDragEnd={onDragEnd} style={{ width: '100px', height: '100px', backgroundColor: 'red', margin: '30px', }} > demo2
content {demos.map((demo) => (
demo {demo.id}
))}
); }; export default App;

你可能感兴趣的:(react.js,编辑器,前端)