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 < 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
範圍內移動(這裡用節流函數優化了下),直到監聽到滑鼠抬起。在移動的過程中,計算目標元素的相對視覺視窗左側和頂部的距離,將值賦予到 left
和 top
。
這裡的計算move.clientX - down.offsetX, window.innerWidth - this.video.nativeElement.offsetWidth
,相關的概念也許你不是很清楚,不過沒關係,上面的內容,理解思路即可。相關的知識點會在接下來的文章中介紹。
最後,我們得到的效果如下
【完】
更多程式相關知識,請造訪:程式設計影片! !
以上是淺析Angular+rxjs怎麼實現拖曳功能?的詳細內容。更多資訊請關注PHP中文網其他相關文章!