mp-colorui
Version:
MP ColorUI 是一款基于 Taro 框架并且联合 Color-UI CSS 库开发的多端 UI 组件库(支持小程序端和H5端)
143 lines (141 loc) • 5.25 kB
JavaScript
import Nerv from "nervjs";
import Taro, { createSelectorQuery as _createSelectorQuery } from "@tarojs/taro-h5";
import { View, Text } from "@tarojs/components";
import ClText from "../text/index";
import ClIcon from "../icon/index";
import ClFlex from "../flex/index";
import { BG_COLOR_LIST } from "../../lib/model";
import { generateId, isH5, screenPercent } from "../../lib/index";
import classnames from "classnames";
import ClLayout from "../layout/index";
import "../text/index.scss";
import "./index.scss";
export default class ClNoticeBar extends Taro.Component {
render() {
const props = this.props;
const { text, bgColor, single, marquee, speed, showMore, moreText, icon, close, onClose, onMore } = props;
const [singleContentWidth, setSingleContentWidth] = Taro.useState("100%");
const [contentWidth, setContentWidth] = Taro.useState(0);
const [marqueeSpeed, setMarqueeSpeed] = Taro.useState(speed);
const [textId] = Taro.useState(generateId());
const [contentId] = Taro.useState(generateId());
const [marqueeClass, setMarqueeClass] = Taro.useState(single && marquee);
const [show, setShow] = Taro.useState(true);
const cut = single && !marquee;
Taro.useEffect(() => {
setMarqueeClass(single && marquee);
if (single) {
let width = 180;
if (!showMore) width = 50;
if (close) width += 50;
setSingleContentWidth(`calc(100vw - ${Taro.pxTransform(width)})`);
}
const query = _createSelectorQuery().in(this.$scope);
const promise = new Promise(resolve => {
query.select(isH5 ? contentId : "#contentId").boundingClientRect(content => {
resolve(content);
}).exec();
});
promise.then(content => {
query.select(isH5 ? textId : "#textId").boundingClientRect(res => {
if (res.width < content.width) {
setMarqueeClass(false);
setMarqueeSpeed(0);
return;
}
setContentWidth(-res.width);
function beginInterval(time) {
let timer;
timer = setInterval(() => {
setContentWidth(res.width);
setMarqueeSpeed(0);
clearInterval(timer);
let timeout;
timeout = setTimeout(() => {
setContentWidth(-res.width);
const percentSpeed = res.width / speed;
const speedNow = speed + content.width / percentSpeed;
setMarqueeSpeed(speedNow);
beginInterval(speedNow);
clearTimeout(timeout);
}, 50);
}, time * 1000);
}
beginInterval(marqueeSpeed);
}).exec();
});
}, [props.showMore, props.single, props.speed]);
const showMoreComponent = showMore ? <View style={{
flex: "0 0 auto",
zIndex: 1,
paddingRight: Taro.pxTransform(10),
paddingLeft: Taro.pxTransform(10)
}} onClick={() => {
onMore && onMore();
}}>
<ClFlex align={"center"}>
<ClText text={moreText} textColor={"gray"} size={"small"} />
<ClIcon iconName={"right"} color={"gray"} size={24} />
</ClFlex>
</View> : "";
const showCloseComponent = close ? <View onClick={() => {
setShow(false);
onClose && onClose();
}}>
<ClIcon iconName={"close"} size={24} color={"gray"} />
</View> : "";
return <View className={classnames("cu-notice", `${BG_COLOR_LIST[bgColor || "yellow"]}`)}>
{show ? <ClFlex align={"center"} justify={"between"} style={{ minHeight: Taro.pxTransform(40) }}>
<ClLayout margin="xsmall" marginDirection="right" style={{ zIndex: 10, flex: "0 0 auto" }}>
<View>
<ClLayout padding="xsmall" paddingDirection="horizontal">
<ClFlex>
{showCloseComponent}
<ClIcon iconName={icon || "notificationfill"} size={24} />
</ClFlex>
</ClLayout>
</View>
</ClLayout>
<View id={isH5 ? contentId : "contentId"} style={{
flex: "1 1 auto",
overflow: "hidden",
minHeight: Taro.pxTransform(40)
}}>
<View className={classnames(["text-sm", {
"text-cut": cut
}])} style={{
lineHeight: Taro.pxTransform(42),
transition: `all ${marqueeClass ? marqueeSpeed : 0}s linear`,
transform: `translateX(${marqueeClass ? Taro.pxTransform(contentWidth / screenPercent) : 0})`,
whiteSpace: "nowrap",
width: singleContentWidth
}}>
<Text id={isH5 ? textId : "textId"} className={classnames([{
"cl-text__nowrap": single,
"cl-text__wrap": !single
}])}>
{text}
</Text>
</View>
</View>
{showMoreComponent}
</ClFlex> : ""}
</View>;
}
}
ClNoticeBar.options = {
addGlobalClass: true
};
ClNoticeBar.defaultProps = {
text: "",
bgColor: "light-yellow",
single: false,
marquee: false,
speed: 5,
showMore: false,
moreText: "查看详情",
icon: "notificationfill",
close: false,
onClose: () => {},
onMore: () => {}
};