mp-colorui
Version:
MP ColorUI 是一款基于 Taro 框架并且联合 Color-UI CSS 库开发的多端 UI 组件库(支持小程序端和H5端)
160 lines (158 loc) • 6.11 kB
JavaScript
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: () => {}
};