前言
由于工作需要,需要做一版在手机上查看的 H5 的广告页。广告页面基本都是一块内容占满一屏,然后上滑下滑就翻页,所以需要一个这样的翻页功能。代码实现
废话不多说,直接上代码/** * 一个放置多个满屏页面的容器,支持上下滑动 */ // ScrollBox.jsx import React, { Component } from 'react'; import './ScrollBox.less'; class ScrollBox extends Component { state = { pageIndex: 0, // 当前在第几屏,从0开始算 } startY = 0; // touch的起始Y坐标 handleTouchMove = (e) => { const y = e.changedTouches[0].clientY; const deltaY = y - this.startY; const height = this.root.offsetHeight; const len = this.props.list.length; const pageIndex = this.state.pageIndex; if(pageIndex === 0 && deltaY > 0) { return; } if(pageIndex === len - 1 && deltaY < 0) { return; } this.scrollBox.style.top = `${-(height * pageIndex - deltaY)}px`; } handleTouchStart = (e) => { this.startY = e.changedTouches[0].clientY; } handleTouchEnd = (e) => { const { list = [] } = this.props; let { pageIndex } = this.state; const y = e.changedTouches[0].clientY; const deltaY = y - this.startY; const len = list.length; if(deltaY > 50) { if(pageIndex > 0) { pageIndex -= 1; } } else if(deltaY < -50) { if(pageIndex < len - 1) { pageIndex += 1; } } this.setState({ pageIndex }, () => { this.anmateFunc(); }) } anmateFunc = () => { const currentStr = this.scrollBox.style.top; let current = 0; if(currentStr) { current = Number(currentStr.slice(0, currentStr.length - 2)); } const height = this.root.offsetHeight; const target = -(height * this.state.pageIndex); const delta = target - current; const part = delta / 20; const moveOnce = (i) => { this.scrollBox.style.top = `${current + (i * part)}px`; if(++i < 21) { ((index) => { setTimeout(() => { moveOnce(index); }, 10); })(i) } } moveOnce(1); } componentDidMount() { this.root = document.getElementById('root'); this.root.addEventListener('touchstart', this.handleTouchStart); this.root.addEventListener('touchend', this.handleTouchEnd); this.root.addEventListener('touchmove', this.handleTouchMove); } componentWillUnmount() { this.root.removeEventListener('touchstart', this.handleTouchStart); this.root.removeEventListener('touchend', this.handleTouchEnd); this.root.removeEventListener('touchmove', this.handleTouchMove); } render() { const { list = [] } = this.props; const { pageIndex } = this.state; return ( <div className="ScrollBox" ref={scrollBox => this.scrollBox = scrollBox} > { list.map((child, index) => { return ( <div className={`page ${pageIndex === index ? 'active' : ''}`} style={{ background: colors[index] }} key={`page-${index}`}> <div style={{ fontSize: '1rem' }} className={`animate ${index % 2 === 0 ? 'animate-slideLeft' : 'animate-slideRight'}`}> { child } </div> </div> ) }) } </div> ) } } const colors = ['red', 'orange', 'yellow', 'green']; export default ScrollBox;
// ScrollBar.less .ScrollBox { position: absolute; top: 0; left: 0; .page { width: 100vw; height: 100vh; } // 当页面滑到可视区域时,可以添加一个active的类,方便做动画的管理,只有当页面出现到可视区域才加上动画效果,否则就不加。因为广告页大多是需要动画效果的 .active { .animate { animation-timing-function: ease-in-out; animation-duration: 0.6s; animation-iteration-count: 1; &-slideLeft { animation-name: slideLeft; } &-slideRight { animation-name: slideRight; } @keyframes slideLeft { 0% { transform: translateX(100%); } 100% { transform: translateX(0); } } @keyframes slideRight { 0% { transform: translateX(-100%); } 100% { transform: translateX(0); } } } } }
// 使用 <ScrollBox list={['page1', 'page2', 'page3', 'page4']} />
小结
先记一下,以后如果有更好的思路再优化,先暂时用着
查看更多关于React编写一个移动H5的纵向翻屏组件的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did222611