react 项目下
目标描述:多个图片排列下来,按右边的小按钮,抵达相应位置,鼠标滑动,抵达下一图,或者上一图
知识点:onmousewheel,addEventListener,scrollTo,setTimeout
过程:
1.body 宽,高钉死,100vw,100vh,overflow:hidden 使得不出现滚动条,不然不好看
2.图片放进去,排起来,(注意:默认空隙的处理,可以使用flex布局,空隙就不见了)
3.制作相对于视窗的按钮,几张图片就几个按钮,(position: fixed;计算一下高度,可以利用calc计算top使得上下居中)
4.美化一下,css写写
5.先写简单的按钮事件
handlerGoNext(page) { //传入要走到第几个图
this.num = 10
const vw = document.body.clientWidth < 1000 ? 1000 : document.body.clientWidth //这里按图片比例算出来高度
let nowH = window.pageYOffset //此时距离顶部的高度
this.top = nowH //当前top //给存一下,后面要用到
let h = 675/1200*vw*(page - 1) + 91 //计算总高度,这里我顶部有个导航栏高度是91
if(page === 1) {
h = 0 //第一张就是0啦
}
const faster = (h-nowH)/10 //10次结束,每次需要增加的的距离,
this.handlerGo(faster) //去走动画效果啦
this.setState({
now: page //把当前的位置存一下
})
}
handlerGo(faster) {
this.timer && clearTimeout(this.timer) //注意clearTimeout
if(this.num > 0) { //当次数没走完的时候
this.num = this.num - 1
this.top = this.top + faster //每次改变top
window.scrollTo(0,this.top) //滚动到需要到位置
this.timer = setTimeout(() => {
this.handlerGo(faster)//这里循环
},50)//每次滚动的时间,这里可以试着变长,500左右,你可以清除看到你动画的慢动作
}else {//10次结束,要重新变成10,然后允许下一次动画
this.num = 10
this.timer = setTimeout(() => {
this.ing = false //这里是控制动画的,为了限制滑动后的触发次数
},500) //这里给点时间间隔,不然容易跨页,滑动有惯性
}
}
6.写监听滑动事件(onmousewheel在火狐无效,DOMMouseScroll只在火狐有效)
react在componentDidMount的时候监听
document.body.onmousewheel = (e) => {
if(e.wheelDelta < 0 && this.state.now < 5 && !this.ing) { //向下滑动,没有到底,没有正在执行的滑动效果
this.timer && clearTimeout(this.timer)
this.timer = setTimeout(() => {
!this.ing && this.handlerGoNext(this.state.now+1)
this.ing = true
}, 30);
}else if(e.wheelDelta > 0 && this.state.now > 1 && !this.ing){//向上滑动,没有到顶
this.timer && clearTimeout(this.timer)
this.timer = setTimeout(() => {
!this.ing && this.handlerGoNext(this.state.now-1)
this.ing = true
}, 30);
}else if (e.wheelDelta < 0 && this.state.now === 5 && !this.ing) {
//向下滑动,刚好最后一个动画的时候,这里是因为我的页面有个底部,滑动到最后一个图片还不够全部展示,这里单独走一次动画,使得滑动到最底下。
this.timer && clearTimeout(this.timer)
this.timer = setTimeout(() => {
!this.ing && this.handlerGo(10) //这里我根据自己的页面做了简单的计算保证速度10可以到底
this.ing = true
}, 30);
}
}
7.补充写一下火狐的
componentDidMount() {
getData({type:1, no:1},(data) => {
this.setState({
dataA: data.list.result[0]
})
})
getData({type:2, no:1},(data) => {
this.setState({
dataB: data.list.result[0]
})
})
if(window.navigator.userAgent.indexOf('Firefox') > -1) {
document.addEventListener('DOMMouseScroll',(e) => {
this.handleMove( 0 - e.detail)
},false)
}else {
document.body.onmousewheel = (e) => {
this.handleMove(e.wheelDelta)
}
}
}
handleMove(type) { //用type表示上下
if(type < 0 && this.state.now < 5 && !this.ing) { //向下滑动,没有到底,没有正在执行的滑动效果
this.timer && clearTimeout(this.timer)
this.timer = setTimeout(() => {
!this.ing && this.handlerGoNext(this.state.now+1)
this.ing = true
}, 30);
}else if(type > 0 && this.state.now > 1 && !this.ing){
this.timer && clearTimeout(this.timer)
this.timer = setTimeout(() => {
!this.ing && this.handlerGoNext(this.state.now-1)
this.ing = true
}, 30);
}else if (type < 0 && this.state.now === 5 && !this.ing) {
this.timer && clearTimeout(this.timer)
this.timer = setTimeout(() => {
!this.ing && this.handlerGo(10)
this.ing = true
}, 30);
}
}
- 页面卸载,取消绑定
if(window.navigator.userAgent.indexOf('Firefox') > -1) {
document.addEventListener('DOMMouseScroll',this.handlerGet,false) //这里为了取消他,需要用这样的函数替代
}else {
document.body.onmousewheel = (e) => {
this.handleMove(e.wheelDelta)
}
}
handlerGet = (e) => { //过渡一下
this.handleMove( 0 - e.detail)
}
componentWillUnmount() { //清除监听事件
this.timer && clearTimeout(this.timer)
if(window.navigator.userAgent.indexOf('Firefox') > -1) {
document.removeEventListener('DOMMouseScroll',this.handlerGet,false)
}else {
document.body.onmousewheel = false
}
}
9.测试检查一下。
完成啦,啦啦啦~
我的截图:
成果
缺点:这里我是一直对页面进行监听,导致滑动过快对时候动画效果开始执行对时间延后。体现为滑动对轻,整个就流畅一点。
ps:写这种带计算带页面,我觉得是考验思维的,你可以对这里的知识点不熟练,但是你必须得能理解每一步的加加减减。
网友评论