React DnD로 휴대폰에 끌어놓기

12685 단어 ReactJavaScript
Enigmo Advent Calendar 2018째 보도다.
주의: 본 샘플 코드에 사용된 모든 프로그램 라이브러리의 버전은 다음과 같습니다.
react 16.4.0
react-dnd 4.0.2
react-dnd-html5-backend 4.0.2
react-dnd-touch-backend 0.5.1

React DnD


React에서 드래그 정렬을 실현할 때 자주 사용하는 프로그램 라이브러리 React DnD.
이 프로그램 라이브러리는 HTML5Drag and Drop API를 사용해 드래그를 실현했지만, API 자체는 스마트폰 등 터치 기기를 지원하지 않아 스마트폰으로 직접 드래그를 할 수 없다.

TouchBackend


React DnD를 사용할 경우 드래그 앤 드롭할 어셈블리를 DragDropContextHOC(Higer Order Component에 전달합니다.
DragDropContext에 전달되는 첫 번째 파라미터는 보통 백엔드 모듈HTML5Backend이다.
import HTML5Backend from 'react-dnd-html5-backend'
import { DragDropContext } from 'react-dnd'

class YourApp {
    /* ... */
}

export default DragDropContext(HTML5Backend)(YourApp)
위에서 말한 바와 같이 터치 장치는 이것을 사용할 수 없다HTML5Backend.그런데 대응하는 터치 장치TouchBackend가 있어서 그걸로 해요.
import HTML5Backend from 'react-dnd-html5-backend'
import TouchBackend from 'react-dnd-touch-backend';
import { DragDropContext } from 'react-dnd'

const isTouchDevice = () => {
 /* タッチデバイス判定 */
}

class YourApp {
    /* ... */
}
export default DragDropContext(isTouchDevice() ? TouchBackend : HTML5Backend)(YourApp)
이렇게 하면 터치 장치를 지원할 수 있다.
하지만 HTML5Backend처럼 좋은 느낌으로 미리 볼 수는 없다.

HTML5 Backend에서 미리보기가 잘 되어 있어요.

터치백에 미리보기가 없어요!
※ 크롬의 DevTools에 스마트폰이 모의 녹화돼 있어 마우스 커서가 표시됩니다.

DragLayer


React DnD에는 드래그할 때 미리 보기 표시DragLayer를 사용자 정의할 수 있는 API가 있습니다.
이 옵션을 사용하면 터치 장치에 좋은 미리보기를 표시할 수 있습니다.
사용자의 샘플 코드는 다음과 같다.
import React from 'react'
import DragLayer from 'react-dnd/lib/DragLayer'
import TouchBackend from 'react-dnd-touch-backend';
import { DragDropContext } from 'react-dnd'

function collect(monitor) {
  const item = monitor.getItem()
  return {
    currentOffset: monitor.getSourceClientOffset(),
    previewProps: item && item.previewProps,
    isDragging:
      monitor.isDragging() && monitor.getItemType() === 'IMAGE'
  }
}

function getItemStyles(currentOffset) {
  if (!currentOffset) {
    return {
      display: 'none'
    }
  }

  const x = currentOffset.x
  const y = currentOffset.y
  const transform = `translate(${x}px, ${y}px) scale(1.05)`

  return {
    WebkitTransform: transform,
    transform: transform,
  }
}

class PreviewComponent extends React.Component {
  render() {
    const { isDragging, previewProps, currentOffset } = this.props
    if (!isDragging) {
      return null
    }

    return (
      <div style={getItemStyles(currentOffset)}>
        {/*...*/}
      </div>
    )
  }
}

const DragPreview = DragLayer(collect)(PreviewComponent)


class YourApp {
  render() {
    return (
      <div>
        {/* ... */}
        <DragPreview />
      </div>
    )
  }
}

export default DragDropContext(TouchBackend)(YourApp)

간단히 설명하다

DragLayer의 매개 변수collect 함수 전달DragLayerMonitor의 대상.monitor.getItem()에서 방문DragSource, 임의로 교부할 수 있는 props(이번에는 previewProps의 이름으로 교부할 수 있지만 어떤 이름이든 교부할 수 있다).
또한 monitor.isDragging를 통해 실제 드래그 여부를 판단할 수 있다.
같은 화면의 다른 구성 요소에서도 드래그를 하기 위해 여러 개DragDropContext가 있으면 monitor.getItemType()가 어느 상하문인지 판정할 수 있다.monitor.getSourceClientOffset()를 사용하여 미리보기의 터치 부분을 따라 오프셋 좌표를 반환합니다.collect 함수의 반환값 대상은 미리 보기 구성 요소props로 직접 수신할 수 있습니다.getItemStyles 함수는 받은 props.currentOffset를 사용하여 CSS를 조정합니다.
전달DragDropContext의 어셈블리DragLayer를 그리면 드래그할 때 미리보기를 표시할 수 있습니다.

스마트폰도 미리 볼 수 있다!
※ 크롬의 DevTools에 스마트폰이 모의 녹화돼 있어 마우스 커서가 표시됩니다.

최후


다음은 스마트폰 등 터치 기기로 HTML5 등 드래그 앤 드롭을 실현하는 방법에 대해 설명한다.
실제 설치 시TouchBackend의 창고에 완전한 동작의 샘플이 있으니 참고하세요.

참조 링크


http://react-dnd.github.io/react-dnd/about
https://github.com/yahoo/react-dnd-touch-backend

좋은 웹페이지 즐겨찾기