/

手写一个简洁且高性能的轮播图组件

如何用最低的性能,运行一个轮播图呢? js控制position:absolute 或者transform:translate,之前也这样写过。

不过有一次看过一个文章,不用js就可以写一个轮播图,原理是利用锚点控制滚动+css属性 -webkit-overflow-scrolling: touch;scroll-snap-align: start,这样的思路真的很厉害,简单方便,性能也很高。

但是在自己的项目中却无法使用,因为用到了锚点,angular会把他当作路由,导航到404页面。

于是我想改动一下,利用js来控制滚动。这样也简单很多,不用再使用插件了。 直接剪贴代码啦,有兴趣的可以参照一下

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="slide-nav"> <button class="prev btn" (click)="scrollPage($event, 'l')"><span nz-icon [nzType]="btnType[xy][0]" nzTheme="outline"></span></button> <button class="next btn" (click)="scrollPage($event, 'r')"><span nz-icon [nzType]="btnType[xy][1]" nzTheme="outline"></span></button> </div> <div class="slides" [style]="style[xy]"> <div class="slide-item" [style]="itemStyle[xy]"> 1 </div> <div class="slide-item" [style]="itemStyle[xy]"> 2 </div> <div class="slide-item" [style]="itemStyle[xy]"> 3 </div> <div class="slide-item" [style]="itemStyle[xy]"> 4 </div> <div class="slide-item" [style]="itemStyle[xy]"> 5 </div> </div>

css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
:host { width: 100%; height: 100%; display: block; overflow: hidden; position: relative; .slides { width: 100%; height: 100%; display: flex; // overflow-x: auto; // flex-direction: column; // scroll-snap-type: x mandatory; scroll-behavior: smooth; -webkit-overflow-scrolling: touch; // scroll-snap-points-x: repeat(300px); // scroll-snap-type: mandatory; .slide-item { scroll-snap-align: start; flex-shrink: 0; width: 100%; height: 100%; // margin-right: 16px; border-radius: 10px; background: #eee; } } .slide-nav{ position: absolute; right: 1em; top: 1em; .btn{ width: 2em; height: 2em; background-color: rgba(0, 0, 0, 0.2); cursor: pointer; border: 0; margin-left: 0.25em; color: rgba(255,255,255,.7); border-radius: .25em; } } }

js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
export class CarouselComponent implements OnInit { ops={ y:{ wh: 'height', scroll: 'scrollTop', xy: 'top' }, x: { wh: 'width', scroll: 'scrollLeft', xy: 'left' } } style={ x: { flexDirection: 'row', scrollSnapType: 'x mandatory', overflowX: 'auto' }, y: { flexDirection: 'column', scrollSnapType: 'y mandatory', overflowY: 'auto' } } btnType={ y:['up', 'down'], x:['left', 'right'], } itemStyle={ x:{ marginRight: '16px' }, y:{ marginBottom: '16px' } } @Input() xy:'x'|'y' = 'y' constructor() { } ngOnInit(): void { } scrollPage(ev:any,direction:'l'|'r'|'b'|'t', op = this.ops[this.xy]){ let e = ev.target while(e && e.nodeName!=='BUTTON'){ e=e.parentNode } let sildesDom = e.parentNode.nextElementSibling let sChildren = sildesDom.children let scrollTop = sildesDom[op.scroll] let index = 0 let sum = 0 for(let i=0,len = sChildren.length; i<len; i++){ let rect = sChildren[i].getBoundingClientRect() if(scrollTop<=sum){ index = i break }else{ sum += rect[op.wh]+16 } } if(index+1==sChildren.length){ sum=0 }else{ if(direction=='r'||direction=='b'){ let rect = sChildren[index+1].getBoundingClientRect() sum += rect[op.wh]+16 }else if(index!==0){ let rect = sChildren[index-1].getBoundingClientRect() sum-=rect[op.wh]+16 } } sildesDom.scroll({ [op.xy]: sum, }) } }

通过scrollTop来判断当前在第几屏,xy传参判断横向滚动还是纵向滚动。
参考文章:CSS-Only Carousel

作者:liuk123标签:js分类:javascript

本文是原创文章,采用 CC BY-NC-ND 4.0 协议, 完整转载请注明来自 liuk123