mp-colorui
Version:
MP ColorUI 是一款基于 Taro 框架并且联合 Color-UI CSS 库开发的多端 UI 组件库(支持小程序端和H5端)
143 lines (141 loc) • 5.45 kB
JavaScript
import Nerv from "nervjs";
import Taro, { createAnimation as _createAnimation } from "@tarojs/taro-h5";
import { View } from "@tarojs/components";
import utils, { classNames, generateId } from "../../lib/index";
import ClIcon from "../icon/index";
import "./index.scss";
import ClAnimation from "../animation/index";
import ClLayout from "../layout/index";
let tempPageX = 0;
let tempPageY = 0;
let pageX = 25;
let pageY = 100;
export default class ClFloatButton extends Taro.Component {
render() {
const props = this.props;
const [show, setShow] = Taro.useState(false);
const [rotate, setRotate] = Taro.useState(0);
const [animation, setAnimation] = Taro.useState({});
const [actionListState, setActionListState] = Taro.useState(props.actionList);
const { move, open, icon, bgColor, iconColor, direction, shadow, shape, size, actionList, onClick, onActionClick, closeWithShadow } = props;
Taro.useEffect(() => {
const list = actionList || [];
setActionListState(list.map(item => {
item.cu_float_button_id = generateId();
return item;
}));
}, [props.actionList]);
const dealSize = utils.model.SIZE[size || "normal"];
const dealBgColor = utils.model.BG_COLOR_LIST[bgColor || "blue"];
const dealShadow = shadow ? "shadow" : "";
const dealIconColor = iconColor || "";
let dealActionList = actionListState || [];
const len = dealActionList.length;
const type = () => {
if (direction === "vertical") {
return show ? "slide-bottom" : "slide-top";
} else {
return show ? "slide-right" : "slide-left";
}
};
const actionListComponent = dealActionList.map((item, index) => <View key={item.cu_float_button_id} style={{ position: show ? "relative" : "absolute" }}>
<ClAnimation type={type()} delay={show ? (len - index - 1) / 10 : 0} duration={0.2}>
<ClLayout padding="small" paddingDirection={direction === "vertical" ? "bottom" : "right"}>
<View className={`cu-avatar ${shape} ${dealSize} ${item.bgColor ? utils.model.BG_COLOR_LIST[item.bgColor] : dealBgColor} ${dealShadow}`} onClick={e => {
e.stopPropagation();
clickButton();
onActionClick && onActionClick(index);
}}>
<View className={`${item.iconColor || dealIconColor}`}>
<ClIcon iconName={item.icon} size={size} />
</View>
</View>
</ClLayout>
</ClAnimation>
</View>);
const directionClass = direction === "vertical" ? "" : "flex";
const clickButton = () => {
open && setShow(!show);
open && setRotate(rotate ? 0 : 45);
};
const position = props.position || {
top: "auto",
right: 50,
bottom: 200,
left: "auto"
};
const isString = value => typeof value === "string";
return <View className={classNames(`${show ? "float_button__mask" : ""}`, props.className)} style={Object.assign({}, props.style)} onClick={() => {
closeWithShadow && clickButton();
}}>
<View className="float_button__fixed" style={{
top: position.top && position.top !== "auto" ? Taro.pxTransform(position.top) : "auto",
right: position.right && position.right !== "auto" ? Taro.pxTransform(position.right) : "auto",
bottom: position.bottom && position.bottom !== "auto" ? Taro.pxTransform(position.bottom) : "auto",
left: position.left && position.left !== "auto" ? Taro.pxTransform(position.left) : "auto"
}} animation={animation} onTouchStart={e => {
if (!move) return;
const touchs = e.touches[0];
tempPageX = touchs.pageX;
tempPageY = touchs.pageY;
}} onTouchMove={e => {
e.stopPropagation();
if (!move) return;
const touchs = e.touches[0];
let newAnimation = _createAnimation(animation);
pageX = pageX - (touchs.pageX - tempPageX);
pageY = pageY - (touchs.pageY - tempPageY);
const length = Math.sqrt(Math.pow(pageX, 2) + Math.pow(pageY, 2));
newAnimation.right(pageX);
newAnimation.bottom(pageY).step({
duration: 13 * length / 100
});
setAnimation(newAnimation.export());
tempPageX = touchs.pageX;
tempPageY = touchs.pageY;
}} onTouchCancel={e => {
e.stopPropagation();
}}>
<View className={`float_button__content ${directionClass}`}>
{actionListComponent}
<View className={`cu-avatar ${shape} ${dealSize} ${dealBgColor} ${dealShadow}`} onClick={e => {
e.stopPropagation();
clickButton();
onClick && onClick();
}}>
<View className={`${dealIconColor}`} style={{
transform: `rotate(${rotate}deg)`,
transition: "all 0.15s linear"
}}>
{isString(icon) ? <ClIcon iconName={icon} size={size} /> : <ClIcon {...icon} />}
</View>
</View>
</View>
</View>
</View>;
}
}
ClFloatButton.options = {
addGlobalClass: true
};
ClFloatButton.defaultProps = {
move: false,
open: true,
icon: "add",
bgColor: "blue",
iconColor: undefined,
direction: "vertical",
onClick: () => {},
shadow: true,
onActionClick: () => {},
actionList: [],
size: "normal",
shape: "round",
closeWithShadow: false,
position: {
top: "auto",
right: 50,
bottom: 200,
left: "auto"
}
};