React-dnd: Schlechter Screenshot bei normalem Ziehen, abgehackte Bewegung bei benutzerdefinierter Ziehvorschau

Erstellt am 8. Mai 2016  ·  22Kommentare  ·  Quelle: react-dnd/react-dnd

Wie viele habe ich eine Liste mit sortierbaren Karten. In meinem Fall ist jede Karte ein Inhaltsblock eines Blogposts und einige davon sind Codeschnipsel, die mit react-codemirror gerendert werden. Die Ziehvorschau für die Snippets enthielt einen großen weißen Hintergrund, der der Breite und Höhe des Textes im Code-Editor von codemirror entsprach. Dies war unerwünscht, also habe ich versucht, es mit CSS zu reparieren, hatte aber kein Glück, und als ich mehr Dokumentation lese, denke ich, dass dies nicht möglich ist, da dnd einen Screenshot des dom-Knotens erstellt, bevor neue Klassen oder Stile darauf angewendet werden können (bitte korrigieren Sie mich .) wenn das natürlich falsch ist)

Da ich CSS nicht zum Laufen bringen konnte, habe ich versucht, eine benutzerdefinierte Drag-Ebene zu verwenden, um etwas anderes für die Vorschau anzuzeigen. Das funktioniert großartig, außer dass das Ziehen wirklich abgehackt wird, wo es vorher eigentlich ziemlich glatt war.

Hier ist ein Video, das das gerade beschriebene Problem demonstriert:

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

Und ich nehme an, Sie möchten auch etwas Code sehen. Hier ist mein benutzerdefinierter Drag-Layer

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)

Hier sind die Konfigurationsoptionen für das Drag Source & Drop-Ziel

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

Und hier ist die Card Komponente, die gezogen wird

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)

Lassen Sie es mich wissen, wenn Sie mehr Code sehen möchten, ich denke, dies sollte ausreichen.

Vorschläge für entweder a) wie ich CSS verwenden könnte, um den weißen Hintergrund auszublenden oder b) die benutzerdefinierte Drag-Vorschau glatter zu machen, wären sehr dankbar!

Beachten Sie, dass diese Arbeit Teil eines Screencast-Kurses zum Erstellen von Apps mit React/Redux ist und ich plane, wahrscheinlich 2-3 kurze Videos zu React-dnd zu machen, um zu zeigen, wie die sortierbaren Inhaltsblockkarten implementiert werden. In der Hoffnung, diese so schnell wie möglich veröffentlichen zu können!

needs info wontfix

Hilfreichster Kommentar

Ja, wir begannen damit, jede Komponente zu entfernen, um diejenige zu finden, die das Problem verursachte, und sobald wir sie gefunden hatten, gingen wir auf den Teil herunter, der die Verlangsamung verursachte, und dann auf das äußerste Element, das ein style akzeptieren kann style={{transform: translate3d(0, 0, 0)}}

Alle 22 Kommentare

Ich habe auch beim benutzerdefinierten DragLayer (nur das Beispiel der Website) Abhacken bemerkt: http://gaearon.github.io/react-dnd/examples-drag-around-custom-drag-layer.html

In Chrome ist alles in Ordnung, aber in Firefox ist die Animation abgehackt. (unter Linux Mint, Firefox 46.0.1)

Übrigens eine tolle Bibliothek!

@sslotsky Hast du das jemals herausgefunden?

Wenn nicht, kann ich mich damit befassen und sehen, ob wir in CSS etwas cleveres tun können oder alternativ etwas tun können, um die Abhackung zu reduzieren. Andere Leute haben berichtet, dass die Leistung der benutzerdefinierten Drag-Layer viel zu wünschen übrig lässt.

Nö, habe es immer noch nicht herausgefunden. Eine Lösung wäre toll, wenn ich dazu komme, das nächste Video aufzunehmen!

Wir sehen dies auch und abonnieren diese Ausgabe für alle Updates

@kesne Nur kommentieren, um das am Leben zu erhalten. Wenn Sie irgendwelche Updates haben, die es wert sind, geteilt zu werden, würden wir uns sicher freuen, davon zu hören :)

Ja, ich würde mich auch hier über eine Lösung freuen. Ich möchte mehr als nur einen Screenshot des ziehbaren Objekts implementieren, sondern im Wesentlichen eine supereinfache Reaktionskomponente.

Ich werde auch darauf eingehen. Wir sehen auch das gleiche Problem.

Ich laufe auch darauf. Einfaches Drag & Drop funktioniert gut. Aber ich habe eine Implementierung, die zu komplex ist, und dies geschieht.

Habe das gleiche Problem. Hat jemand eine Lösung oder einen Workaround gefunden?

@alexey-belous Wir haben diese Bibliothek verschrottet und sind mit https://github.com/bevacqua/react-dragula gegangen

Gleiches Thema hier, würde mich über weitere Kommentare freuen.

Ich habe dieses Problem untersucht und festgestellt, dass der Screenshot des Ziehens des Dom-Knotens nur unter Windows unabhängig vom Browser transparent ist.

Ich konnte die Qualität erheblich verbessern, indem ich einfach eine console.log() aus meiner getItemStyles(props)-Methode entfernt habe. Das hilft dem OP nicht, aber vielleicht stolpert hier noch jemand.

Also habe ich dies geklont und den Dev-Server ausgeführt, und das Beispiel für die benutzerdefinierte Drag-Vorschau ist auch abgehackt. Wenn ich jedoch die Site erstelle (indem ich npm run build-site ), wird die Site in normales Markup (ohne React-Komponentenreferenzen) konvertiert und jetzt läuft das Drag-Preview-Beispiel reibungslos.

Meine Hypothese ist also, dass ReactDOM.renderToString( ) verbessert die Drag-and-Drop-Leistung für die benutzerdefinierte Drag-Vorschau.

Das ist immer noch ein großes Thema... :(

592 Scheint etwas Glück gehabt zu haben, aber ich konnte noch nicht forken und bearbeiten. Vielleicht kommt jemand anderes dazu, bevor ich es tue.

@gaearon wir lieben dich Mann! Lass uns nicht hängen! Zeigen Sie uns in die richtige Richtung und ich bin sicher, wir werden es reparieren :)

Ich hatte ein Problem mit abgehackter Animation auf einer benutzerdefinierten Drag-Ebene und stellte fest, dass dies an einem extrem komplexen DOM-Baum lag.

Ich arbeite an einer App, die über eine Tabellenkomponente verfügt, die bis zu Tausenden von Zeilen und Spalten mit Tabellendaten anzeigen kann, wodurch etwa 4 DOM-Elemente pro Zelle oder so erstellt werden. Wenn die Tabelle leer war, funktionierte der Drag-Layer einwandfrei, aber als die in der Tabelle angezeigte Datenmenge zunahm, verlangsamte sich die Leistung des benutzerdefinierten Drag-Layers. (In diesem Fall ist die Tabelle überhaupt nicht an der Bedienung der Drag-Quellen oder Drop-Ziele beteiligt).

In diesem Fall änderte sich die Leistung in Firefox nicht, während die Leistung in Chrome dramatisch schlechter wurde, je komplexer der DOM-Baum wurde.

Ich konnte das Problem lösen, indem ich die Tabelle in Chrome in eine eigene Compositing-Ebene schob, indem ich sie mit einer leeren 3D-Transformationseigenschaft gestaltete: transform: translate3d(0, 0, 0)

Danach war die Leistung mit der der Demoseite vergleichbar. Ich bin mir nicht sicher, welche Auswirkungen diese Bibliothek hat, aber indem Sie komplexe Teile des DOM-Baums Ihrer Anwendung in separate Compositing-Schichten verschieben, können Sie möglicherweise Ihre Leistungsprobleme beheben.

@mgerring Hast du weitere Informationen dazu, wie du das gemacht hast? Ich würde es gerne in meiner App ausprobieren

Ja, wir begannen damit, jede Komponente zu entfernen, um diejenige zu finden, die das Problem verursachte, und sobald wir sie gefunden hatten, gingen wir auf den Teil herunter, der die Verlangsamung verursachte, und dann auf das äußerste Element, das ein style akzeptieren kann style={{transform: translate3d(0, 0, 0)}}

Ich wollte diesen Kommentar zu #592 hinterlassen, aber ich denke, er gilt auch hier

@mgerring- Lösung hat bei mir funktioniert.

@alexey-belous Wir haben diese Bibliothek verschrottet und sind mit https://github.com/bevacqua/react-dragula gegangen
+1

Dieses Problem wurde automatisch als veraltet markiert, da es in letzter Zeit keine Aktivität hatte. Es wird geschlossen, wenn keine weitere Aktivität stattfindet. Vielen Dank für Ihre Beiträge.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen