Heim >Web-Frontend >js-Tutorial >Eine kurze Analyse, wie Angular+rxjs die Drag-and-Drop-Funktion implementiert?

Eine kurze Analyse, wie Angular+rxjs die Drag-and-Drop-Funktion implementiert?

青灯夜游
青灯夜游nach vorne
2022-04-30 10:00:173181Durchsuche

Wie implementiert man die Drag-and-Drop-Funktion mit Angular+rxjs? Der folgende Artikel stellt Ihnen vor, wie Angular mit rxjs kombiniert wird, um Drag & Drop zu implementieren. Ich hoffe, er wird Ihnen hilfreich sein!

Eine kurze Analyse, wie Angular+rxjs die Drag-and-Drop-Funktion implementiert?

Im vorherigen Artikel haben wir etwas über benutzerdefinierte Videooperationen in Angular erfahren. Leser, die es noch nicht erlebt haben, können sich zuerst darüber informieren.

Jetzt gibt es so eine Nachfrage, wie wollen Sie das realisieren?

Wenn die Bildlaufhöhe im Video-Tag auf der Seite ihre Position überschreitet, stellen Sie sie so ein, dass sie frei im sichtbaren Bereich gezogen werden kann.

Eine gute Idee, wenn Sie Angulars @angular/cdk/drag-drop verwenden, kann sie leicht umgesetzt werden, aber wir Habe es hier nicht. Benutze Werkzeuge. [Verwandte Tutorial-Empfehlungen: „Idea,如果你使用 Angular@angular/cdk/drag-drop 可以轻松实现,但是我们这里不使用工具。【相关教程推荐:《angular教程》】

好吧,我们来分析下实现的思路:

  • 页面滚动高度大于视频所在的位置:那么就是视频的 bottom 值相对可视窗口的值要小于0,我们需要设定一个包裹 video 标签的 div 方便计算,其高度是原设定 video 的高度。即元素脱离原文档布局
  • video 元素可以拖拽,那么其定位需要被改变为 fixed
  • video 元素在可视区内自由拖动,那么需要对其 top, left 值进行限定

所以我们设定下面的 demo 布局:

<div id="anchor" #anchor>
  <div class="video" id="video" #video>
    <div class="masker"></div>
    <video width="100%" height="100%" controls poster="assets/poster.png">
      <source src="../assets/demo.mp4" type="video/mp4" />
      Your browser does not support.
    </video>
  </div>
</div>

有下面这些预定的样式:

<!-- styles.scss -->
<!-- 这部分需要放在全局样式中 -->
html, body {
  height: 6000px;
  background-color: #fff;
}
<!-- demo.component.scss -->

#anchor {
  height: 360px;
  width: 100%;
  background-color: #F0F0F0;
}

.video {
  width: 640px;
  height: 360px;
  margin: 0 auto;
  background-color: black;
  <!-- video fixed 布局的样式,默认布局中是没有的 -->
  &.video-fixed { 
    position: fixed;
    top: 10px;
    left: 10px;
    width: 320px;
    height: 150px;
    cursor: all-scroll;
    .masker {
         display: none;
      }
    &:hover {
      .masker {
        display: block;
        position: absolute;
        width: 100%;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.8);
        z-index: 2;
      }
    }
  }
}

这里还引入了 rxjs 来操作。

元素脱离原文档布局

刚才已经分析了 video 元素脱离文档的临界调节了:

video 的外 div,即 #anchor 元素的相对视图的 bottom 。所以我们有:

@ViewChild(&#39;anchor&#39;, { static: false })
public anchor!: ElementRef;
@ViewChild(&#39;video&#39;, { static: false })
public video!: ElementRef;

public scroll!: any;

ngAfterViewInit(): void {
  this.scroll = fromEvent(document, &#39;scroll&#39;);
  this.scrollFn();
}

// 页面滚动
public scrollFn() {
  this.scroll
    .pipe(
      debounceTime(50), // 防抖
      map(() => this.anchor.nativeElement.getBoundindClientRect().bottom < 0)
    )
    .subscribe((flag: boolean) => {
      // 添加和移除样式
      if(flag) {
        this.video.nativeElement.classList.add(&#39;video-fixed&#39;);
      } else {
        this.video.nativeElement.classList.remove(&#39;video-fixed&#39;);
      }
    })
}

Eine kurze Analyse, wie Angular+rxjs die Drag-and-Drop-Funktion implementiert?

先获取 anchor 元素对象,监听页面对象 document 滚动(我们这里加入了防抖函数优化),当 bottom 的时候,将相关的样式 <code>video-fixed 添加给 video

元素拖拽

接下来就是实现 video 元素的拖拽。这里我们要监听 video 元素的三个事件,分别是鼠标按下 mousedown,鼠标移动 mousemove 和鼠标抬起 mouseup

// demo.component.ts

public mouseDown!: any;
public mouseUp!: any;
public mouseMove!: any;

ngAfterViewInit(): void {
  this.mouseDown = fromEvent(this.video.nativeElement, &#39;mousedown&#39;); // 目标元素按下,即 video
  this.mouseMove = fromEvent(document, &#39;mousemove&#39;); // 元素在文档内移动
  this.mouseUp = fromEvent(document, &#39;mouseup&#39;); // 鼠标抬起
  
  this.moveFn()
}

// 目标元素移动
public moveFn() {
  this.mouseDown
    .pipe(
      filter(() => this.video.nativeElement.classList.contains(&#39;video-fixed&#39;)),
      map(() => this.mouseMove.pipe(
        throttleTime(50), // 节流
        takeUntil(this.mouseUp)
      )),
      // concatAll 顺序接受上游抛出的各个数据流作为它的数据, 若前面的数据流不能同步的完结,它会暂存后续数据流,当前数据流完成后它才会订阅后一个暂存的数据流
      concatAll(),
      withLatestFrom(this.mouseDown, (move:any, down:any) => {
        return {
          x: this.validValue(move.clientX - down.offsetX, window.innerWidth - this.video.nativeElement.offsetWidth, 0),
          y: this.validValue(move.clientY - down.offsetY, window.innerHeight - this.video.nativeElement.offsetHeight, 0)
        }
      })
    )
    .subscribe((position: {
      x: number,
      y: number
    }) => {
      this.video.nativeElement.style.top = position.y + &#39;px&#39;;
      this.video.nativeElement.style.left = position.x + &#39;px&#39;;
    })
}

// 校验边界值
public validValue = (value:number, max:number, min: number) => {
  return Math.min(Math.max(value, min), max)
}

我们监听目标元素(filter 函数)被鼠标按下,然后鼠标可以在 document 范围内移动(这里用节流函数优化了下),直到监听到鼠标抬起。在移动的过程中,计算目标元素的相对可视窗口左侧和顶部的距离,将值赋予到 lefttop

这里的计算 move.clientX - down.offsetX, window.innerWidth - this.video.nativeElement.offsetWidthAngular-Tutorial

“]

Okay, analysieren wir die Implementierungsidee:

  • Die Scrollhöhe der Seite ist größer als die Position des Videos: Dann ist es der unten-Wert sollte relativ zum Wert des visuellen Fensters kleiner als 0 sein. Wir müssen ein <code>div festlegen, das das video-Tag umschließt Zur einfacheren Berechnung entspricht die Höhe der ursprünglichen Einstellung von Die Höhe des Videos. Das heißt, das Element befindet sich außerhalb des ursprünglichen Dokumentlayouts
  • video Das Element kann per Drag & Drop verschoben werden, daher muss seine Positionierung in festgeändert werden >
  • video-Element kann frei innerhalb des visuellen Bereichs gezogen werden, dann sind seine Werte top, left erforderlich begrenzt werden
Eine kurze Analyse, wie Angular+rxjs die Drag-and-Drop-Funktion implementiert?Also stellen wir das folgende demo-Layout ein: rrreee

hat die folgenden vorgegebenen Stile:

rrreeerrreee

Hier werden auch rxjs vorgestellt für den Betrieb.

Das Element entspricht nicht dem ursprünglichen Dokumentlayout🎜🎜🎜Ich habe gerade die kritische Anpassung des video-Elements analysiert aus dem Dokument: 🎜🎜 Der äußere div von 🎜video🎜 ist der bottom der relativen Ansicht des <code>#anchor-Elements . Wir haben also: 🎜rrreee🎜Eine kurze Analyse, wie Angular+rxjs die Drag-and-Drop-Funktion implementiert?🎜🎜Zuerst das anchor-Elementobjekt abrufen und das Scrollen des Seitenobjekts document überwachen (wir haben hier eine Anti-Shake-Funktionsoptimierung hinzugefügt). , fügen Sie den entsprechenden Stil video-fixed zu video hinzu. 🎜🎜🎜Element-Ziehen🎜🎜🎜Der nächste Schritt besteht darin, das Ziehen des video-Elements zu implementieren. Hier wollen wir uns drei Ereignisse des video-Elements anhören, nämlich Maus nach unten mousedown, Mausbewegung mousemove und Maus nach oben mouseup . 🎜rrreee🎜Wir hören zu, wie die Maus auf das Zielelement (Filterfunktion) drückt, und dann kann sich die Maus innerhalb des Bereichs von <code>document bewegen (hier wird mit der Drosselungsfunktion optimiert), bis die Maus gedrückt wird erzogen. Während der Bewegung wird der Abstand links und oben vom Zielelement relativ zum Sichtfenster berechnet und die Werte left und top zugewiesen. 🎜🎜Die Berechnung hier ist move.clientX - down.offsetX, window.innerWidth - this.video.nativeElement.offsetWidth Sie sind sich vielleicht nicht ganz im Klaren über die zugehörigen Konzepte, aber das spielt keine Rolle . Bitte verstehen Sie den obigen Inhalt. Relevante Wissenspunkte werden in den folgenden Artikeln vorgestellt. 🎜🎜Der Effekt, den wir erzielt haben, ist wie folgt🎜🎜🎜🎜🎜【Ende】🎜🎜Weitere Programmierkenntnisse finden Sie unter: 🎜Programmiervideo🎜! ! 🎜

Das obige ist der detaillierte Inhalt vonEine kurze Analyse, wie Angular+rxjs die Drag-and-Drop-Funktion implementiert?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen