From 3837c07dd84d697b5b686a48bafda6f41da4622d Mon Sep 17 00:00:00 2001 From: xuan Date: Thu, 13 Oct 2022 17:41:14 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(toolTip=E7=BB=84=E4=BB=B6):=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9EtoolTip=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/dropDown-item/index.tsx | 4 + src/components/toolTips/index.module.scss | 50 +++++ src/components/toolTips/index.tsx | 216 ++++++++++++++++++++++ src/pages/saleStatistic/index.tsx | 11 +- 4 files changed, 277 insertions(+), 4 deletions(-) create mode 100644 src/components/toolTips/index.module.scss create mode 100644 src/components/toolTips/index.tsx diff --git a/src/components/dropDown-item/index.tsx b/src/components/dropDown-item/index.tsx index 3586ad4..ba2bc2c 100644 --- a/src/components/dropDown-item/index.tsx +++ b/src/components/dropDown-item/index.tsx @@ -1,3 +1,7 @@ +/** + * 注意:需要在父节点设置 position: relative; + */ + import { View, Text } from '@tarojs/components' import { useEffect, useMemo, useRef, useState } from 'react' import styles from './index.module.scss' diff --git a/src/components/toolTips/index.module.scss b/src/components/toolTips/index.module.scss new file mode 100644 index 0000000..311ceef --- /dev/null +++ b/src/components/toolTips/index.module.scss @@ -0,0 +1,50 @@ +.mark { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: transparent; +} +.tooltip { + &-container{ + position: relative; + } + position: absolute; + left: 0; + top: 0; + user-select: text; + color: white; + &-inner { + position: absolute; + background-color: #333333; + font-size: $font_size; + box-shadow: 0 0 30px 0 rgba(51, 51, 51, 0.2); + border-radius: 8px; + &-content { + padding: 8px 12px; + white-space: nowrap; + } + } + &-hidden { + display: none; + } +} +.arrowIcon { + position: absolute; + display: flex; + justify-content: center; + align-items: center; + &-top { + transform: rotate(0deg); + } + &-left { + transform: rotate(270deg); + } + &-right { + transform: rotate(90deg); + } + &-bottom { + transform: rotate(180deg); + } +} diff --git a/src/components/toolTips/index.tsx b/src/components/toolTips/index.tsx new file mode 100644 index 0000000..c8fc8f2 --- /dev/null +++ b/src/components/toolTips/index.tsx @@ -0,0 +1,216 @@ +import { View } from '@tarojs/components' +import Taro from '@tarojs/taro' +import classNames from 'classnames' +import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react' +import IconFont from '../iconfont/iconfont' +import styles from './index.module.scss' + +const SystemWidth = Taro.getSystemInfoSync().windowWidth + +const arrowSize = 32 + +// 由于taro自动把px编译成rpx,所以这里需要把单位处理一下 转成真正的px +const convertPx = (px: number) => { + const realPx = (px / 750) * SystemWidth + return realPx +} + +type Placement = 'top' | 'right' | 'bottom' | 'left' + +interface ToolTipEvent { + onVisibleChange?: (visible?: boolean) => void +} + +interface ToolTipPropsType extends ToolTipEvent { + defaultVisible?: boolean + content: React.ReactNode + placement?: Placement + children?: React.ReactNode + customClassName?: string + customStyle?: React.CSSProperties + customContentStyle?: React.CSSProperties +} + +interface ToolTipRef { + show: () => void + hide: () => void + visible: boolean +} + +const popoverStyle = { + color: '#333333', +} + +const ToolTip = forwardRef((props, ref) => { + const { placement = 'top', defaultVisible = false, onVisibleChange, children, content = '请填入提示信息', customClassName, customStyle, customContentStyle } = props + + if (!content){ + throw new Error('tooltip: content 不能为空') + } + + const [visible, setVisible] = useState(defaultVisible) + + const onVisibleChangeRef = useRef(onVisibleChange) + onVisibleChangeRef.current = onVisibleChange + + // 暴露方法给外部 + useImperativeHandle( + ref, + () => { + return { + show: () => setVisible(true), + hide: () => setVisible(false), + visible, + } + }, + [visible], + ) + + const handleClick = useCallback(() => { + setVisible(v => { + onVisibleChangeRef.current?.(!v) + return !v + }) + }, []) + + const handleClickMark = useCallback(() => { + setVisible(false) + onVisibleChangeRef.current?.(false) + }, []) + + const getArrowSide = useMemo(() => { + const side = placement.split('-')[0] as string // placement = 'top-start' 取 'top' + + const arrowSide = { + top: 'bottom', + right: 'left', + bottom: 'top', + left: 'right', + }[side] as string + return arrowSide + }, [placement]) + + const [childrenRect, setChildrenRect] = useState({}) + const childrenRectRef = useRef(childrenRect) + childrenRectRef.current = childrenRect + + const [viewport, setViewport] = useState({}) + const viewportRef = useRef(viewport) + viewportRef.current = viewport + + useEffect(() => { + console.log('useLayoutEffect') + const query = Taro.createSelectorQuery() + query.select('#children').boundingClientRect() + query.selectViewport().scrollOffset() + query.exec(res => { + console.log(res[0]) + console.log(res[1]) + setChildrenRect(res[0]) + childrenRectRef.current = res[0] + setViewport(res[1]) + viewportRef.current = res[1] + }) + }, []) + + // 箭头 坐标 + const arrowCoords = useMemo(() => { + console.log('getArrowSide==>', getArrowSide, childrenRectRef.current) + switch (getArrowSide) { + case 'bottom': // 下箭头 + return { + left: childrenRectRef.current.width / 2 - convertPx(arrowSize) / 2, + top: -convertPx(arrowSize), + right: '', + bottom: '', + } + case 'left': // 左箭头 + return { + left: childrenRectRef.current.width, + right: '', + top: childrenRectRef.current.height / 2 - convertPx(arrowSize) / 2, + bottom: '', + } + case 'top': // 上箭头 + return { + left: childrenRectRef.current.width / 2 - convertPx(arrowSize) / 2, + right: '', + top: childrenRectRef.current.height, + bottom: '', + } + case 'right': // 右箭头 + return { + left: -convertPx(arrowSize), + right: '', + top: childrenRectRef.current.height / 2 - convertPx(arrowSize) / 2, + bottom: '', + } + } + }, [getArrowSide, childrenRectRef.current]) + + // content 坐标 + const contentCoords = useMemo(() => { + switch (getArrowSide) { + case 'bottom': // 下箭头 + return { + left: 0, + top: '', + right: '', + bottom: convertPx(arrowSize) - 5, + } + case 'left': // 左箭头 + return { + left: childrenRectRef.current.width + convertPx(arrowSize) - 5, + top: 0, + right: '', + bottom: '', + } + case 'top': // 上箭头 + return { + left: 0, + top: childrenRectRef.current.height + convertPx(arrowSize) - 5, + right: '', + bottom: '', + } + case 'right': // 右箭头 + return { + left: '', + top: 0, + right: convertPx(arrowSize) - 5, + bottom: '', + } + } + }, [getArrowSide, childrenRectRef.current]) + + const ContentComponent = useMemo(() => { + console.log('执行完') + + return ( + + {/* 箭头 */} + + + + {/* content */} + + {content} + + + ) + }, [content, getArrowSide, visible, arrowCoords, contentCoords]) + + return ( + <> + {/* 遮罩层 */} + + + + {children} + + {ContentComponent} + + + ) +}) + +export default ToolTip diff --git a/src/pages/saleStatistic/index.tsx b/src/pages/saleStatistic/index.tsx index 8be07b7..9a93d48 100644 --- a/src/pages/saleStatistic/index.tsx +++ b/src/pages/saleStatistic/index.tsx @@ -10,6 +10,7 @@ import SelectSaleType from '@/components/SelectSaleType' import SelectTimePicker, { ChangedValue } from '@/components/SelectTimePicker' import Table from '@/components/table' import TimePicker from '@/components/timePicker' +import ToolTip from '@/components/toolTips' import { View, Text } from '@tarojs/components' import classnames from 'classnames' import dayjs from 'dayjs' @@ -177,10 +178,12 @@ const saleStatistic = () => { - - 订单总数 - - + + + 订单总数 + + + 3425 (共432423匹)