繁体   English   中英

如何在 Angular2 中实现拖放?

[英]How to implement drag and drop in Angular2?

我想使用 Angular 2 实现拖放。我有一些项目:

<div class="item"></div>

我希望能够将其拖放到容器中:

<div class="container"></div>

我在 Angular 2 中找不到任何好的信息来源。我找到了这个文件: https : //github.com/AngularClass/angular2-examples/blob/master/rx-draggable/directives/draggable.ts尝试过但我无法让它工作,我也不完全确定它应该如何工作。

我该如何实施?

尝试这个:

function onDragStart(event, data) {
  event.dataTransfer.setData('data', data);
}
function onDrop(event, data) {
  let dataTransfer = event.dataTransfer.getData('data');
  event.preventDefault();
}
function allowDrop(event) {
  event.preventDefault();
}
<div (drop)="onDrop($event, dropData)" (dragover)="allowDrop($event)"></div>
<div draggable="true" (dragstart)="onDragStart($event, dragData)"></div>

尝试这个:

systemjs.config:

var map =       {
    'app': './wwwroot/ngApp',
    'rxjs': './wwwroot/js/libs/rxjs',
    '@angular': './wwwroot/js/libs/@angular',
    'dragula': './wwwroot/js/libs/dragula/dist/dragula.js',
    'ng2-dragula': './wwwroot/js/libs/ng2-dragula'
  };

var packages = {
    'app': { main: 'main.js', defaultExtension: 'js' },
    'rxjs': { defaultExtension: 'js' },
    'dragula': { defaultExtension: 'js' },
    'ng2-dragula': {defaultExtension: 'js' }
  };

var config = {
    map: map,
    packages: packages  
  }`

然后导入

import {Dragula, DragulaService} from 'ng2-dragula/ng2-dragula';

而在@Component

directives: [Dragula], viewProviders: [DragulaService]

我建议使用Ng2-Dragula

它是 angular2 依赖项,它可以轻松地为您的应用程序提供拖放功能。

您需要做的就是通过 npm 安装此依赖项。

npm install ng2-dragula dragula --save

在 index.html 中添加包含并将系统配置为

<script src="/node_modules/ng2-dragula/bundles/ng2-dragula.js"></script>
<link href="/node_modules/ng2-dragula/src/public/css/dragula.min.css" rel='stylesheet' type='text/css'>
<script>
    System.config({        
    paths:{
        'dragula'         : '../node_modules/dragula/dist/dragula.min.js'
    },
    packages: {            
      app: {
        format: 'register',
        defaultExtension: 'js'
      }
    }
  });

 System.import('app/main')
       .then(null, console.error.bind(console));
</script>

将它导入到要使用拖放的组件中,就可以了。

@Component({
  selector: 'sample',
  directives: [Dragula],
  viewProviders: [DragulaService],
  template:`
  <div>
    <div class='wrapper'>
      <div class='container' [dragula]='"first-bag"'>
        <div>You can move these elements between these two containers</div>
        <div>Moving them anywhere else isn't quite possible</div>
        <div>There's also the possibility of moving elements around in the same container, changing their position</div>
      </div>
      <div class='container' [dragula]='"first-bag"'>
        <div>This is the default use case. You only need to specify the containers you want to use</div>
        <div>More interactive use cases lie ahead</div>
        <div>Make sure to check out the <a href='https://github.com/bevacqua/dragula#readme'>documentation on GitHub!</a></div>
      </div>
    </div>
  </div>
  `
})
class Sample {}

我也开始为我的可拖动对象使用相同的示例 - 并且确实让它起作用。 该示例来自 angular2 的早期版本,因此需要进行一些更改。 看看这个答案 它有一些变化。 祝你好运!

我自己稍微更通用的版本是这样的:

import {Directive, EventEmitter, HostListener, Output} from 'angular2/core';
import {Observable} from 'rxjs/Observable';

@Directive({
  selector: '[draggable]'
})
export class DraggableDirective {

  @Output() mousedrag: Observable<{x: number, y: number}>;
  @Output() dragend = new EventEmitter<void>();
  mousedown = new EventEmitter<MouseEvent>();
  mousemove = new EventEmitter<MouseEvent>();
  dragActive = false;

  @HostListener('document:mouseup', ['$event'])
  onMouseup(event) {
    if(this.dragActive) {
      this.dragend.emit(null);
      this.dragActive = false;
    }
  }

  @HostListener('mousedown', ['$event'])
  onMousedown(event: MouseEvent) {
    this.mousedown.emit(event);
  }

  @HostListener('document:mousemove', ['$event'])
  onMousemove(event: MouseEvent) {
    if(this.dragActive) {
      this.mousemove.emit(event);
      return false;
    }
  }

  constructor() {
    this.mousedrag = this.mousedown.map((event) => {
      this.dragActive = true;
      return { x: event.clientX, y: event.clientY };
    }).flatMap(mouseDownPos => this.mousemove.map(pos => {
      return { x: pos.clientX - mouseDownPos.x, y: pos.clientY - mouseDownPos.y };
    }).takeUntil(this.dragend));
  }
}

因为我目前正在寻找似乎与该指令有关的内存泄漏,所以请稍加注意。 如果我发现问题,我会更新。

我已经使用 jquery draggable 完成了它 - 集成在 Angular 中

import {Component, ElementRef, OnInit} from '@angular/core';'

declare var jQuery:any;

@Component({
    selector: 'jquery-integration',
    templateUrl: './components/jquery-integration/jquery-integration.html'
})
export class JqueryIntegration implements OnInit {
    elementRef: ElementRef;
    constructor(elementRef: ElementRef) {
        this.elementRef = elementRef;
    }
    ngOnInit() {
        jQuery(this.elementRef.nativeElement).draggable({containment:'#draggable-parent'});
    }
}

更多信息在这里: http : //www.syntaxsuccess.com/viewarticle/using-jquery-with-angular-2.0

现场演示: http : //www.syntaxsuccess.com/angular-2-samples/#/demo/jquery

俄语的答案效果很好,但变化检测使它变慢。 您可以使用自定义指令解决此问题。

功劳来自这里https://netbasal.com/angular-2-escape-from-change-detection-317b3b44906b

import {Directive, ElementRef, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output} from '@angular/core';

@Directive({
  selector: '[appIgnoreEvent]'
})
export class IgnoreEventDirective implements OnInit, OnDestroy {
  @Input() event = 'dragover';
  @Output() emitter = new EventEmitter();
  private _handler: Function;
  constructor(private _ngZone: NgZone, private el: ElementRef) {}

  ngOnInit() {
    this._ngZone.runOutsideAngular(() => {
      const nativeElement = this.el.nativeElement;
      this._handler = $event => {
        this.emitter.emit($event);
      };

      nativeElement.addEventListener(this.event, this._handler, false);
    });
  }

  ngOnDestroy() {
    this.el.nativeElement.removeEventListener(this.event, this._handler);
  }
}

然后将 dragOver 事件传递给您的发射器。

<div (drop)="onDrop($event, dropData)" appIgnoreEvent (emitter)="allowDrop($event)"></div>

没有足够的声誉让我将此添加为评论

我为我的一个项目制作了这个组件,希望这会有所帮助。

 import { Component, OnInit, ViewChild, ElementRef, HostListener } from '@angular/core'; @Component({ selector: 'app-video-call-container', templateUrl: './video-call-container.component.html', styleUrls: ['./video-call-container.component.css'] }) export class VideoCallContainerComponent implements OnInit { constructor() { } mouseCursorX = 0; mouseCursorY = 0; dragActive = false; @ViewChild('container') container: ElementRef; @HostListener('window:mouseup', ['$event']) mouseUp(event) { if (this.dragActive == true) { this.dragActive = false; } } @HostListener('window:mousemove', ['$event']) mouseMove(event) { if (this.dragActive) { var left = this.mouseCursorX - event.clientX; var top = this.mouseCursorY - event.clientY; var offsets = this.getElementOffsets(this.container.nativeElement); var posLeft = (offsets.left - left); var posTop = (offsets.top - top); if (posLeft > 0 && posLeft <= window.innerWidth - this.container.nativeElement.offsetWidth && posTop > 0 && posTop <= window.innerHeight - this.container.nativeElement.offsetHeight) { this.container.nativeElement.style.left = posLeft + "px"; this.container.nativeElement.style.top = posTop + "px"; } this.mouseCursorX = event.clientX; this.mouseCursorY = event.clientY; } } drag(event) { this.dragActive = true; this.mouseCursorX = event.clientX; this.mouseCursorY = event.clientY; } getElementOffsets(elem) { return { top: this.getOffsetTop(elem), left: this.getOffsetLeft(elem) } } getOffsetTop(elem) { var offsetTop = 0; do { if (!isNaN(elem.offsetTop)) { offsetTop += elem.offsetTop; } } while (elem = elem.offsetParent); return offsetTop; } getOffsetLeft(elem) { var offsetLeft = 0; do { if (!isNaN(elem.offsetLeft)) { offsetLeft += elem.offsetLeft; } } while (elem = elem.offsetParent); return offsetLeft; } ngOnInit(): void { } }
 <div class="container-box" #container> <div class="container-header" (mousedown)="drag($event)"> <label>Vikas Kandari</label> <span>Ringing...</span> <button><i class="fa fa-close"></i></button> </div> <div class="container-body"> <div class="video-call-caller"> <video></video> </div> <div class="video-call-receiver"> <video></video> </div> </div> </div>
 .container-box { position: fixed; background-color: #fefefe; border-radius: 2px; box-shadow: 0 0 0 1px rgba(0,0,0,.15), 0 2px 3px rgba(0,0,0,.2); z-index: 9999999999999; right: 15px; bottom: 50px; width: 300px; height: 400px; } .container-header { width: 100%; float: left; padding: 10px; border-bottom: 1px solid #ddd; cursor: move; } .container-header>label { display: block; width: 100%; float: left; margin: 0px; cursor: move; } .container-header>button { position: absolute; right: 10px; top: 10px; border-radius: 100%; height: 30px; width: 30px; border: none; font-size: 20px; background: transparent; cursor: pointer; } .container-header>span { display: block; float: left; width: 100%; cursor: move; } .container-header:hover>button { background: #e6ecf0; }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM