如何用最低的性能,运行一个轮播图呢? 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