中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Angular+rxjs如何實現拖拽功能

發布時間:2022-04-29 13:37:30 來源:億速云 閱讀:192 作者:iii 欄目:web開發

這篇文章主要介紹“Angular+rxjs如何實現拖拽功能”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Angular+rxjs如何實現拖拽功能”文章能幫助大家解決問題。

Angular+rxjs如何實現拖拽功能

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

一個不錯的 Idea,如果你使用 Angular@angular/cdk/drag-drop 可以輕松實現,但是我們這里不使用工具。

好吧,我們來分析下實現的思路:

  • 頁面滾動高度大于視頻所在的位置:那么就是視頻的 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 < 0。所以我們有:

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

public scroll!: any;

ngAfterViewInit(): void {
  this.scroll = fromEvent(document, 'scroll');
  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('video-fixed');
      } else {
        this.video.nativeElement.classList.remove('video-fixed');
      }
    })
}

先獲取 anchor 元素對象,監聽頁面對象 document 滾動(我們這里加入了防抖函數優化),當 bottom < 0 的時候,將相關的樣式 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, 'mousedown'); // 目標元素按下,即 video
  this.mouseMove = fromEvent(document, 'mousemove'); // 元素在文檔內移動
  this.mouseUp = fromEvent(document, 'mouseup'); // 鼠標抬起
  
  this.moveFn()
}

// 目標元素移動
public moveFn() {
  this.mouseDown
    .pipe(
      filter(() => this.video.nativeElement.classList.contains('video-fixed')),
      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 + 'px';
      this.video.nativeElement.style.left = position.x + 'px';
    })
}

// 校驗邊界值
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如何實現拖拽功能”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

屯留县| 开江县| 宜君县| 娄底市| 策勒县| 兴海县| 大厂| 临朐县| 民权县| 永年县| 大化| 周口市| 青龙| 金阳县| 南和县| 桂林市| 正定县| 云南省| 南投县| 海宁市| 阿拉善右旗| 富宁县| 蓬安县| 青海省| 江油市| 临江市| 洛南县| 泸定县| 舞阳县| 西华县| 桦甸市| 柏乡县| 三门峡市| 永丰县| 无极县| 奉贤区| 镇巴县| 远安县| 加查县| 灵石县| 邵阳市|