首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >react-dnd的connectDragPreview()是如何工作的?

react-dnd的connectDragPreview()是如何工作的?
EN

Stack Overflow用户
提问于 2018-02-15 23:49:32
回答 3查看 7.1K关注 0票数 6

我一直在回顾文档和github的问题,connectDragPreview对我来说仍然是一个谜。我想定义一个自定义预览,当项目被拖动时,它是如何显示的。它的功能应该就像示例here处理出现在拖动上的马图像一样。下面是我的代码:

代码语言:javascript
复制
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()方法中,但这似乎只是改变了拖动源的位置,而不是它被拖动时的外观。

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

EN

回答 3

Stack Overflow用户

发布于 2018-02-26 01:33:28

看起来你在使用react-dnd-html5-backend。React-dnd-html5-后端提供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回调:

代码语言:javascript
复制
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 = 'base64-image';
    img.onload = () => connectDragPreview(img);
  }
  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 };

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

您的TokenClass:

代码语言:javascript
复制
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, monitor) => {
  return {
    connectDragSource: connect.dragSource(),
    connectDragPreview: connect.dragPreview(),
    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, isDragging, 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", tokenSpec, tokenCollector)(
  TokenClass
);

CustomDragLayer实现:

代码语言:javascript
复制
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解决方案,它可以同时处理图像和标记。您可以上传它们并运行:yarn install yarn start解决方案:https://github.com/xnimorz/stackoverflow-example/tree/dragAndDrop

票数 7
EN

Stack Overflow用户

发布于 2018-02-20 02:02:55

尝试将img.onload更改为直接使用img,而不是将其包装在div

代码语言:javascript
复制
img.onload = () => connectDragPreview(img);

据我所知,这是您的代码与示例之间唯一的真正区别。

票数 0
EN

Stack Overflow用户

发布于 2019-02-01 04:06:59

代码语言:javascript
复制
import React from 'react';
import { DragSource } from 'react-dnd';

/* ... */

function collect(connect, monitor) {
  return {
    connectDragSource: connect.dragSource(),
    connectDragPreview: connect.dragPreview()
  };
}

class ComponentWithCopyEffect {
  render() {
    const { connectDragSource } = this.props;

    return connectDragSource(
      <div>
        This div shows a plus icon in some browsers.
      </div>,
      { dropEffect: 'copy' }
    );
  }
});
ComponentWithCopyEffect = DragSource(/* ... */)(ComponentWithCopyEffect);

class ComponentWithHandle {
  render() {
    const { connectDragSource, connectDragPreview } = this.props;

    return connectDragPreview(
      <div>
        This div is draggable by a handle!
        {connectDragSource(
          <div>drag me</div>
        )}
      </div>
    );
  }
}
ComponentWithHandle = DragSource(/* ... */)(ComponentWithHandle);

class ComponentWithImagePreview {
  componentDidMount() {
    const { connectDragPreview } = this.props;

    const img = new Image();
    img.src = '/image.jpg';
    img.onload = () => connectDragPreview(img);
  }

  render() {
    const { connectDragSource } = this.props;

    return connectDragSource(
      <div>
        This div shows an image when dragged!
      </div>
    );
  }
}
ComponentWithImagePreview = DragSource(/* ... */)(ComponentWithImagePreview);

Source

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48811165

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档