UNPKG

mp-colorui

Version:

MP ColorUI 是一款基于 Taro 框架并且联合 Color-UI CSS 库开发的多端 UI 组件库(支持小程序端和H5端)

143 lines (141 loc) 5.25 kB
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: () => {} };