UNPKG

mp-colorui

Version:

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

160 lines (158 loc) 6.11 kB
import Nerv from "nervjs"; import Taro, { createSelectorQuery as _createSelectorQuery } from "@tarojs/taro-h5"; import { View } from "@tarojs/components"; import "./index.scss"; import { BG_COLOR_LIST } from "../../lib/model"; import { classNames, generateId, isH5, screenPercent } from "../../lib/index"; import ClLayout from "../layout/index"; export default class ClSwiperAction extends Taro.Component { render() { const props = this.props; const [initOptions, setInitOptions] = Taro.useState(props.options || []); const [contentId, setContentId] = Taro.useState(generateId()); const [actionWidth, setActionWidth] = Taro.useState(); const [lastPoint, setLastPoint] = Taro.useState(0); const [translateX, setTranslateX] = Taro.useState(0); const [lastTranslateX, setLastTranslateX] = Taro.useState(0); const [showAnimation, setShowAnimation] = Taro.useState(0); const [beforeMove, setBeforeMove] = Taro.useState(0); const [show, setShow] = Taro.useState(false); const [init, setInit] = Taro.useState(false); Taro.useEffect(() => { const list = props.options || []; const newOprions = list.map(item => { item.cu_index_id = generateId(); return item; }); setInitOptions(newOprions); if (isH5) { const query = document.querySelector(`#${contentId}`); if (query) { const width = query.clientWidth; setActionWidth(width); } } else { const query = _createSelectorQuery().in(this.$scope); this.componentDidMount = () => { setTimeout(() => { const view = query.select("#contentId"); try { view.boundingClientRect().exec(rect => { const res = rect[0]; const width = res.width; setActionWidth(width); setInit(true); }); } catch (e) { throw e; } }, 500); }; } }, [props.options]); const actionsComponent = initOptions.map((item, index) => <View className={`${BG_COLOR_LIST[item.bgColor || "white"]} flex justify-center align-center cl-swiper-action__action__item`} style={{ height: "100%" }} key={item.cu_index_id} onClick={() => { props.onClick && props.onClick(index); if (props.autoClose) setTranslateX(0); }}> <ClLayout padding="small" paddingDirection="horizontal"> {item.text} </ClLayout> </View>); Taro.useEffect(() => { setShow(false); if (translateX === 0) { setShow(false); props.onClose && props.onClose(); } else if (Math.abs(translateX) === actionWidth) { setTimeout(() => { setShow(true); }, 300); props.onOpened && props.onOpened(); } }, [translateX]); Taro.useEffect(() => { setShow(!!props.show); if (props.show) { if (props.direction === "left") { setTranslateX(actionWidth); } else { setTranslateX(-actionWidth); } } }, [props.show, actionWidth]); return <View className={classNames("cl-swiper-action", props.className)} style={Object.assign({}, props.style)} onClick={e => { e.stopPropagation(); }} onTouchStart={e => { if (props.disabled) return; setLastPoint(e.touches[0].clientX); setBeforeMove(e.touches[0].clientX); setLastTranslateX(translateX); setShowAnimation(0); }} onTouchMove={e => { if (props.disabled) return; const nowPoint = e.touches[0].clientX; // 为正则右,为负则左 let distance = nowPoint - lastPoint; if (props.direction === "right") { distance = Math.abs(lastTranslateX) === actionWidth ? distance < 0 ? 0 : distance : lastTranslateX === 0 ? distance > 0 ? 0 : distance : distance; } if (props.direction === "left") { distance = Math.abs(lastTranslateX) === actionWidth ? distance > 0 ? 0 : distance : lastTranslateX === 0 ? distance < 0 ? 0 : distance : distance; } setTranslateX(lastTranslateX + distance * screenPercent); }} onTouchEnd={e => { if (props.disabled) return; setShowAnimation(0.3); const touches = e.changedTouches[0]; const nowClientX = touches.clientX; const move = beforeMove - nowClientX; const isRight = props.direction === "right"; // 向左滑动一定距离 if (move > 20) { setTranslateX(isRight ? -actionWidth : 0); setLastTranslateX(isRight ? -actionWidth : 0); // 向右滑动一定距离 } else if (move < -20) { setTranslateX(isRight ? 0 : actionWidth); setLastTranslateX(isRight ? 0 : actionWidth); } else { setLastTranslateX(lastTranslateX); setTranslateX(lastTranslateX); } }}> <View style={{ transform: `translateX(${Taro.pxTransform(translateX / screenPercent)})`, transition: `all 0.3s ease-in`, position: "relative" }}> {this.props.children} {isH5 ? <View className="cl-swiper-action__action" id={contentId} style={{ right: `${props.direction === "right" ? Taro.pxTransform(-actionWidth / screenPercent) : "auto"}`, left: `${props.direction === "left" ? Taro.pxTransform(-actionWidth / screenPercent) : "auto"}`, zIndex: init ? 1 : -1 }}> {actionsComponent} </View> : <View className="cl-swiper-action__action" id="contentId" style={{ right: `${props.direction === "right" ? Taro.pxTransform(-actionWidth / screenPercent) : "auto"}`, left: `${props.direction === "left" ? Taro.pxTransform(-actionWidth / screenPercent) : "auto"}`, zIndex: init ? 1 : -1 }}> {actionsComponent} </View>} </View> </View>; } } ClSwiperAction.options = { addGlobalClass: true }; ClSwiperAction.defaultProps = { show: false, disabled: false, autoClose: false, options: [], direction: "right", onClick: () => {}, onClose: () => {}, onOpened: () => {} };