這篇文章主要介紹“Angular+rxjs如何實(shí)現(xiàn)拖拽功能”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“Angular+rxjs如何實(shí)現(xiàn)拖拽功能”文章能幫助大家解決問(wèn)題。
成都創(chuàng)新互聯(lián)公司是一家朝氣蓬勃的網(wǎng)站建設(shè)公司。公司專(zhuān)注于為企業(yè)提供信息化建設(shè)解決方案。從事網(wǎng)站開(kāi)發(fā),網(wǎng)站制作,網(wǎng)站設(shè)計(jì),網(wǎng)站模板,微信公眾號(hào)開(kāi)發(fā),軟件開(kāi)發(fā),微信小程序,10年建站對(duì)成都服務(wù)器租用等多個(gè)方面,擁有豐富的網(wǎng)站維護(hù)經(jīng)驗(yàn)。
頁(yè)面中 video 標(biāo)簽,當(dāng)滾動(dòng)高度超過(guò)其位置之后,將其設(shè)置為可在可視區(qū)域自由拖拽。
一個(gè)不錯(cuò)的 Idea
,如果你使用 Angular
的 @angular/cdk/drag-drop
可以輕松實(shí)現(xiàn),但是我們這里不使用工具。
好吧,我們來(lái)分析下實(shí)現(xiàn)的思路:
頁(yè)面滾動(dòng)高度大于視頻所在的位置:那么就是視頻的 bottom
值相對(duì)可視窗口的值要小于0,我們需要設(shè)定一個(gè)包裹 video
標(biāo)簽的 div
方便計(jì)算,其高度是原設(shè)定 video
的高度。即元素脫離原文檔布局
video
元素可以拖拽,那么其定位需要被改變?yōu)?fixed
video
元素在可視區(qū)內(nèi)自由拖動(dòng),那么需要對(duì)其 top
, left
值進(jìn)行限定
所以我們?cè)O(shè)定下面的 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>
有下面這些預(yù)定的樣式:
<!-- 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 布局的樣式,默認(rèn)布局中是沒(méi)有的 --> &.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
來(lái)操作。
元素脫離原文檔布局
剛才已經(jīng)分析了 video
元素脫離文檔的臨界調(diào)節(jié)了:
video的外 div
,即 #anchor
元素的相對(duì)視圖的 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(); } // 頁(yè)面滾動(dòng) 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
元素對(duì)象,監(jiān)聽(tīng)頁(yè)面對(duì)象 document
滾動(dòng)(我們這里加入了防抖函數(shù)優(yōu)化),當(dāng) bottom < 0
的時(shí)候,將相關(guān)的樣式 video-fixed
添加給 video
。
元素拖拽
接下來(lái)就是實(shí)現(xiàn) video
元素的拖拽。這里我們要監(jiān)聽(tīng) video
元素的三個(gè)事件,分別是鼠標(biāo)按下 mousedown
,鼠標(biāo)移動(dòng) mousemove
和鼠標(biāo)抬起 mouseup
。
// demo.component.ts public mouseDown!: any; public mouseUp!: any; public mouseMove!: any; ngAfterViewInit(): void { this.mouseDown = fromEvent(this.video.nativeElement, 'mousedown'); // 目標(biāo)元素按下,即 video this.mouseMove = fromEvent(document, 'mousemove'); // 元素在文檔內(nèi)移動(dòng) this.mouseUp = fromEvent(document, 'mouseup'); // 鼠標(biāo)抬起 this.moveFn() } // 目標(biāo)元素移動(dòng) public moveFn() { this.mouseDown .pipe( filter(() => this.video.nativeElement.classList.contains('video-fixed')), map(() => this.mouseMove.pipe( throttleTime(50), // 節(jié)流 takeUntil(this.mouseUp) )), // concatAll 順序接受上游拋出的各個(gè)數(shù)據(jù)流作為它的數(shù)據(jù), 若前面的數(shù)據(jù)流不能同步的完結(jié),它會(huì)暫存后續(xù)數(shù)據(jù)流,當(dāng)前數(shù)據(jù)流完成后它才會(huì)訂閱后一個(gè)暫存的數(shù)據(jù)流 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'; }) } // 校驗(yàn)邊界值 public validValue = (value:number, max:number, min: number) => { return Math.min(Math.max(value, min), max) }
我們監(jiān)聽(tīng)目標(biāo)元素(filter 函數(shù))被鼠標(biāo)按下,然后鼠標(biāo)可以在 document
范圍內(nèi)移動(dòng)(這里用節(jié)流函數(shù)優(yōu)化了下),直到監(jiān)聽(tīng)到鼠標(biāo)抬起。在移動(dòng)的過(guò)程中,計(jì)算目標(biāo)元素的相對(duì)可視窗口左側(cè)和頂部的距離,將值賦予到 left
和 top
。
這里的計(jì)算 move.clientX - down.offsetX, window.innerWidth - this.video.nativeElement.offsetWidth
,相關(guān)的概念也許你不是很清楚,不過(guò)沒(méi)關(guān)系,上面的內(nèi)容,理解思路即可。
關(guān)于“Angular+rxjs如何實(shí)現(xiàn)拖拽功能”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。
當(dāng)前題目:Angular+rxjs如何實(shí)現(xiàn)拖拽功能
當(dāng)前鏈接:http://jinyejixie.com/article0/jjgcoo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標(biāo)簽優(yōu)化、品牌網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、網(wǎng)站內(nèi)鏈、網(wǎng)站設(shè)計(jì)公司、關(guān)鍵詞優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)