React-dnd: Captura de pantalla incorrecta en el arrastre regular, movimiento entrecortado en la vista previa de arrastre personalizado

Creado en 8 may. 2016  ·  22Comentarios  ·  Fuente: react-dnd/react-dnd

Como muchos, tengo una lista de cartas clasificables. En mi caso, cada tarjeta es un bloque de contenido de una publicación de blog y algunos de estos son fragmentos de código representados con react-codemirror . La vista previa de arrastre para los fragmentos incluía un gran fondo blanco que era igual al ancho y alto del texto dentro del editor de código de codemirror. Esto no era deseable, así que intenté arreglarlo con CSS pero no tuve suerte, y a medida que leo más documentación, creo que no es posible porque dnd está haciendo una captura de pantalla del nodo dom antes de que se puedan aplicar nuevas clases o estilos (corríjame). si eso está mal por supuesto)

Como no pude hacer que CSS funcionara, intenté usar una capa de arrastre personalizada para mostrar algo diferente para la vista previa. Esto funciona muy bien, excepto que el arrastre se vuelve muy entrecortado donde antes era bastante fluido.

Aquí hay un video que demuestra el problema que acabo de describir:

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

Y supongo que también querrás ver algún código. Aquí está mi capa de arrastre personalizada

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)

Aquí están las opciones de configuración para el origen de arrastrar y soltar destino

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()
  }
}

Y aquí está el componente Card que se está arrastrando

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)

Avíseme si necesita ver más código que ese, creo que esto debería ser suficiente.

Las sugerencias para a) cómo podría usar CSS para ocultar el fondo blanco ob) hacer que la vista previa de arrastre personalizado arrastre más suavemente sería muy apreciada.

Tenga en cuenta que este trabajo es parte de un curso de screencast sobre la creación de aplicaciones con react / redux y que planeo hacer probablemente 2-3 videos cortos en react-dnd para mostrar cómo se implementan las tarjetas de bloque de contenido clasificable. ¡Esperando lanzarlos lo antes posible!

needs info wontfix

Comentario más útil

Sí, comenzamos eliminando todos los componentes para encontrar el que estaba causando el problema, y ​​una vez que lo encontramos, profundizamos en la parte que estaba causando la desaceleración y luego en el elemento más externo que puede aceptar un style param escribimos: style={{transform: translate3d(0, 0, 0)}}

Todos 22 comentarios

También he notado irregularidades con el dragLayer personalizado (solo ejecutando el ejemplo del sitio web): http://gaearon.github.io/react-dnd/examples-drag-around-custom-drag-layer.html

Todo está bien en Chrome, pero la animación es entrecortada en Firefox. (en linux mint, firefox 46.0.1)

¡Biblioteca impresionante por cierto!

@sslotsky ¿Alguna vez te

Si no es así, puedo sumergirme en esto y ver si hay algo inteligente en CSS que podamos hacer o, alternativamente, algo que podamos hacer para reducir la agitación. Otras personas han informado que el rendimiento de la capa de arrastre personalizada deja mucho que desear.

No, todavía no lo he descubierto. ¡Una solución sería genial para cuando tenga la oportunidad de grabar el siguiente video!

También estamos viendo esto también, suscribiéndonos a este problema para recibir actualizaciones

@kesne Solo comentaba para mantener esto vivo. Si tiene alguna actualización que valga la pena compartir, estoy seguro de que nos encantaría saberla :)

Sí, también me encantaría una solución para esto. Estoy buscando implementar más que una simple captura de pantalla del objeto que se puede arrastrar, pero esencialmente un componente de reacción súper simple.

Yo también incluiré esto. También estamos viendo el mismo problema.

Me estoy encontrando con esto también ... Arrastrar y soltar simples funcionan bien. Pero tengo una implementación que es demasiado compleja y esto está sucediendo.

Tiene el mismo problema. ¿A alguien se le ocurrió alguna solución o solución temporal?

@ alexey-belous Eliminamos esta biblioteca y optamos por https://github.com/bevacqua/react-dragula

El mismo problema aquí, estaría encantado de recibir más comentarios.

He estado investigando este problema y descubrí que la captura de pantalla de arrastrar el nodo dom es transparente solo en Windows, independientemente del navegador.

Pude mejorar enormemente la calidad simplemente eliminando un console.log () de mi método getItemStyles (props). Esto no ayuda al OP, pero tal vez alguien más tropiece aquí.

Así que cloné esto y ejecuté el servidor de desarrollo y el ejemplo de vista previa de arrastre personalizado también está entrecortado. Sin embargo, cuando construyo el sitio (ejecutando npm run build-site ), el sitio se convierte al marcado regular (sin referencias de componentes de React) y ahora el ejemplo de vista previa de arrastre se está ejecutando sin problemas.

Entonces mi hipótesis es que ReactDOM.renderToString ( ) mejora el rendimiento de arrastrar y soltar para obtener una vista previa personalizada de arrastrar y soltar.

Este sigue siendo un problema importante ... :(

592 Parece haber tenido algo de suerte, pero todavía no he podido bifurcar y editar. Quizás alguien más pueda hacerlo antes que yo.

@gaearon ¡ te amamos hombre! ¡No nos dejes colgados! Indíquenos en la dirección correcta y estoy seguro de que lo arreglaremos :)

Tenía un problema con la animación entrecortada en una capa de arrastre personalizada y descubrí que se debía a un árbol DOM extremadamente complejo.

Trabajo en una aplicación que tiene un componente de tabla que puede mostrar hasta miles de filas y columnas de datos tabulares, lo que crea algo así como 4 elementos DOM por celda más o menos. Cuando la tabla estaba vacía, la capa de arrastre funcionaba bien, pero a medida que aumentaba la cantidad de datos mostrados en la tabla, el rendimiento de la capa de arrastre personalizada se ralentizaba. (En este caso, la tabla no está involucrada en absoluto con la operación de las fuentes de arrastre o los destinos de colocación).

En este caso, el rendimiento en Firefox no cambió, mientras que el rendimiento en Chrome empeoró drásticamente a medida que aumentaba la complejidad del árbol DOM.

Pude resolver el problema presionando la tabla en su propia capa de composición en Chrome, dándole estilo con una propiedad de transformación 3D vacía: transform: translate3d(0, 0, 0)

Después de eso, el rendimiento fue comparable al de la página de demostración. No estoy seguro de cuáles son las implicaciones para esta biblioteca, pero al colocar partes complejas del árbol DOM de su aplicación en capas de composición separadas, es posible que pueda solucionar sus problemas de rendimiento.

@mgerring ¿Tienes más información sobre cómo hiciste eso? Me gustaría probarlo en mi aplicación

Sí, comenzamos eliminando todos los componentes para encontrar el que estaba causando el problema, y ​​una vez que lo encontramos, profundizamos en la parte que estaba causando la desaceleración y luego en el elemento más externo que puede aceptar un style param escribimos: style={{transform: translate3d(0, 0, 0)}}

Quería dejar este comentario en el n. ° 592, pero creo que también se aplica aquí.

La solución

@ alexey-belous Eliminamos esta biblioteca y optamos por https://github.com/bevacqua/react-dragula
+1

Este problema se ha marcado automáticamente como obsoleto porque no ha tenido actividad reciente. Se cerrará si no se produce más actividad. Gracias por sus aportaciones.

¿Fue útil esta página
0 / 5 - 0 calificaciones