React-dnd: Плохой снимок экрана при обычном перетаскивании, прерывистое движение при предварительном просмотре пользовательского перетаскивания

Созданный на 8 мая 2016  ·  22Комментарии  ·  Источник: react-dnd/react-dnd

Как и у многих, у меня есть список сортируемых карточек. В моем случае каждая карточка представляет собой блок содержимого сообщения в блоге, а некоторые из них представляют собой фрагменты кода, отображаемые с помощью react-codemirror . Предварительный просмотр фрагментов включал большой белый фон, равный ширине и высоте текста в редакторе кода codemirror. Это было нежелательно, поэтому я попытался исправить это с помощью CSS, но мне не повезло, и, читая больше документации, я думаю, что это невозможно, потому что dnd делает снимок экрана узла dom до того, как к нему могут быть применены какие-либо новые классы или стили (пожалуйста, поправьте меня если это не так конечно)

Поскольку я не мог заставить работать css, я попытался использовать собственный слой перетаскивания, чтобы показать что-то другое для предварительного просмотра. Это отлично работает, за исключением того, что перетаскивание становится действительно прерывистым, хотя раньше оно было довольно плавным.

Вот видео, демонстрирующее только что описанную проблему:

https://drive.google.com/file/d/0Bzbw-6Q_sVTySUNiNmJGcFVIQ00/view?usp=sharing

И я полагаю, вы также захотите увидеть какой-нибудь код. Вот мой собственный слой перетаскивания

import React, { Component, PropTypes } from 'react'
import { DragLayer } from 'react-dnd'

function collect(monitor) {
  return {
    item: monitor.getItem(),
    currentOffset: monitor.getSourceClientOffset(),
    isDragging: monitor.isDragging()
  }
}

const layerStyles = {
  position: 'fixed',
  pointerEvents: 'none',
  zIndex: 100,
  left: 0,
  top: 0,
  width: '20%',
  height: '100%'
}

function getItemStyles(props) {
  var currentOffset = props.currentOffset
  if (!currentOffset) {
    return {
      display: 'none'
    }
  }

  var x = currentOffset.x
  var y = currentOffset.y
  var transform = 'translate(' + x + 'px, ' + y + 'px)'
  return {
    transform: transform,
    WebkitTransform: transform
  }
}

class CardDragLayer extends Component {
  static propTypes = {
    item: PropTypes.object
  }

  render() {
    const { item, isDragging } = this.props

    if (!isDragging)
      return false

    return (
      <div style={layerStyles}>
        <div className='drag-preview' style={getItemStyles(this.props)}>
          <i className='fa fa-hand-scissors-o fa-6'></i>
        </div>
      </div>
    )
  }
}

export default DragLayer(collect)(CardDragLayer)

Вот параметры конфигурации для источника и цели перетаскивания

export const cardSource = {
  beginDrag(props) {
    return {
      index: props.index
    }
  }
}

export const cardTarget = {
  hover(props, monitor, component) {
    const dragIndex = monitor.getItem().index
    const hoverIndex = props.index

    if (dragIndex === hoverIndex)
      return

    props.swap(dragIndex, hoverIndex)
    monitor.getItem().index = hoverIndex;
  }
}

export function collectSource(connect, monitor) {
  return {
    connectDragSource: connect.dragSource(),
    connectDragPreview: connect.dragPreview(),
    isDragging: monitor.isDragging()
  }
}

export function collectTarget(connect) {
  return {
    connectDropTarget: connect.dropTarget()
  }
}

А вот перетаскиваемый компонент Card

import React, { PropTypes, Component } from 'react'
import { Snippet, Markdown } from './Show'
import { DragSource, DropTarget } from 'react-dnd'
import { getEmptyImage } from 'react-dnd-html5-backend'
import { cardSource, cardTarget, collectSource, collectTarget } from './dragDropConfig'
import classnames from 'classnames'

class SnippetCard extends Component {
  options() {
    return {
      readOnly: true,
      scrollbarStyle: 'null',
      viewportMargin: Infinity
    }
  }

  render() {
    const { language, text } = this.props
    return(
      <Snippet
        options={this.options()}
        language={language.value}
        text={text.value} />
    )
  }
}

class MarkdownCard extends Component {
  render() {
    const { text } = this.props
    return (
      <div className='markdown-card'>
        <div className='card-content'>
          <Markdown text={text.value} />
        </div>
      </div>
    )
  }
}

const components = {
  snippet: SnippetCard,
  markdown: MarkdownCard
}

class Card extends Component {
  static propTypes = {
    connectDragSource: PropTypes.func.isRequired,
    connectDropTarget: PropTypes.func.isRequired,
    index: PropTypes.number.isRequired,
    block: PropTypes.object.isRequired,
    swap: PropTypes.func.isRequired
  }

  componentDidMount() {
    const { connectDragPreview } = this.props
    connectDragPreview(getEmptyImage(), {
      captureDraggingState: true
    })
  }

  render() {
    const { isDragging, block, connectDragSource, connectDropTarget } = this.props
    const Component = components[block.format.value]
    const classes = classnames('card', {
      dragging: isDragging
    })

    return connectDragSource(connectDropTarget((
      <div className={classes}>
        <div className='card-header'>
          <div>
            <label>
              {block.format.value}
            </label>
          </div>
          <Component {...block} />
        </div>
      </div>
    )))
  }
}

const Source = DragSource('card', cardSource, collectSource)(Card)
export default DropTarget('card', cardTarget, collectTarget)(Source)

Дайте мне знать, если вам нужно увидеть больше кода, я думаю, этого должно быть достаточно.

Будем очень признательны за предложения: а) как я могу использовать CSS для скрытия белого фона или б) сделать перетаскивание пользовательского предварительного просмотра перетаскивания более плавным!

Обратите внимание, что эта работа является частью курса по созданию приложений с помощью response / redux и что я планирую сделать, вероятно, 2-3 коротких видеоролика по response-dnd, чтобы показать, как реализованы сортируемые карточки блока содержимого. Надеемся выпустить их как можно скорее!

needs info wontfix

Самый полезный комментарий

Да, мы начали с удаления каждого компонента, чтобы найти тот, который вызывал проблему, и, как только мы его нашли, перешли к той части, которая вызывала замедление, а затем к самому внешнему элементу, который может принимать style param мы написали: style={{transform: translate3d(0, 0, 0)}}

Все 22 Комментарий

Я также заметил нестабильность при использовании настраиваемого dragLayer (просто запустил пример веб-сайта): http://gaearon.github.io/react-dnd/examples-drag-around-custom-drag-layer.html

В Chrome все нормально, но в Firefox анимация прерывистая. (на linux mint, firefox 46.0.1)

Кстати, классная библиотека!

@sslotsky Вы когда-нибудь в этом

Если нет, я могу погрузиться в это и посмотреть, есть ли что-нибудь умное в CSS, что мы можем сделать, или, альтернативно, что-нибудь, что мы можем сделать, чтобы уменьшить волнение. Другие люди сообщают, что производительность настраиваемого слоя перетаскивания оставляет желать лучшего.

Нет, до сих пор не понял. Решение было бы отличным, когда я займусь записью следующего видео!

Мы тоже это видим, подписываясь на этот выпуск, чтобы получать обновления.

@kesne Просто комментирую, чтобы сохранить это в живых. Если у вас есть какие-то обновления, которыми стоит поделиться, я уверен, что мы будем рады услышать об этом :)

Да, я бы тоже хотел решить эту проблему. Я хочу реализовать больше, чем просто снимок экрана перетаскиваемого объекта, но, по сути, очень простой компонент реакции.

Я тоже добавлю это. Мы тоже наблюдаем ту же проблему.

Я тоже сталкиваюсь с этим .. Простое перетаскивание работает нормально. Но у меня слишком сложная реализация, и это происходит.

Есть такая же проблема. Кто-нибудь придумал какое-то решение или обходной путь?

@ alexey-belous Мы отказались от этой библиотеки и выбрали https://github.com/bevacqua/react-dragula

Та же проблема здесь, буду рад любым дальнейшим комментариям.

Я исследовал эту проблему и выяснил, что снимок экрана с перетаскиванием узла dom прозрачен только в Windows независимо от браузера.

Мне удалось значительно улучшить качество, просто удалив console.log () из моего метода getItemStyles (props). Это не помогает OP, но, возможно, кто-то еще здесь спотыкается.

Итак, я клонировал это и запустил сервер разработки, и пример пользовательского предварительного просмотра перетаскивания также нестабилен. Однако, когда я создаю сайт (запустив npm run build-site ), сайт преобразуется в обычную разметку (без ссылок на компоненты React), и теперь пример предварительного просмотра перетаскивания работает плавно.

Итак, моя гипотеза заключается в том, что ReactDOM.renderToString ( ) улучшает производительность перетаскивания для пользовательского предварительного просмотра перетаскивания.

Это все еще серьезная проблема ... :(

592 Кажется, немного повезло, но я еще не смог выполнить форк и редактировать. Может быть, кто-нибудь еще сможет добраться до меня раньше меня.

@gaearon, мы любим тебя, чувак! Не оставляйте нас в ожидании! Укажите нам верное направление, и я уверен, что мы это исправим :)

У меня возникла проблема с прерывистой анимацией на настраиваемом слое перетаскивания, и я обнаружил, что это из-за чрезвычайно сложного дерева DOM.

Я работаю над приложением, в котором есть табличный компонент, который может отображать до тысяч строк и столбцов табличных данных, что создает что-то вроде 4-х элементов DOM на ячейку или около того. Когда таблица была пустой, слой перетаскивания работал нормально, но по мере увеличения количества данных, отображаемых в таблице, производительность настраиваемого слоя перетаскивания замедлялась. (В этом случае таблица вообще не участвует в работе источников перетаскивания или целей перетаскивания).

В этом случае производительность в Firefox не изменилась, в то время как производительность в Chrome резко ухудшилась по мере увеличения сложности дерева DOM.

Мне удалось решить проблему, поместив таблицу в отдельный слой компоновки в Chrome, применив для нее стиль с пустым свойством 3D-преобразования: transform: translate3d(0, 0, 0)

После этого производительность была сопоставима с демонстрационной страницей. Я не уверен, каковы будут последствия для этой библиотеки, но, поместив сложные части дерева DOM вашего приложения в отдельные слои композитинга, вы сможете исправить свои проблемы с производительностью.

@mgerring У вас есть дополнительная информация о том, как вы это сделали? Я бы хотел попробовать это в своем приложении

Да, мы начали с удаления каждого компонента, чтобы найти тот, который вызывал проблему, и, как только мы его нашли, перешли к той части, которая вызывала замедление, а затем к самому внешнему элементу, который может принимать style param мы написали: style={{transform: translate3d(0, 0, 0)}}

Я хотел оставить этот комментарий к # 592, но думаю, он применим и здесь.

Решение @mgerring сработало для меня.

@ alexey-belous Мы отказались от этой библиотеки и выбрали https://github.com/bevacqua/react-dragula
+1

Эта проблема была автоматически помечена как устаревшая, поскольку в последнее время не было активности. Он будет закрыт, если больше не будет активности. Спасибо за ваш вклад.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги