feat(Tab): add swipe animation #1174
This commit is contained in:
+36
-42
@@ -1,14 +1,16 @@
|
||||
import { ref, watch } from 'vue';
|
||||
import { createNamespace } from '../utils';
|
||||
import { useTouch } from '../composition/use-touch';
|
||||
import Swipe from '../swipe';
|
||||
|
||||
const [createComponent, bem] = createNamespace('tabs');
|
||||
const MIN_SWIPE_DISTANCE = 50;
|
||||
|
||||
export default createComponent({
|
||||
props: {
|
||||
inited: Boolean,
|
||||
duration: [Number, String],
|
||||
animated: Boolean,
|
||||
swipeable: Boolean,
|
||||
lazyRender: Boolean,
|
||||
count: {
|
||||
type: Number,
|
||||
required: true,
|
||||
@@ -22,60 +24,52 @@ export default createComponent({
|
||||
emits: ['change'],
|
||||
|
||||
setup(props, { emit, slots }) {
|
||||
const touch = useTouch();
|
||||
const swipeRef = ref();
|
||||
|
||||
const onTouchEnd = () => {
|
||||
const { deltaX, offsetX } = touch;
|
||||
const { currentIndex } = props;
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (touch.isHorizontal() && offsetX.value >= MIN_SWIPE_DISTANCE) {
|
||||
/* istanbul ignore else */
|
||||
if (deltaX.value > 0 && currentIndex !== 0) {
|
||||
emit('change', currentIndex - 1);
|
||||
} else if (deltaX.value < 0 && currentIndex !== props.count - 1) {
|
||||
emit('change', currentIndex + 1);
|
||||
}
|
||||
}
|
||||
const onChange = (index: number) => {
|
||||
emit('change', index);
|
||||
};
|
||||
|
||||
const renderChildren = () => {
|
||||
const Content = slots.default?.();
|
||||
|
||||
if (props.animated) {
|
||||
const style = {
|
||||
transform: `translate3d(${-1 * props.currentIndex * 100}%, 0, 0)`,
|
||||
transitionDuration: `${props.duration}s`,
|
||||
};
|
||||
|
||||
if (props.animated || props.swipeable) {
|
||||
return (
|
||||
<div class={bem('track')} style={style}>
|
||||
<Swipe
|
||||
ref={swipeRef}
|
||||
loop={false}
|
||||
class={bem('track')}
|
||||
touchable={props.swipeable}
|
||||
lazyRender={props.lazyRender}
|
||||
showIndicators={false}
|
||||
onChange={onChange}
|
||||
>
|
||||
{Content}
|
||||
</div>
|
||||
</Swipe>
|
||||
);
|
||||
}
|
||||
|
||||
return Content;
|
||||
};
|
||||
|
||||
return () => {
|
||||
const listeners = props.swipeable
|
||||
? {
|
||||
onTouchstart: touch.start,
|
||||
onTouchmove: touch.move,
|
||||
onTouchend: onTouchEnd,
|
||||
onTouchcancel: onTouchEnd,
|
||||
}
|
||||
: null;
|
||||
watch(
|
||||
() => props.currentIndex,
|
||||
(index) => {
|
||||
const swipe = swipeRef.value;
|
||||
if (swipe && swipe.state.active !== index) {
|
||||
swipe.swipeTo(index, { immediate: !props.inited });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
class={bem('content', { animated: props.animated })}
|
||||
{...listeners}
|
||||
>
|
||||
{renderChildren()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
return () => (
|
||||
<div
|
||||
class={bem('content', {
|
||||
animated: props.animated || props.swipeable,
|
||||
})}
|
||||
>
|
||||
{renderChildren()}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
+5
-3
@@ -91,7 +91,6 @@ export default createComponent({
|
||||
emits: ['click', 'change', 'scroll', 'disabled', 'rendered', 'update:active'],
|
||||
|
||||
setup(props, { emit, slots }) {
|
||||
let inited;
|
||||
let tabHeight;
|
||||
let lockScroll;
|
||||
let stickyFixed;
|
||||
@@ -106,6 +105,7 @@ export default createComponent({
|
||||
const { children, linkChildren } = useChildren(TABS_KEY);
|
||||
|
||||
const state = reactive({
|
||||
inited: false,
|
||||
position: '',
|
||||
currentIndex: -1,
|
||||
lineStyle: {
|
||||
@@ -159,7 +159,7 @@ export default createComponent({
|
||||
|
||||
const init = () => {
|
||||
nextTick(() => {
|
||||
inited = true;
|
||||
state.inited = true;
|
||||
tabHeight = getVisibleHeight(wrapRef.value);
|
||||
scrollIntoView(true);
|
||||
});
|
||||
@@ -167,7 +167,7 @@ export default createComponent({
|
||||
|
||||
// update nav bar style
|
||||
const setLine = () => {
|
||||
const shouldAnimate = inited;
|
||||
const shouldAnimate = state.inited;
|
||||
|
||||
nextTick(() => {
|
||||
const titles = titleRefs.value;
|
||||
@@ -436,9 +436,11 @@ export default createComponent({
|
||||
)}
|
||||
<TabsContent
|
||||
count={children.length}
|
||||
inited={state.inited}
|
||||
animated={props.animated}
|
||||
duration={props.duration}
|
||||
swipeable={props.swipeable}
|
||||
lazyRender={props.lazyRender}
|
||||
currentIndex={state.currentIndex}
|
||||
onChange={setCurrentIndex}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user