Home > Article > Web Front-end > A brief analysis of how Angular+rxjs implements drag-and-drop function?
How to implement drag-and-drop function in Angular rxjs? The following article will introduce to you how Angular combines rxjs to implement drag and drop. I hope it will be helpful to you!
In the previous article, we learned about custom Video operations in Angular. Readers who have not experienced it can learn about it first.
Now that there is such a demand, how will you realize it?
In the video tag on the page, when the scroll height exceeds its position, set it so that it can be freely dragged in the visible area.
A nice Idea
, if you use Angular
's @angular/cdk/drag-drop
it can be easily achieved, but We don't use tools here. [Related tutorial recommendations: "angular tutorial"]
Okay, let's analyze the implementation ideas:
bottom
value of the video must be less than 0 relative to the value of the visual window. We need to set a div
that wraps the video
tag to facilitate calculation, and its height It is the original height of video
. That is, the element is out of the original document layout video
The element can be dragged and dropped, then its positioning needs to be changed to fixed
video
If the element is freely dragged within the visual area, its top
, left
values need to be limited so we set the following demo
Layout:
<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>
has the following predetermined styles:
<!-- 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
is also introduced here for operation.
The element is out of the original document layout
We have just analyzed the critical adjustment of the video
element out of the document:## The outer
of #video, that is, the
bottom of the relative view of the #anchor element. So we have:
@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'); } }) }
##First get the
anchor element object and monitor the scrolling of the page object document
(we have added anti-shake here Function optimization), when bottom , add the related style <code>video-fixed
to video
.
Element draggingThe next step is to realize the dragging of the
video element. Here we want to listen to three events of the video
element, namely mouse downmousedown
, mouse movementmousemove
and mouse upmouseup
. <pre class="brush:js;toolbar:false;">// 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)
}</pre>
We listen to the target element (filter function) being pressed by the mouse, and then the mouse can move within the
range (here is optimized with the throttling function) until the mouse is raised. rise. During the movement, the distance to the left and top of the relative visual window of the target element is calculated, and the values are assigned to left
and top
. Calculation here
, you may not be very clear about the related concepts, but it doesn’t matter, the above content , just understand the idea. Relevant knowledge points will be introduced in the following articles. Finally, the effect we got is as follows
[End]
For more programming-related knowledge, please visit:
Programming videoThe above is the detailed content of A brief analysis of how Angular+rxjs implements drag-and-drop function?. For more information, please follow other related articles on the PHP Chinese website!