首页 > 其他分享 >react-draggable All In One

react-draggable All In One

时间:2024-01-05 15:01:19浏览次数:22  
标签:draggable React const controlledPosition react state activeDrags

React Draggable Component All In One

HTML5 DnD / Drag and Drop / draggable

Draggable API

react-draggable

https://www.npmjs.com/package/react-draggable

https://github.com/react-grid-layout/react-draggable

image

demos

https://react-grid-layout.github.io/react-draggable/example/

https://github.com/react-grid-layout/react-draggable/blob/master/example/example.js

import React from 'react';
import ReactDOM from 'react-dom';
import Draggable from 'react-draggable';

class App extends React.Component {

  eventLogger = (e: MouseEvent, data: Object) => {
    console.log('Event: ', e);
    console.log('Data: ', data);
  };

  render() {
    return (
      <Draggable
        axis="x"
        handle=".handle"
        defaultPosition={{x: 0, y: 0}}
        position={null}
        grid={[25, 25]}
        scale={1}
        onStart={this.handleStart}
        onDrag={this.handleDrag}
        onStop={this.handleStop}>
        <div>
          <div className="handle">Drag from here</div>
          <div>This readme is really dragging on...</div>
        </div>
      </Draggable>
    );
  }
}

ReactDOM.render(<App/>, document.body);

const {ReactDraggable: Draggable, React, ReactDOM} = window;

class App extends React.Component {
  state = {
    activeDrags: 0,
    deltaPosition: {
      x: 0, y: 0
    },
    controlledPosition: {
      x: -400, y: 200
    }
  };

  handleDrag = (e, ui) => {
    const {x, y} = this.state.deltaPosition;
    this.setState({
      deltaPosition: {
        x: x + ui.deltaX,
        y: y + ui.deltaY,
      }
    });
  };

  onStart = () => {
    this.setState({activeDrags: ++this.state.activeDrags});
  };

  onStop = () => {
    this.setState({activeDrags: --this.state.activeDrags});
  };
  onDrop = (e) => {
    this.setState({activeDrags: --this.state.activeDrags});
    if (e.target.classList.contains("drop-target")) {
      alert("Dropped!");
      e.target.classList.remove('hovered');
    }
  };
  onDropAreaMouseEnter = (e) => {
    if (this.state.activeDrags) {
      e.target.classList.add('hovered');
    }
  }
  onDropAreaMouseLeave = (e) => {
    e.target.classList.remove('hovered');
  }

  // For controlled component
  adjustXPos = (e) => {
    e.preventDefault();
    e.stopPropagation();
    const {x, y} = this.state.controlledPosition;
    this.setState({controlledPosition: {x: x - 10, y}});
  };

  adjustYPos = (e) => {
    e.preventDefault();
    e.stopPropagation();
    const {controlledPosition} = this.state;
    const {x, y} = controlledPosition;
    this.setState({controlledPosition: {x, y: y - 10}});
  };

  onControlledDrag = (e, position) => {
    const {x, y} = position;
    this.setState({controlledPosition: {x, y}});
  };

  onControlledDragStop = (e, position) => {
    this.onControlledDrag(e, position);
    this.onStop();
  };

  render() {
    const dragHandlers = {onStart: this.onStart, onStop: this.onStop};
    const {deltaPosition, controlledPosition} = this.state;
    return (
      <div>
        <h1>React Draggable</h1>
        <p>Active DragHandlers: {this.state.activeDrags}</p>
        <p>
          <a href="https://github.com/STRML/react-draggable/blob/master/example/example.js">Demo Source</a>
        </p>
        <Draggable {...dragHandlers}>
          <div className="box">I can be dragged anywhere</div>
        </Draggable>
        <Draggable axis="x" {...dragHandlers}>
          <div className="box cursor-x">I can only be dragged horizonally (x axis)</div>
        </Draggable>
        <Draggable axis="y" {...dragHandlers}>
          <div className="box cursor-y">I can only be dragged vertically (y axis)</div>
        </Draggable>
        <Draggable onStart={() => false}>
          <div className="box">I don't want to be dragged</div>
        </Draggable>
        <Draggable onDrag={this.handleDrag} {...dragHandlers}>
          <div className="box">
            <div>I track my deltas</div>
            <div>x: {deltaPosition.x.toFixed(0)}, y: {deltaPosition.y.toFixed(0)}</div>
          </div>
        </Draggable>
        <Draggable handle="strong" {...dragHandlers}>
          <div className="box no-cursor">
            <strong className="cursor"><div>Drag here</div></strong>
            <div>You must click my handle to drag me</div>
          </div>
        </Draggable>
        <Draggable handle="strong">
          <div className="box no-cursor" style={{display: 'flex', flexDirection: 'column'}}>
            <strong className="cursor"><div>Drag here</div></strong>
            <div style={{overflow: 'scroll'}}>
              <div style={{background: 'yellow', whiteSpace: 'pre-wrap'}}>
                I have long scrollable content with a handle
                {'\n' + Array(40).fill('x').join('\n')}
              </div>
            </div>
          </div>
        </Draggable>
        <Draggable cancel="strong" {...dragHandlers}>
          <div className="box">
            <strong className="no-cursor">Can't drag here</strong>
            <div>Dragging here works</div>
          </div>
        </Draggable>
        <Draggable grid={[25, 25]} {...dragHandlers}>
          <div className="box">I snap to a 25 x 25 grid</div>
        </Draggable>
        <Draggable grid={[50, 50]} {...dragHandlers}>
          <div className="box">I snap to a 50 x 50 grid</div>
        </Draggable>
        <Draggable bounds={{top: -100, left: -100, right: 100, bottom: 100}} {...dragHandlers}>
          <div className="box">I can only be moved 100px in any direction.</div>
        </Draggable>
        <Draggable {...dragHandlers}>
          <div className="box drop-target" onm ouseEnter={this.onDropAreaMouseEnter} onm ouseLeave={this.onDropAreaMouseLeave}>I can detect drops from the next box.</div>
        </Draggable>
        <Draggable {...dragHandlers} onStop={this.onDrop}>
          <div className={`box ${this.state.activeDrags ? "no-pointer-events" : ""}`}>I can be dropped onto another box.</div>
        </Draggable>
        <div className="box" style={{height: '500px', width: '500px', position: 'relative', overflow: 'auto', padding: '0'}}>
          <div style={{height: '1000px', width: '1000px', padding: '10px'}}>
            <Draggable bounds="parent" {...dragHandlers}>
              <div className="box">
                I can only be moved within my offsetParent.<br /><br />
                Both parent padding and child margin work properly.
              </div>
            </Draggable>
            <Draggable bounds="parent" {...dragHandlers}>
              <div className="box">
                I also can only be moved within my offsetParent.<br /><br />
                Both parent padding and child margin work properly.
              </div>
            </Draggable>
          </div>
        </div>
        <Draggable bounds="body" {...dragHandlers}>
          <div className="box">
            I can only be moved within the confines of the body element.
          </div>
        </Draggable>
        <Draggable {...dragHandlers}>
          <div className="box" style={{position: 'absolute', bottom: '100px', right: '100px'}}>
            I already have an absolute position.
          </div>
        </Draggable>
        <Draggable {...dragHandlers}>
          <RemWrapper>
            <div className="box rem-position-fix" style={{position: 'absolute', bottom: '6.25rem', right: '18rem'}}>
              I use <span style={{ fontWeight: 700 }}>rem</span> instead of <span style={{ fontWeight: 700 }}>px</span> for my transforms. I also have absolute positioning.

              <br /><br />
              I depend on a CSS hack to avoid double absolute positioning.
            </div>
          </RemWrapper>
        </Draggable>
        <Draggable defaultPosition={{x: 25, y: 25}} {...dragHandlers}>
          <div className="box">
            {"I have a default position of {x: 25, y: 25}, so I'm slightly offset."}
          </div>
        </Draggable>
        <Draggable positionOffset={{x: '-10%', y: '-10%'}} {...dragHandlers}>
          <div className="box">
            {'I have a default position based on percents {x: \'-10%\', y: \'-10%\'}, so I\'m slightly offset.'}
          </div>
        </Draggable>
        <Draggable position={controlledPosition} {...dragHandlers} onDrag={this.onControlledDrag}>
          <div className="box">
            My position can be changed programmatically. <br />
            I have a drag handler to sync state.
            <div>
              <a href="#" onClick={this.adjustXPos}>Adjust x ({controlledPosition.x})</a>
            </div>
            <div>
              <a href="#" onClick={this.adjustYPos}>Adjust y ({controlledPosition.y})</a>
            </div>
          </div>
        </Draggable>
        <Draggable position={controlledPosition} {...dragHandlers} onStop={this.onControlledDragStop}>
          <div className="box">
            My position can be changed programmatically. <br />
            I have a dragStop handler to sync state.
            <div>
              <a href="#" onClick={this.adjustXPos}>Adjust x ({controlledPosition.x})</a>
            </div>
            <div>
              <a href="#" onClick={this.adjustYPos}>Adjust y ({controlledPosition.y})</a>
            </div>
          </div>
        </Draggable>

      </div>
    );
  }
}

class RemWrapper extends React.Component {
  // PropTypes is not available in this environment, but here they are.
  // static propTypes = {
  //   style: PropTypes.shape({
  //     transform: PropTypes.string.isRequired
  //   }),
  //   children: PropTypes.node.isRequired,
  //   remBaseline: PropTypes.number,
  // }

  translateTransformToRem(transform, remBaseline = 16) {
    const convertedValues = transform.replace('translate(', '').replace(')', '')
      .split(',')
      .map(px => px.replace('px', ''))
      .map(px => parseInt(px, 10) / remBaseline)
      .map(x => `${x}rem`)
    const [x, y] = convertedValues

    return `translate(${x}, ${y})`
  }

  render() {
    const { children, remBaseline = 16, style } = this.props
    const child = React.Children.only(children)

    const editedStyle = {
      ...child.props.style,
      ...style,
      transform: this.translateTransformToRem(style.transform, remBaseline),
    }

    return React.cloneElement(child, {
       ...child.props,
       ...this.props,
       style: editedStyle
    })
  }
}


ReactDOM.render(<App/>, document.getElementById('container'));

(

标签:draggable,React,const,controlledPosition,react,state,activeDrags
From: https://www.cnblogs.com/xgqfrms/p/17947257

相关文章

  • 如何管理多个React组件的异步请求
    如何管理多个React组件的异步请求一、异步请求的背景前端应用中的异步请求前端应用中的异步请求是指在前端开发中,通过使用Ajax、fetch或其他网络请求库,向后端服务器发送请求并获取数据的过程。由于前端开发中常常需要实现多个React组件之间的数据交互,因此对于异步请求的管理变得尤......
  • React函数式组件避免无用渲染的方案
    在class组件中可以使用shouldComponentUpdate钩子函数,但是函数式组件中是没有这种钩子函数的,那么在函数式组件中来达到类似的效果呢?答案是:React.Memo,如以下使用案例://父组件const[values,setValues]=useState({a:1,b:1,});functionincrement(){......
  • VUE框架Vue3下使用watch监听reactive下的数据变化并使深度监视起效------VUE框架
    <template><h1>{{data.counter}}</h1><button@click="data.counter++">按一下加一</button><h1>{{data.a.b.c.d.counter1}}</h1><button@click="data.a.b.c.d.counter1++">按一下加一&l......
  • vue3的ref、reactive、toRef、toRefs
    用处:用于在setup中创建响应式变量导出:import{ref,reactive,toRef,toRefs}from'vue'区别:ref用来定义基础数据类型,String,Number,Boolean,Symbol;通过Object.defineProperty()的get和set来实现响应式;js操作数据需要.value,模版中读取不需要.valuereactive用来定义......
  • React 类组件转换为函数式
    函数式的React组件更加现代,并支持有用的hooks,现在流行把旧式的类组件转换为函数式组件。这篇文章总结了转换的一些通用的步骤和陷阱。通用替换定义从class(\w+)extendsComponent\{改为const$1:FC=()=>{这是没有export和props的场景从(export)defau......
  • react项目经验,以及一些骚写法
    语法糖1.constlogged=!!getToken();这里的`!!`是求布尔值的快捷方式类似的:2.vara=b*1是转数字的快捷方式3.vara=b+''是转字符串的快捷方式架构相关1.webpack2.qiankuan通过package.json可以查看react等等项目中的依赖的各种版本。学会使用chatgpt插件安......
  • 使用hook封装表格常用功能(react)
    实现内容配置分页:usePagination生成过滤项:useFilter获取表格选择配置:useSelect生成批量删除按钮:useDelete生成模态框:useModal示例render部分:<React.Fragment><Formlayout="inline">{DeleteEle}{FilterEles}</Form><Table{...{......
  • react 文件选择器
    exporttypeFileSelectorType={emit:boolean;type:"file"|"dir";callBack:(path:string,fileList:FileList)=>void;};exportconstFileSelector=(props:{upload:FileSelectorType})=>{useEffect(()=>{......
  • 【 react 】《 React实现图片比对效果 》
    这里使用img-comparison-slider组件进行实现官网地址https://img-comparison-slider.sneas.io/examples.html#always-showGitHub地址https://github.com/sneas/img-comparison-slider实现效果拖动中间分割线来切换展示旧图片与新图片安装组件##安装组件npminstall@......
  • React的各种bug及分析
    Parsingerror:Usingtheexportkeywordbetweenadecoratorandaclassisnotallowed.Pleaseuse`export@decclass`instead.脚手架修饰器的问题:我一般碰到这个问题,就直接把导出代码写到外面。@connect(state=>({isloading:state.error.isloading,}))classTri......