UNPKG

mp-colorui

Version:

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

143 lines (141 loc) 5.45 kB
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" } };