像许多人一样,我有一个可排序的卡片列表。 就我而言,每张卡片都是博客文章的一个内容块,其中一些是用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 个短视频,以展示如何实现可排序的内容块卡。 希望尽快发布!
我也注意到自定义 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(
这仍然是一个主要问题... :(
@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
此问题已自动标记为陈旧,因为它最近没有活动。 如果没有进一步的活动发生,它将被关闭。 感谢你的贡献。
最有用的评论
是的,我们首先删除每个组件以找到导致问题的组件,一旦我们找到它,就深入到导致速度变慢的部分,然后在可以接受
style
的最外层元素上我们写的style={{transform: translate3d(0, 0, 0)}}