Просмотр исходного кода

Removed flickering from drag enter/leave transition

Benoît Hubert 7 лет назад
Родитель
Сommit
9241c8384a
1 измененных файлов с 83 добавлено и 19 удалено
  1. 83 19
      react-admin/src/components/Home.js

+ 83 - 19
react-admin/src/components/Home.js

@@ -37,12 +37,41 @@ const tutos = [
 console.log(tutos);
 
 class Tree extends React.Component {
+  constructor(props) {
+    super(props);
+    this.onDragStart = this.onDragStart.bind(this);
+    this.onDragOver = this.onDragOver.bind(this);
+    this.state = {
+      draggedItem: null,
+      draggedOver: null
+    };
+  }
+
+  onDragStart(draggedItem) {
+    console.log('tree.onDragStart', draggedItem, this);
+    const { draggedOver } = this.state;
+    this.setState((prevState, props) => ({
+      draggedItem, draggedOver
+    }));
+  }
+
+  onDragOver(draggedOver) {
+    console.log('tree.onDragOver', draggedOver, this);
+    const { draggedItem } = this.state;
+    this.setState((prevState, props) => ({
+      draggedItem, draggedOver
+    }));
+  }
+
   render() {
     const { items } = this.props;
+    const { draggedItem, draggedOver } = this.state;
     return (
       <div>
+        {(! draggedItem) ? 'X' : draggedItem.props.path} |
+        {(! draggedOver) ? 'Y' : draggedOver.props.path}
         {items.map((item, i) =>
-          <TreeNode item={item} key={item.title} index={i} level={0} />
+          <TreeNode tree={this} item={item} key={item.title} index={i} path={i} level={0} />
         )}
       </div>
     );
@@ -61,9 +90,12 @@ class TreeNode extends React.Component {
     this.onDragOver = this.onDragOver.bind(this);
     this.onDragLeave = this.onDragLeave.bind(this);
     this.state = {
-      dragOver: false
+      dragged: false, dragOver: false, aboveMidLine: false
     };
     this.hid = getHandleId();
+    console.log('TreeNode', this.props.path, this.props.item.title)
+
+    this.drags = 0;
   }
 
   onMouseDown(e) {
@@ -79,8 +111,17 @@ class TreeNode extends React.Component {
     
     const { draggable } = this;
     var handle = draggable.getElementsByClassName('drag-handle')[0];
+    console.log('onDragStart', handle, draggable);
     if (handle.contains(this.dragTarget)) {
       e.dataTransfer.setData('text/plain', handle.id);
+      this.props.tree.onDragStart(this);
+      const { dragOver, aboveMidLine } = this.state;
+
+      this.setState({
+        dragged: true, dragOver, aboveMidLine
+      });
+
+
     } else {
       e.preventDefault();
     }
@@ -97,13 +138,35 @@ class TreeNode extends React.Component {
     const aboveMidLine = pageY < this.draggableMidLine;
     // console.log(aboveMidLine);
 
+
+this.props.tree.onDragOver(this);
+
+    const { dragged } = this.state;
 // console.log(this.draggable, e.target);
 //     if(this.draggable !== e.target) return;
-    this.setState({
-      dragOver: true, aboveMidLine
-    });
+    // this.setState({
+    //   dragged, dragOver: true, aboveMidLine
+    // });
     console.log(this.props.index);
 
+
+    this.scheduleDragOverChange(1);
+  }
+
+  scheduleDragOverChange(change) {
+    // const setState = this.setState.bind(this);
+    const self = this;
+    if(this.timeout) {
+      clearTimeout(this.timeout);
+    }
+    this.drags += change;
+    // const { dragged, dragOver,  }
+    this.timeout = setTimeout(() => {
+      console.log('drags change/total', change, self.drags)
+      this.setState({
+        dragOver: self.drags > 0
+      });
+    }, 100);
   }
 
   componentDidMount() {
@@ -113,9 +176,10 @@ class TreeNode extends React.Component {
 
   onDragLeave(e) {
     e.stopPropagation();
-      this.setState({
-        dragOver: false
-      });
+      // this.setState({
+      //   dragOver: false
+      // });
+      this.scheduleDragOverChange(-1);
     // console.log(e.pageY);
     // this.dragOver = '';
     // console.log('dragleave', this.state.dragOver);
@@ -123,27 +187,27 @@ class TreeNode extends React.Component {
 
   render() {
     const { title, items } = this.props.item;
-    const { level } = this.props;
+    const { tree, path, level } = this.props;
     const { dragOver, aboveMidLine } = this.state;
     const paddingLeft = (level * 15) + 'px';
     const dragPlaceholderStyles = {
       minHeight: '39px', border: '1px dashed blue'
     }
     return (
-        <div
+      <div draggable
+        ref={(div) => { this.draggable = div; }}
           className={ "tree-node" + (dragOver ? ' drag-over' : '') }
           style={{ paddingLeft }}
           onMouseDown={this.onMouseDown}
           onDragStart={this.onDragStart}
-          onDragOver={this.onDragOver}
-          onDragLeave={this.onDragLeave}
-          ref={(div) => { this.draggable = div; }}
-          draggable>
-          <h5><i id={ this.hid } className="material-icons drag-handle">drag_handle</i><span>{ title }</span></h5>
-          {(items || []).map((item, i) =>
-            <TreeNode item={item} index={i} key={item.title} level={level + 1} />
-          )}
-        </div>
+          onDragEnter={this.onDragOver}
+          onDragLeave={this.onDragLeave}>
+        <h5><i id={ this.hid } className="material-icons drag-handle">drag_handle</i><span>{ title }</span></h5>
+        {(items || []).map((item, i) =>
+          <TreeNode tree={tree} item={item} index={i} key={item.title} path={ path + '.' + i} level={level + 1} />
+        )}
+      {this.state.dragOver ? <div style={dragPlaceholderStyles}></div> : ''}
+      </div>
     );
   }
 }