ReactDnD单一目标(例子)

2022-03-08  本文已影响0人  ikonan

这是最简单的拖放示例。

拖动下面的框并将它们放入垃圾箱。 请注意,它具有正常、活动和悬停状态。 拖动的项目本身会在拖动时更改不透明度。

image.png

ItemType.ts

export const ItemTypes = {
  BOX: 'box',
};

Box.tsx

import { FC, CSSProperties } from 'react';
import { useDrag } from 'react-dnd';

import { ItemTypes } from './ItemTypes';

const style: CSSProperties = {
  border: '1px dashed gray',
  backgroundColor: 'white',
  padding: '0.5rem 1rem',
  marginRight: '1.5rem',
  marginBottom: '1.5rem',
  cursor: 'move',
  float: 'left',
};

export interface BoxProps {
  name: string;
}

interface DropResult {
  name: string;
}

export const Box: FC<BoxProps> = ({ name }) => {
  const [{ isDragging }, drag] = useDrag(() => ({
    type: ItemTypes.BOX,
    item: { name },
    end: (item, monitor) => {
      const dropResult = monitor.getDropResult<DropResult>();
      if (item && dropResult) {
        alert(`You dropped ${item.name} into ${dropResult.name}!`);
      }
    },

    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
      handlerId: monitor.getHandlerId(),
    }),
  }));

  const opacity = isDragging ? 0.4 : 1.0;

  return (
    <div ref={drag} role="Box" style={{ ...style, opacity }}>
      {name}
    </div>
  );
};

Dustbin.tsx

import { FC, CSSProperties } from 'react';
import { ItemTypes } from './ItemTypes';
import { useDrop } from 'react-dnd';

const style: CSSProperties = {
  height: '12rem',
  width: '12rem',
  marginRight: '1.5rem',
  marginBottom: '1.5rem',
  color: 'white',
  padding: '1rem',
  textAlign: 'center',
  fontSize: '1rem',
  lineHeight: 'normal',
};

export const Dustbin: FC = (props) => {
  const [{ canDrop, isOver }, drop] = useDrop(() => ({
    accept: ItemTypes.BOX,
    drop: () => ({ name: 'Dustbin' }),
    collect: (monitor) => ({
      canDrop: monitor.canDrop(),
      isOver: monitor.isOver(),
    }),
  }));

  const isActive = canDrop && isOver;
  let backgroundColor = '#222';
  if (isActive) {
    backgroundColor = 'darkgreen';
  } else if (canDrop) {
    backgroundColor = 'darkkhaki';
  }

  return (
    <div ref={drop} style={{ ...style, backgroundColor }}>
      {isActive ? 'Release to drop' : 'Drag a box here'}
    </div>
  );
};

index.tsx

import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';

import { Dustbin } from './Dustbin';
import { Box } from './Box';

const Page: React.FC<any> = (props) => {
  return (
    <DndProvider backend={HTML5Backend}>
      <div style={{ padding: '32px' }}>
        <div>
          <Dustbin />
        </div>
        <div>
          <Box name="Glass" />
          <Box name="Banana" />
          <Box name="Paper" />
        </div>
      </div>
    </DndProvider>
  );
};

export default Page;
上一篇 下一篇

猜你喜欢

热点阅读