taro-ui-vue3
Version:
Taro UI Rewritten in Vue 3.0
211 lines (210 loc) • 5.9 kB
JavaScript
import {
h,
defineComponent,
reactive,
onMounted,
computed,
ref,
mergeProps
} from "vue";
import Taro from "@tarojs/taro";
import {Text, View} from "@tarojs/components";
const AtNoticebar = defineComponent({
name: "AtNoticebar",
props: {
close: Boolean,
single: Boolean,
marquee: Boolean,
showMore: Boolean,
speed: {
type: Number,
default: 100
},
moreText: {
type: String,
default: "\u67E5\u770B\u8BE6\u60C5"
},
icon: String,
onClose: Function,
onGotoMore: Function
},
setup(props, {attrs, slots}) {
const env = Taro.getEnv();
const timeout = ref(null);
const interval = ref(null);
const state = reactive({
dura: 15,
show: true,
_close: props.marquee ? false : props.close,
_showMore: !props.single ? false : props.showMore,
animElemId: `J_${Math.ceil(Math.random() * 1e6).toString(36)}`,
animationData: {actions: [{}]},
isWEB: env === Taro.ENV_TYPE.WEB
});
const rootClasses = computed(() => ({
"at-noticebar": true,
"at-noticebar--marquee": props.marquee,
"at-noticebar--weapp": props.marquee && !state.isWEB,
"at-noticebar--single": !props.marquee && props.single
}));
const animationStyle = computed(() => {
const style = {};
if (props.marquee) {
style["animation-duration"] = `${state.dura}s`;
}
return style;
});
const innerContentClasses = computed(() => ({
"at-noticebar__content-inner": true,
[`${state.animElemId}`]: props.marquee
}));
const iconClasses = computed(() => ({
"at-icon": true,
[`at-icon-${props.icon}`]: Boolean(props.icon)
}));
function handleClose(event) {
var _a;
state.show = false;
(_a = props.onClose) == null ? void 0 : _a.call(props, event);
}
function onGotoMore(event) {
var _a;
(_a = props.onGotoMore) == null ? void 0 : _a.call(props, event);
}
function initWebAnimation() {
const elem = document.querySelector(`.${state.animElemId}`);
if (!elem)
return;
const width = elem.getBoundingClientRect().width;
state.dura = width / +props.speed;
}
function initMiniAppAnimation() {
const query = Taro.createSelectorQuery();
query.select(`.${state.animElemId}`).boundingClientRect().exec((res) => {
const queryRes = res[0];
if (!queryRes)
return;
const {width} = queryRes;
const dura = width / +props.speed;
const animation = Taro.createAnimation({
duration: dura * 1e3
});
const resetAnimation = Taro.createAnimation({
duration: 0
});
const resetOpacityAnimation = Taro.createAnimation({
duration: 0
});
const animBody = () => {
resetOpacityAnimation.opacity(0).step();
state.animationData = resetOpacityAnimation.export();
setTimeout(() => {
resetAnimation.translateX(0).step();
state.animationData = resetAnimation.export();
}, 300);
setTimeout(() => {
resetOpacityAnimation.opacity(1).step();
state.animationData = resetOpacityAnimation.export();
}, 600);
setTimeout(() => {
animation.translateX(-width).step();
state.animationData = animation.export();
}, 900);
};
animBody();
interval.value = setInterval(animBody, dura * 1e3 + 1e3);
});
}
function initAnimation() {
timeout.value = setTimeout(() => {
timeout.value = null;
if (state.isWEB)
initWebAnimation();
else
initMiniAppAnimation();
}, 100);
}
onMounted(() => {
if (!props.marquee)
return;
initAnimation();
});
return () => {
if (!state.show)
return null;
const closeIconVNode = h(View, {
class: "at-noticebar__close",
onTap: handleClose
}, {
default: () => [
h(Text, {
class: "at-icon at-icon-close"
})
]
});
const contentIconVnode = h(View, {
class: "at-noticebar__content-icon"
}, {
default: () => [
h(Text, {
class: iconClasses.value
})
]
});
const showMoreContentVnode = h(View, {
class: "at-noticebar__more",
onTap: onGotoMore.bind(this)
}, {
default: () => [
h(Text, {
class: "text"
}, {default: () => props.moreText}),
h(View, {
class: "at-noticebar__more-icon"
}, {
default: () => [
h(Text, {
class: "at-icon at-icon-chevron-right"
})
]
})
]
});
const defaultSlotVnode = h(View, {
id: state.animElemId,
animation: state.animationData,
class: innerContentClasses.value,
style: animationStyle.value
}, {default: () => {
var _a;
return (_a = slots.default) == null ? void 0 : _a.call(slots);
}});
return h(View, mergeProps(attrs, {
class: rootClasses.value
}), {
default: () => [
state._close && closeIconVNode,
h(View, {
class: "at-noticebar__content"
}, {
default: () => [
props.icon && contentIconVnode,
h(View, {
class: "at-noticebar__content-text"
}, {
default: () => [
defaultSlotVnode,
state._showMore && showMoreContentVnode
]
})
]
})
]
});
};
}
});
var noticebar_default = AtNoticebar;
export {
noticebar_default as default
};