首頁  >  文章  >  web前端  >  淺析Angular+rxjs怎麼實現拖曳功能?

淺析Angular+rxjs怎麼實現拖曳功能?

青灯夜游
青灯夜游轉載
2022-04-30 10:00:173138瀏覽

Angular rxjs怎麼實現拖曳功能?以下這篇文章跟大家介紹一下Angular 結合 rxjs 實作拖曳的方法,希望對大家有幫助!

淺析Angular+rxjs怎麼實現拖曳功能?

在先前的文章,我們學習了 Angular 中自訂 Video 操作,沒有度過的讀者可先了解。

現在有這麼一個需求,你會怎麼實現呢?

頁面中 video 標籤,當滾動高度超過其位置之後,將其設定為可在可視區域自由拖曳。

一個不錯的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;);
      }
    })
}

淺析Angular+rxjs怎麼實現拖曳功能?

先取得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.offsetWidth,相關的概念也許你不是很清楚,不過沒關係,上面的內容,理解思路即可。相關的知識點會在接下來的文章中介紹。

最後,我們得到的效果如下

淺析Angular+rxjs怎麼實現拖曳功能?

【完】

更多程式相關知識,請造訪:程式設計影片! !

以上是淺析Angular+rxjs怎麼實現拖曳功能?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除