React-dnd: 常规拖动时的屏幕截图不佳,自定义拖动预览时出现断断续续的动作

创建于 2016-05-08  ·  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)

如果您需要查看更多代码,请告诉我,我认为这应该足够了。

对于 a) 我如何使用 css 来隐藏白色背景或 b) 使自定义拖动预览拖动更平滑的建议将非常感谢!

请注意,这项工作是关于使用 react/redux 构建应用程序的截屏课程的一部分,我计划在 react-dnd 上制作大约 2-3 个短视频,以展示如何实现可排序的内容块卡。 希望尽快发布!

needs info wontfix

最有用的评论

是的,我们首先删除每个组件以找到导致问题的组件,一旦我们找到它,就深入到导致速度变慢的部分,然后在可以接受style的最外层元素上我们写的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 上是透明的。

只需从我的 getItemStyles(props) 方法中删除 console.log() ,我就能够大大提高质量。 这对 OP 没有帮助,但也许其他人在这里磕磕绊绊。

所以我克隆了它并运行了开发服务器,自定义拖动预览示例也不稳定。 但是,当我构建站点(通过运行npm run build-site )时,站点被转换为常规标记(没有 React 组件引用),现在拖动预览示例运行顺利。

所以我的假设是 ReactDOM.renderToString( ) 改进了自定义拖动预览的拖放性能。

这仍然是一个主要问题... :(

592 好像有点运气,但是我还没能fork和edit。 也许其他人可以在我之前完成它。

@gaearon我们爱你,伙计! 不要让我们悬着! 为我们指明正确的方向,我相信我们会解决它:)

我在自定义拖动层上遇到断断续续的动画问题,并发现这是因为极其复杂的 DOM 树。

我正在开发一个应用程序,它有一个表格组件,可以显示多达数千行和列的表格数据,它为每个单元格创建 4 个左右的 DOM 元素。 当表格为空时,拖动层工作正常,但随着表格中显示的数据量增加,自定义拖动层的性能变慢。 (在这种情况下,表格完全不涉及拖放源或放置目标的操作)。

在这种情况下,Firefox 中的性能没有改变,而 Chrome 中的性能随着 DOM 树的复杂性增加而急剧恶化。

我能够通过将表格推入 Chrome 中自己的合成层来解决该问题,方法是使用空的 3D 变换属性对其进行样式设置: transform: translate3d(0, 0, 0)

之后,性能与演示页面相当。 我不确定这个库的含义是什么,但是通过将应用程序 DOM 树的复杂部分推送到单独的合成层,您可能能够解决性能问题。

@mgerring你有更多关于你是如何做到的信息吗? 我想在我的应用上试用

是的,我们首先删除每个组件以找到导致问题的组件,一旦我们找到它,就深入到导致速度变慢的部分,然后在可以接受style的最外层元素上我们写的style={{transform: translate3d(0, 0, 0)}}

我想在 #592 上留下这条评论,但我认为它也适用于这里

@mgerring解决方案对我

@alexey-belous 我们废弃了这个库并使用了https://github.com/bevacqua/react-dragula
+1

此问题已自动标记为陈旧,因为它最近没有活动。 如果没有进一步的活动发生,它将被关闭。 感谢你的贡献。

此页面是否有帮助?
0 / 5 - 0 等级