React-dnd: Captura de tela ruim no arrasto regular, movimento instável na visualização do arrasto personalizado

Criado em 8 mai. 2016  ·  22Comentários  ·  Fonte: react-dnd/react-dnd

Como muitos, tenho uma lista de cartas classificáveis. No meu caso, cada cartão é um bloco de conteúdo de uma postagem de blog e alguns deles são trechos de código renderizados com react-codemirror . A visualização do arrasto para os fragmentos incluiu um grande fundo branco que era igual à largura e à altura do texto dentro do editor de código do codemirror. Isso era indesejável, então tentei consertá-lo com CSS, mas não tive sorte e, conforme leio mais documentação, penso que não é possível porque o dnd está fazendo uma captura de tela do nó dom antes que novas classes ou estilos possam ser aplicados a ele (corrija-me se isso estiver errado, é claro)

Como não consegui fazer o css funcionar, tentei usar uma camada de arrastar personalizada para mostrar algo diferente para a visualização. Isso funciona muito bem, exceto que o arrasto se torna muito agitado, onde antes era bastante suave.

Aqui está um vídeo que demonstra o problema que acabei de descrever:

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

E suponho que você também queira ver algum código. Aqui está minha camada de arrastar 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)

Aqui estão as opções de configuração para a fonte de arrastar e destino de soltar

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

E aqui está o componente Card que está sendo arrastado

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)

Deixe-me saber se você precisar ver mais código do que isso, estou pensando que deve ser suficiente.

Sugestões para a) como eu poderia usar css para ocultar o fundo branco ou b) fazer o arrasto de visualização de arrasto personalizado mais suavemente seriam muito apreciadas!

Observe que este trabalho é parte de um curso de screencast sobre a construção de aplicativos com react / redux e que estou planejando fazer provavelmente 2-3 vídeos curtos em react-dnd para mostrar como os cartões de bloco de conteúdo classificáveis ​​são implementados. Esperando liberá-los o mais rápido possível!

needs info wontfix

Comentários muito úteis

Sim, começamos removendo todos os componentes para encontrar aquele que estava causando o problema e, assim que o encontramos, detalhamos a parte que estava causando a desaceleração e, em seguida, o elemento mais externo que pode aceitar um style param que escrevemos: style={{transform: translate3d(0, 0, 0)}}

Todos 22 comentários

Também notei instabilidade com o dragLayer personalizado (apenas executando o exemplo do site): http://gaearon.github.io/react-dnd/examples-drag-around-custom-drag-layer.html

Está tudo bem no Chrome, mas a animação é instável no Firefox. (no linux mint, firefox 46.0.1)

A propósito, biblioteca incrível!

@sslotsky Você já descobriu isso?

Do contrário, posso mergulhar nisso e ver se há algo inteligente em CSS que podemos fazer ou, alternativamente, qualquer coisa que possamos fazer para reduzir a instabilidade. Outras pessoas relataram que o desempenho da camada de arrasto personalizado deixa muito a desejar.

Não, ainda não descobri. Uma solução seria ótima para quando eu pudesse gravar o próximo vídeo!

Também estamos vendo isso, inscrevendo-nos neste problema para quaisquer atualizações

@kesne Apenas comentando para manter isso vivo. Se você tiver alguma atualização que valha a pena compartilhar, tenho certeza de que adoraríamos saber dela :)

Sim, eu adoraria uma solução para isso também. Estou procurando implementar mais do que simplesmente uma captura de tela do objeto arrastável, mas essencialmente um componente de reação super simples.

Vou acrescentar isso também. Também estamos vendo o mesmo problema.

Também estou enfrentando isso .. Arrastar e soltar simples funcionando bem. Mas tenho uma implementação muito complexa e isso está acontecendo.

Tem o mesmo problema. Alguém encontrou alguma solução ou solução alternativa?

@ alexey-belous Nós descartamos esta biblioteca e fomos com https://github.com/bevacqua/react-dragula

Mesmo problema aqui, ficaria feliz com quaisquer comentários adicionais.

Estive investigando esse problema e descobri que a captura de tela de arrastar o nó dom é transparente apenas no Windows, independentemente do navegador.

Consegui melhorar muito a qualidade apenas removendo um console.log () do meu método getItemStyles (props). Isso não ajuda o OP, mas talvez alguém mais tropeçando aqui.

Então, eu clonei isso e executei o servidor de desenvolvimento e o exemplo de visualização de arrastar personalizado também está instável. No entanto, quando eu construo o site (executando npm run build-site ), o site é convertido para marcação regular (sem referências ao componente React) e agora o exemplo de visualização de arrastar está funcionando sem problemas.

Portanto, minha hipótese é que ReactDOM.renderToString ( ) melhora o desempenho de arrastar e soltar para visualização personalizada de arrastar.

Este ainda é um problema importante ... :(

592 Parece ter tido um pouco de sorte, mas ainda não consegui fazer o fork e editar. Talvez outra pessoa consiga pegá-lo antes de mim.

@gaearon nós amamos você cara! Não nos deixe esperando! Mostre-nos a direção certa e tenho certeza que vamos consertar isso :)

Eu estava tendo um problema com a animação instável em uma camada de arrastar personalizada e descobri que era por causa de uma árvore DOM extremamente complexa.

Eu trabalho em um aplicativo que tem um componente de tabela que pode exibir até milhares de linhas e colunas de dados tabulares, o que cria algo como 4 elementos DOM por célula ou algo assim. Quando a tabela estava vazia, a camada de arrasto funcionava bem, mas conforme a quantidade de dados exibidos na tabela aumentava, o desempenho da camada de arrasto personalizada ficava mais lento. (Neste caso, a tabela não está envolvida de forma alguma com a operação das fontes de arrastar ou destinos de soltar).

Nesse caso, o desempenho no Firefox não mudou, enquanto o desempenho no Chrome piorou drasticamente quanto mais a complexidade da árvore DOM aumentava.

Consegui resolver o problema empurrando a tabela para sua própria camada de composição no Chrome, estilizando-a com uma propriedade de transformação 3D vazia: transform: translate3d(0, 0, 0)

Depois disso, o desempenho foi comparável à página de demonstração. Não tenho certeza de quais são as implicações para esta biblioteca, mas empurrando partes complexas da árvore DOM do seu aplicativo em camadas de composição separadas, você pode consertar seus problemas de desempenho.

@mgerring Você tem mais informações sobre como fez isso? Eu gostaria de experimentar no meu aplicativo

Sim, começamos removendo todos os componentes para encontrar aquele que estava causando o problema e, assim que o encontramos, detalhamos a parte que estava causando a desaceleração e, em seguida, o elemento mais externo que pode aceitar um style param que escrevemos: style={{transform: translate3d(0, 0, 0)}}

Eu pretendia deixar este comentário no nº 592, mas acho que se aplica aqui também

A solução

@ alexey-belous Nós descartamos esta biblioteca e fomos com https://github.com/bevacqua/react-dragula
+1

Este problema foi marcado automaticamente como obsoleto porque não teve atividades recentes. Ele será fechado se nenhuma outra atividade ocorrer. Obrigado por suas contribuições.

Esta página foi útil?
0 / 5 - 0 avaliações