Skip to content

feat(useDrag): useDrag adds custom picture feature #2182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jul 12, 2023
33 changes: 33 additions & 0 deletions packages/hooks/src/useDrag/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,43 @@
import { useRef } from 'react';
import useLatest from '../useLatest';
import useMount from '../useMount';
import { isString } from '../utils';
import type { BasicTarget } from '../utils/domTarget';
import { getTargetElement } from '../utils/domTarget';
import useEffectWithTarget from '../utils/useEffectWithTarget';

export interface Options {
onDragStart?: (event: React.DragEvent) => void;
onDragEnd?: (event: React.DragEvent) => void;
dragImage?: {
image: string | Element;
offsetX?: number;
offsetY?: number;
};
}

const useDrag = <T>(data: T, target: BasicTarget, options: Options = {}) => {
const optionsRef = useLatest(options);
const dataRef = useLatest(data);
const imageElementRef = useRef<Element>();

const { dragImage } = optionsRef.current;

useMount(() => {
if (dragImage?.image) {
const { image } = dragImage;

if (isString(image)) {
const imageElement = new Image();

imageElement.src = image;
imageElementRef.current = imageElement;
} else {
imageElementRef.current = image;
}
}
});

useEffectWithTarget(
() => {
const targetElement = getTargetElement(target);
Expand All @@ -21,6 +48,12 @@ const useDrag = <T>(data: T, target: BasicTarget, options: Options = {}) => {
const onDragStart = (event: React.DragEvent) => {
optionsRef.current.onDragStart?.(event);
event.dataTransfer.setData('custom', JSON.stringify(dataRef.current));

if (dragImage?.image && imageElementRef.current) {
const { offsetX = 0, offsetY = 0 } = dragImage;

event.dataTransfer.setDragImage(imageElementRef.current, offsetX, offsetY);
}
};

const onDragEnd = (event: React.DragEvent) => {
Expand Down
36 changes: 36 additions & 0 deletions packages/hooks/src/useDrop/demo/demo2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* title: Customize Image
* desc: Customize image that follow the mouse pointer during dragging.
*
* title.zh-CN: 自定义拖拽图像
* desc.zh-CN: 自定义拖拽过程中跟随鼠标指针的图像。
*/

import React, { useRef } from 'react';
import { useDrag } from 'ahooks';

const COMMON_STYLE: React.CSSProperties = {
border: '1px solid #e8e8e8',
height: '50px',
lineHeight: '50px',
padding: '16px',
textAlign: 'center',
marginRight: '16px',
};

export default () => {
const dragRef = useRef(null);

useDrag('', dragRef, {
dragImage: {
image: '/logo.svg',
},
});

return (
<div ref={dragRef} style={{ display: 'flex' }}>
<img style={COMMON_STYLE} src="/simple-logo.svg" />
<div style={COMMON_STYLE}>drag me</div>
</div>
);
};
21 changes: 17 additions & 4 deletions packages/hooks/src/useDrop/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ A pair of hooks to help you manage data transfer between drag and drop

<code src="./demo/demo1.tsx" />

### Customize Image

<code src="./demo/demo2.tsx" />

## API

### useDrag
Expand All @@ -41,10 +45,19 @@ useDrag<T>(

#### DragOptions

| Property | Description | Type | Default |
| ----------- | ---------------------- | ------------------------------ | ------- |
| onDragStart | On drag start callback | `(e: React.DragEvent) => void` | - |
| onDragEnd | On drag end callback | `(e: React.DragEvent) => void` | - |
| Property | Description | Type | Default |
| ----------- | ------------------------------------------------------------- | ------------------------------ | ------- |
| onDragStart | On drag start callback | `(e: React.DragEvent) => void` | - |
| onDragEnd | On drag end callback | `(e: React.DragEvent) => void` | - |
| dragImage | Customize image that follow the mouse pointer during dragging | `DragImageOptions` | - |

#### DragImageOptions

| 参数 | 说明 | 类型 | 默认值 |
| ------- | ----------------------------------------------------------- | ------------------- | ------ |
| image | An image Element element to use for the drag feedback image | `string \| Element` | - |
| offsetX | the horizontal offset within the image | `number` | 0 |
| offsetY | the vertical offset within the image | `number` | 0 |

### useDrop

Expand Down
21 changes: 17 additions & 4 deletions packages/hooks/src/useDrop/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ nav:

<code src="./demo/demo1.tsx" />

### 自定义拖拽图像

<code src="./demo/demo2.tsx" />

## API

### useDrag
Expand All @@ -41,10 +45,19 @@ useDrag<T>(

#### DragOptions

| 参数 | 说明 | 类型 | 默认值 |
| ----------- | -------------- | ------------------------------ | ------ |
| onDragStart | 开始拖拽的回调 | `(e: React.DragEvent) => void` | - |
| onDragEnd | 结束拖拽的回调 | `(e: React.DragEvent) => void` | - |
| 参数 | 说明 | 类型 | 默认值 |
| ----------- | ---------------------------------- | ------------------------------ | ------ |
| onDragStart | 开始拖拽的回调 | `(e: React.DragEvent) => void` | - |
| onDragEnd | 结束拖拽的回调 | `(e: React.DragEvent) => void` | - |
| dragImage | 自定义拖拽过程中跟随鼠标指针的图像 | `DragImageOptions` | - |

#### DragImageOptions

| 参数 | 说明 | 类型 | 默认值 |
| ------- | ---------------------------- | ------------------- | ------ |
| image | 拖拽过程中跟随鼠标指针的图像 | `string \| Element` | - |
| offsetX | 水平偏移 | `number` | 0 |
| offsetY | 垂直偏移 | `number` | 0 |

### useDrop

Expand Down