Как и у многих, у меня есть список сортируемых карточек. В моем случае каждая карточка представляет собой блок содержимого сообщения в блоге, а некоторые из них представляют собой фрагменты кода, отображаемые с помощью 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, чтобы показать, как реализованы сортируемые карточки блока содержимого. Надеемся выпустить их как можно скорее!
Я также заметил нестабильность при использовании настраиваемого 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 (
Это все еще серьезная проблема ... :(
@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
Эта проблема была автоматически помечена как устаревшая, поскольку в последнее время не было активности. Он будет закрыт, если больше не будет активности. Спасибо за ваш вклад.
Самый полезный комментарий
Да, мы начали с удаления каждого компонента, чтобы найти тот, который вызывал проблему, и, как только мы его нашли, перешли к той части, которая вызывала замедление, а затем к самому внешнему элементу, который может принимать
style
param мы написали:style={{transform: translate3d(0, 0, 0)}}