Skip to content

Commit

Permalink
feat(tabs): 增加动画,手势滑动
Browse files Browse the repository at this point in the history
  • Loading branch information
jimczj committed Aug 8, 2018
1 parent 4820c6b commit 1c4fc7e
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 21 deletions.
67 changes: 60 additions & 7 deletions src/components/tabs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,101 @@ import './index.scss'
* @author:chenzeji
* @description tabs 标签页
* @prop current {Number} 当前选中的tab index值,从0计数,default:0
* @prop color {String} 选中标签的颜色
* @prop scroll {Boolean} 是否横向滚动,default:false
* @prop tabList {Array} tab 列表 eg: [{ title: '标签页1' }, { title: '标签页2' }]
* @prop onClick {Function} 点击时触发事件,回调参数 {value: 1}
*/
class AtTabs extends Taro.Component {
constructor () {
super(...arguments)
// 触摸时的原点
this.touchDot = 0
// 定时器
this.interval = null
// 滑动时间间隔
this.time = 0
// 是否已经在滑动
this.isMoving = false
// 最大索引
this.maxIndex = this.props.tabList.length
}

handleClick (i) {
this.props.onClick(i, ...arguments)
}

handleTouchStart (e) {
if (!this.props.swipeable) return

// 获取触摸时的原点
this.touchDot = e.touches[0].pageX
// 使用js计时器记录时间
this.interval = setInterval(function () {
this.time++
}, 100)
}
handleTouchMove (e) {
if (!this.props.swipeable) return

const { current } = this.props
const touchMove = e.touches[0].pageX
// 向左滑动
if (!this.isMoving && current - 1 >= 0 && touchMove - this.touchDot <= -40 && this.time < 10) {
this.isMoving = true
this.handleClick(current - 1)
}
// 向右滑动
if (!this.isMoving && current + 1 < this.maxIndex && touchMove - this.touchDot >= 40 && this.time < 10) {
this.isMoving = true
this.handleClick(current + 1)
}
}

handleTouchEnd () {
if (!this.props.swipeable) return

clearInterval(this.interval)
this.time = 0
this.isMoving = false
}

render () {
const { tabList, scroll, current, color } = this.props
const { tabList, scroll, current } = this.props
const headerCls = ['at-tabs__header']
const style = `color: ${color};border-bottom: 1px solid ${color};`
if (scroll) {
headerCls.push('at-tabs__header--scroll')
}
const animationStyle = `transform: translate3d(-${current * 100}%, 0px, 0px);`
return <View className='at-tabs'>
<View className={headerCls}>
{
tabList.map((item, i) => <View className='at-tabs__item' style={current === i ? style : ''} key={item} onClick={this.handleClick.bind(this, i)}>
tabList.map((item, i) => <View className={current === i ? 'at-tabs__item at-tabs__item--active' : 'at-tabs__item'} key={item} onClick={this.handleClick.bind(this, i)}>
{item.title}
</View>)
}
</View>
<View className='at-tabs__body' style={animationStyle}>
<View className='at-tabs__body'
id='test'
onTouchStart={this.handleTouchStart.bind(this)}
onTouchEnd={this.handleTouchEnd.bind(this)}
onTouchMove={this.handleTouchMove.bind(this)}
style={animationStyle}
>
{this.props.children}
</View>
</View>
}
}
AtTabs.defaultProps = {
current: 0,
color: '#6190E8',
swipeable: true,
scroll: false,
tabList: [],
onClick: () => { }
}
AtTabs.propTypes = {
current: PropTypes.number,
color: PropTypes.string,
swipeable: PropTypes.bool,
scroll: PropTypes.bool,
tabList: PropTypes.array,
onClick: PropTypes.func
Expand Down
25 changes: 25 additions & 0 deletions src/components/tabs/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,34 @@
@import '../../style/theme/default.scss';

.at-tabs {
overflow: hidden;

&__item {
position: relative;
flex: 1;
font-size: 30px;
padding: 20px;
color: $color-text-base;

&::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 1PX;
background-color: $color-brand;
transform: scaleX(0);
transition: all 0.15s;
}

&--active {
color: $color-brand;

&::after {
transform: scaleX(1);
}
}
}

&__header {
Expand All @@ -19,6 +42,7 @@

&--scroll {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
white-space: nowrap;

.at-tabs__item {
Expand All @@ -32,5 +56,6 @@
font-size: 0;
white-space: nowrap;
transition: all 0.3s;
width: 100%;
}
}
91 changes: 78 additions & 13 deletions src/pages/navigation/tabs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,27 @@ export default class Index extends Taro.Component {
this.state = {
current1: 0,
current2: 0,
current3: 0
current3: 0,
current4: 0
}
}
handleClick (stateName, value) {
this.state[stateName] = value
this.setState()
}
render () {
const { current1, current2, current3 } = this.state
const tabList1 = [{ title: '标签页1' }, { title: '标签页2' }]
const { current1, current2, current3, current4 } = this.state
const tabList1 = [{ title: '标签页1' }, { title: '标签页2' }, { title: '标签页3' }]
const tabList2 = [
{ title: '标签页1' },
{ title: '标签页2' },
{ title: '标签页3' },
{ title: '标签页4' },
{ title: '标签页5' },
{ title: '标签页6' },
{ title: '标签页7' }
{ title: '标签页7' },
{ title: '标签页8' },
{ title: '标签页9' }
]

return (
Expand All @@ -42,31 +45,93 @@ export default class Index extends Taro.Component {
<View className='doc-body'>
{/* 基础用法 */}
<View className='panel'>
<View className='panel__title'>基础用法</View>
<View className='panel__title'>等宽标签栏</View>
<View className='panel__content'>
<AtTabs current={current1} tabList={tabList1} onClick={this.handleClick.bind(this, 'current1')}>
<AtTabs swipeable={false} current={current1} tabList={tabList1} onClick={this.handleClick.bind(this, 'current1')}>
<AtTabsPane>
<View className='tab-content'>标签页一的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页二的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页三的内容</View>
</AtTabsPane>
</AtTabs>
</View>
</View>
<View className='panel'>
<View className='panel__title'>滚动标签栏</View>
<View className='panel__content'>
<AtTabs swipeable={false} scroll current={current2} tabList={tabList2} onClick={this.handleClick.bind(this, 'current2')}>
<AtTabsPane>
<View className='tab-content'>标签页一的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页二的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页三的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页四的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页五的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页六的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页七的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页八的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页九的内容</View>
</AtTabsPane>
</AtTabs>
</View>
</View>
{/* 滚动 */}
<View className='panel'>
<View className='panel__title'>滚动</View>
<View className='panel__title'>滑动切换内容</View>
<View className='panel__content'>
<AtTabs scroll current={current2} tabList={tabList2} onClick={this.handleClick.bind(this, 'current2')} />
<AtTabs current={current3} tabList={tabList1} onClick={this.handleClick.bind(this, 'current3')}>
<AtTabsPane>
<View className='tab-content'>标签页一的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页二的内容</View>
</AtTabsPane>
<AtTabsPane>
<View className='tab-content'>标签页三的内容</View>
</AtTabsPane>
</AtTabs>
</View>
</View>

{/* 自定义颜色 */}
<View className='panel'>
<View className='panel__title'>自定义颜色</View>
<View className='panel__title'>禁止内容切换动画</View>
<View className='panel__content'>
<AtTabs scroll color='#f759ab' current={current3} tabList={tabList2} onClick={this.handleClick.bind(this, 'current3')} />
<AtTabs current={current4} tabList={tabList1} onClick={this.handleClick.bind(this, 'current4')} />
{current4 === 0
? <AtTabsPane>
<View className='tab-content'>标签页一的内容</View>
</AtTabsPane>
: null
}
{current4 === 1
? <AtTabsPane>
<View className='tab-content'>标签页二的内容</View>
</AtTabsPane>
: null
}
{current4 === 2
? <AtTabsPane>
<View className='tab-content'>标签页三的内容</View>
</AtTabsPane>
: null
}
</View>
</View>
</View>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/navigation/tabs/index.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.tab-content {
font-size: 30px;
padding: 20px;
padding: 100px 50px;
text-align: center;
background-color: #f8f8f8;
}

0 comments on commit 1c4fc7e

Please sign in to comment.