加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

reactjs – react-dnd的connectDragPreview()如何工作?

发布时间:2020-12-15 05:04:22 所属栏目:百科 来源:网络整理
导读:我一直在审查文档和 github问题,connectDragPreview对我来说仍然是一个谜.我想定义一个自定义预览,以了解项目在拖动时的显示方式.它应该起作用,就像示例 here与拖动时出现的马图像一样.这是我的代码: export const tokenCollector: DragSourceCollector = (
我一直在审查文档和 github问题,connectDragPreview对我来说仍然是一个谜.我想定义一个自定义预览,以了解项目在拖动时的显示方式.它应该起作用,就像示例 here与拖动时出现的马图像一样.这是我的代码:
export const tokenCollector: DragSourceCollector = (connect,monitor) => {
  return {
    connectDragSource: connect.dragSource(),connectDragPreview: connect.dragPreview(),isDragging: monitor.isDragging()
  };
};

class TokenClass extends React.Component<TokenProps> {
  componentDidMount() {
    const { connectDragPreview } = this.props;
    const img = new Image();
    img.src = '<encoded image>';
    img.onload = () => connectDragPreview(<div>{img}</div>);
  }
  render() {
    const { connectDragSource,isDragging,children } = this.props;
    return connectDragSource(
      <div style={{ opacity: isDragging ? 0.5 : 1 }}>
        {children}
      </div>
    );
  }
}
const dragSource = DragSource(DropType.Token,tokenSpec,tokenCollector)(TokenClass);
export { dragSource as Token };

此代码将显示标准预览.

然后我尝试使用connectDragPreview将我的connectDragSource包装在我的组件的render()方法中,但这只会改变从中拾取它的拖动源,而不是它在被拖动时的显示方式.

如何指定应该用作拖动视觉的标记?

它似乎你正在使用react-dnd-html5-backend.
React-dnd-html5-backend提供connectDragSource: https://github.com/react-dnd/react-dnd-html5-backend/blob/85fc956c58a5d1a9fde2fca3c7fca9115a7c87df/src/HTML5Backend.js#L100

而react-dnd-html5-backend仅适用于html5拖放事件:https://github.com/react-dnd/react-dnd-html5-backend/blob/85fc956c58a5d1a9fde2fca3c7fca9115a7c87df/src/HTML5Backend.js#L65-L74

因此,您只能为拖动效果设置图像:https://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/setDragImage

您只需更改img.onload回调即可:

export const tokenCollector: DragSourceCollector = (connect,isDragging: monitor.isDragging()
  };
};

class TokenClass extends React.Component<TokenProps> {
  componentDidMount() {
    const { connectDragPreview } = this.props;
    const img = new Image();
    img.src = 'base64-image';
    img.onload = () => connectDragPreview(img);
  }
  render() {
    const { connectDragSource,tokenCollector)(TokenClass);
export { dragSource as Token };

如果要使用自定义标记,可以使用getEmptyImage参数调用connectDragPreview,然后实现CustomDragLayer.

你的TokenClass:

import React,{ Component } from "react";
import { DragSource } from "react-dnd";
import logo from "./logo.svg";
import { getEmptyImage } from "react-dnd-html5-backend";

export const tokenCollector = (connect,isDragging: monitor.isDragging()
  };
};

class TokenClass extends React.Component {
  componentDidMount() {
    const { connectDragPreview } = this.props;

    // Use empty image as a drag preview so browsers don't draw it
    // and we can draw whatever we want on the custom drag layer instead.
    connectDragPreview(getEmptyImage());
  }
  render() {
    const { connectDragSource,children } = this.props;
    return connectDragSource(
      <div style={{ opacity: isDragging ? 0.5 : 1,backgroundColor: "green" }}>
        {children}
      </div>
    );
  }
}

const tokenSpec = {
  beginDrag() {
    return {};
  }
};

export default DragSource("DropType.Markup",tokenCollector)(
  TokenClass
);

CustomDragLayer实现:

import React,{ Component } from "react";
import { DragLayer } from "react-dnd";

function getItemStyles(props) {
  const { initialOffset,currentOffset } = props;
  if (!initialOffset || !currentOffset) {
    return {
      display: "none"
    };
  }

  let { x,y } = currentOffset;

  const transform = `translate(${x}px,${y}px)`;
  return {
    transform,WebkitTransform: transform
  };
}

class CustomDragLayer extends Component {
  render() {
    const isDragging = this.props.isDragging;
    if (!isDragging) {
      return null;
    }

    // You can specify acceptable type:
    if (this.props.itemType !== "DropType.Markup") {
      return null;
    }

    // The component will work only when dragging
    return (
      <div>
        <div style={getItemStyles(this.props)}>Custom drag layer!</div>
      </div>
    );
  }
}

function collect(monitor) {
  return {
    item: monitor.getItem(),itemType: monitor.getItemType(),initialOffset: monitor.getInitialSourceClientOffset(),currentOffset: monitor.getSourceClientOffset(),isDragging: monitor.isDragging()
  };
}

export default DragLayer(collect)(CustomDragLayer); // eslint-disable-line new-cap

此外,我上传到github解决方案,该解决方案适用于图像和标记.您可以上传并运行:

纱线安装
纱线开始

解决方案:https://github.com/xnimorz/stackoverflow-example/tree/dragAndDrop

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读