未验证 提交 c090ee4d 编写于 作者: L libin0824 提交者: GitHub

feat: sticky 适配taro+文档多语言;image+audio 小程序路径删除。 (#613)

上级 118bc3fb
......@@ -230,7 +230,7 @@
"desc": "效果同 css 中的 position: sticky",
"sort": 7,
"show": true,
"taro": false,
"taro": true,
"author": "hx"
}
]
......
import React from 'react'
import React, { useRef } from 'react'
import { Button, Cell, Sticky } from '@/packages/nutui.react.taro'
import { useTranslate } from '@/sites/assets/locale/taro'
import { Sticky } from '@/packages/nutui.react.taro'
import Header from '@/sites/components/header'
import { getEnv } from '@tarojs/taro'
interface T {
basic: string
title1: string
title2: string
title3: string
button1: string
button2: string
button3: string
button4: string
changeTips: string
}
const StickyDemo = () => {
const containerTopRef = useRef(null)
const [translated] = useTranslate<T>({
'zh-CN': {
basic: '基本用法',
title1: '吸顶距离',
title2: '指定容器内吸顶',
title3: '吸底距离',
button1: '吸顶',
button2: '距离顶部120px',
button3: '指定容器内吸顶',
button4: '距离底部0px',
changeTips: '吸顶状态发生了改变,当前fixed为',
},
'zh-TW': {
basic: '基本用法',
title1: '吸頂距離',
title2: '指定容器內吸頂',
title3: '吸底距離',
button1: '吸頂',
button2: '距離頂部120px',
button3: '指定容器內吸頂',
button4: '距離底部0px',
changeTips: '吸頂狀態發生了改變,當前fixed為',
},
'en-US': {
basic: 'Basic usage ',
title1: 'Distance suction a top ',
title2: 'The specified container roof ',
title3: 'Suction bottom distance ',
button1: 'Suck the top ',
button2: 'From the top 120 px ',
button3: 'The specified container roof ',
button4: 'At the bottom of the distance to 0 px ',
changeTips: 'The ceiling status has changed, and the current fixed is',
},
})
const {
basic,
title1,
title2,
title3,
button1,
button2,
button3,
button4,
changeTips,
} = translated
const handleChange = (val: boolean) => {
console.log(`${changeTips}:${val}`)
}
return (
<>
<div className="demo">
<h2>基础用法</h2>
<Sticky></Sticky>
<Header />
<div className={`demo ${getEnv() === 'WEB' ? 'web' : ''}`}>
<h2>{basic}</h2>
<Cell>
<Sticky
top={getEnv() === 'WEB' ? 60 : 0}
onChange={(val: boolean) => handleChange(val)}
>
<Button type="primary">{button1}</Button>
</Sticky>
</Cell>
<h2>{title1}</h2>
<Cell>
<Sticky top={120}>
<Button type="primary">{button2}</Button>
</Sticky>
</Cell>
<h2>{title2}</h2>
<Cell>
<div
className="sticky-container"
ref={containerTopRef}
style={{ height: '600px' }}
>
<Sticky
container={containerTopRef}
top={getEnv() === 'WEB' ? 60 : 0}
>
<Button style={{ marginLeft: '100px' }} type="info">
{button3}
</Button>
</Sticky>
</div>
</Cell>
<h2>{title3}</h2>
<Cell style={{ height: '64px' }}>
<Sticky top={0} position="bottom">
<Button type="primary">{button4}</Button>
</Sticky>
</Cell>
</div>
</>
)
......
......@@ -2,61 +2,115 @@ import React, { useRef } from 'react'
import { Sticky } from './sticky'
import Button from '@/packages/button'
import Cell from '@/packages/cell'
import { useTranslate } from '@/sites/assets/locale'
interface T {
basic: string
title1: string
title2: string
title3: string
title4: string
button1: string
button2: string
button3: string
button4: string
button5: string
changeTips: string
}
const StickyDemo = () => {
const containerTopRef = useRef(null)
const containerRef = useRef(null)
const [translated] = useTranslate<T>({
'zh-CN': {
basic: '基本用法',
title1: '吸顶距离',
title2: '指定容器内吸顶',
title3: '指定容器吸底',
title4: '吸底距离',
button1: '吸顶',
button2: '距离顶部120px',
button3: '指定容器内吸顶',
button4: '指定容器吸底',
button5: '距离底部0px',
changeTips: '吸顶状态发生了改变,当前fixed为',
},
'zh-TW': {
basic: '基本用法',
title1: '吸頂距離',
title2: '指定容器內吸頂',
title3: '指定容器吸底',
title4: '吸底距離',
button1: '吸頂',
button2: '距離頂部120px',
button3: '指定容器內吸頂',
button4: '指定容器吸底',
button5: '距離底部0px',
changeTips: '吸頂狀態發生了改變,當前fixed為',
},
'en-US': {
basic: 'Basic usage ',
title1: 'Distance suction a top ',
title2: 'The specified container roof ',
title3: 'Specify the container bottom ',
title4: 'Suction bottom distance ',
button1: 'Suck the top ',
button2: 'From the top 120 px ',
button3: 'The specified container roof ',
button4: 'Specify the container bottom ',
button5: 'At the bottom of the distance to 0 px ',
changeTips: 'The ceiling status has changed, and the current fixed is',
},
})
const {
basic,
title1,
title2,
title3,
title4,
button1,
button2,
button3,
button4,
button5,
changeTips,
} = translated
const handleChange = (val: boolean) => {
console.log('吸顶状态发生了改变,当前fixed为', val)
console.log(`${changeTips}:${val}`)
}
return (
<>
<div className="demo">
<h2>基础用法</h2>
<h2>{basic}</h2>
<Cell>
<Sticky top={57} onChange={handleChange}>
<Button type="primary">吸顶</Button>
<Sticky top={57} onChange={(val: boolean) => handleChange(val)}>
<Button type="primary">{button1}</Button>
</Sticky>
</Cell>
<h2>吸顶距离</h2>
<h2>{title1}</h2>
<Cell>
<Sticky top={120}>
<Button type="primary">距离顶部120px</Button>
<Button type="primary">{button2}</Button>
</Sticky>
</Cell>
<h2>指定容器内吸顶</h2>
<h2>{title2}</h2>
<Cell>
<div
className="sticky-container"
ref={containerTopRef}
style={{ height: '300px' }}
style={{ height: '600px' }}
>
<Sticky container={containerTopRef} top={57}>
<Button style={{ marginLeft: '100px' }} type="info">
指定容器内吸顶
</Button>
</Sticky>
</div>
</Cell>
<h2>指定容器吸底</h2>
<Cell>
<div
className="sticky-container"
ref={containerRef}
style={{ height: '300px' }}
>
<Sticky position="bottom" container={containerRef} bottom={0}>
<Button style={{ marginLeft: '100px' }} type="info">
指定容器吸底
{button3}
</Button>
</Sticky>
</div>
</Cell>
<h2>吸底距离</h2>
<h2>{title4}</h2>
<Cell style={{ height: '64px' }}>
<Sticky top={0} position="bottom">
<Button type="primary">距离底部0px</Button>
<Button type="primary">{button5}</Button>
</Sticky>
</Cell>
</div>
......
# Sticky组件
# Sticky 组件
### 介绍
效果同 css 中的 position: sticky,对低端浏览器可使用其做兼容
> 支持吸顶、吸底、容器内吸顶效果,也可以使用官方sticky组件 https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/extended/component-plus/sticky.html
### 安装
```tsx
import { Sticky } from '@nutui/nutui-react-taro';
```tsx
import { Sticky } from '@nutui/nutui-react-taro'
```
## 代码演示
### 基础用法
:::demo
```tsx
import React, { useEffect, useRef, useState } from 'react'
import {Button,Cell, Sticky } from '@nutui/nutui-react-taro'
:::demo
```tsx
const App = () => {
import React, { useEffect, useRef, useState } from 'react'
import { Button, Cell, Sticky } from '@nutui/nutui-react-taro'
const handleChange = (val: boolean) => {
const handleChange = (val: boolean) => {
console.log('吸顶状态发生了改变,当前fixed为', val)
}
return(
return (
<>
<h2>基础用法</h2>
<Cell style={{ height: '300px' }}>
<Sticky top={57} onChange={handleChange}>
<Button type="primary">吸顶</Button>
</Sticky>
</Cell>
<h2>吸顶距离</h2>
<Cell style={{ height: '300px' }}>
<Sticky top={120}>
<Button type="primary">距离顶部120px</Button>
</Sticky>
</Cell>
<h2>吸底距离</h2>
<Cell style={{ height: '64px' }}>
<Sticky top={0} position="bottom">
<Button type="primary">距离底部0px</Button>
</Sticky>
</Cell>
<h2>基础用法</h2>
<Cell style={{ height: '300px' }}>
<Sticky top={57} onChange={(val: boolean) => handleChange(val)}>
<Button type="primary">吸顶</Button>
</Sticky>
</Cell>
<h2>吸顶距离</h2>
<Cell style={{ height: '300px' }}>
<Sticky top={120}>
<Button type="primary">距离顶部120px</Button>
</Sticky>
</Cell>
<h2>吸底距离</h2>
<Cell style={{ height: '64px' }}>
<Sticky top={0} position="bottom">
<Button type="primary">距离底部0px</Button>
</Sticky>
</Cell>
</>
)
}
export default App;
export default App
```
:::
### 指定容器内
:::demo
```tsx
import React, { useEffect, useRef, useState } from 'react'
import {Button,Cell, Sticky } from '@nutui/nutui-react-taro'
const App = () => {
const containerTopRef = useRef(null)
const containerRef = useRef(null)
return(
import React, { useEffect, useRef, useState } from 'react'
import { Button, Cell, Sticky } from '@nutui/nutui-react-taro'
return (
<>
<h2>指定容器内吸顶</h2>
<Cell>
<div
className="sticky-container"
ref={containerTopRef}
style={{ height: '300px' }}
>
<Sticky container={containerTopRef} top={57}>
<Button type="info">
指定容器内吸顶
</Button>
</Sticky>
</div>
</Cell>
<h2>指定容器吸底</h2>
<Cell>
<div
className="sticky-container"
ref={containerRef}
style={{ height: '300px' }}
>
<Sticky position="bottom" container={containerRef} bottom={0}>
<Button type="info">
指定容器吸底
</Button>
</Sticky>
</div>
</Cell>
<h2>指定容器内吸顶</h2>
<Cell>
<div
className="sticky-container"
ref={containerTopRef}
style={{ height: '300px' }}
>
<Sticky container={containerTopRef} top={57}>
<Button type="info">指定容器内吸顶</Button>
</Sticky>
</div>
</Cell>
</>
)
}
export default App;
export default App
```
:::
......@@ -104,16 +90,16 @@ export default App;
### Props
| 参数 | 说明 | 类型 | 默认值 |
|--------------|----------------------------------|--------|------------------|
| position | 吸附位置(top、bottom) | String | top |
| top | 吸顶距离 | Number | 0 |
| bottom | 吸底距离 | Number | 0 |
| z-index | 吸附时的层级 | Number | 2000 |
| container | 容器的 ref | `React.RefObject<HTMLElement>`|
| 参数 | 说明 | 类型 | 默认值 |
| --------- | ----------------------- | ------------------------------ | ------ |
| position | 吸附位置(top、bottom) | String | top |
| top | 吸顶距离 | Number | 0 |
| bottom | 吸底距离 | Number | 0 |
| z-index | 吸附时的层级 | Number | 2000 |
| container | 容器的 ref | `React.RefObject<HTMLElement>` |
### Events
| 事件名 | 说明 | 回调参数 |
|--------|------------------------------------------------|--------------|
| onChange | 吸附状态改变时触发 | val: Boolean |
| 事件名 | 说明 | 回调参数 |
| -------- | ------------------ | ------------ |
| onChange | 吸附状态改变时触发 | val: Boolean |
.nut-sticky-fixed {
position: fixed;
}
import React, { FunctionComponent } from 'react'
import { useConfig } from '@/packages/configprovider'
export interface StickyProps {}
const defaultProps = {} as StickyProps
export const Sticky: FunctionComponent<
Partial<StickyProps> & React.HTMLAttributes<HTMLDivElement>
> = (props) => {
const { locale } = useConfig()
const { children } = { ...defaultProps, ...props }
return <div className="nut-sticky">Sticky</div>
import React, {
FunctionComponent,
useRef,
useState,
useMemo,
CSSProperties,
useCallback,
useEffect,
} from 'react'
import { BasicComponent } from '@/utils/typings'
import useWatch from '@/utils/useWatch'
import { getRectByTaro } from '@/utils/useClientRect'
import {
PageScrollObject,
usePageScroll,
getSystemInfoSync,
getEnv,
} from '@tarojs/taro'
import { getScrollParent } from '@/utils/get-scroll-parent'
export interface StickyProps extends BasicComponent {
container?: React.RefObject<HTMLElement>
position?: 'top' | 'bottom'
className?: string
top?: number
bottom?: number
zIndex?: number
children: React.ReactNode
onChange?: (val: boolean) => void
}
interface StickyRect {
top: number
right: number
bottom: number
left: number
width: number
height: number
}
interface RootStyle {
width?: number | string
height?: number | string
}
interface StickyStyle extends RootStyle {
top?: number | string
bottom?: number | string
transform?: string
zIndex?: number
}
const defaultProps = {
position: 'top',
top: 0,
bottom: 0,
zIndex: 2000,
} as StickyProps
export const Sticky: FunctionComponent<StickyProps> = (props) => {
const {
position = 'top',
top = 0,
bottom = 0,
zIndex = 2000,
children,
container,
className,
onChange,
...rest
} = props
const stickyRef = useRef<HTMLDivElement>(null)
const rootRef = useRef<HTMLDivElement>(null)
const offset = position === 'top' ? top : bottom
const [rootRect, setRootRect] = useState<Partial<StickyRect>>({})
const [fixed, setFixed] = useState(false)
const [transform, setTransform] = useState(0) //相对容器偏移距离
useWatch(fixed, () => {
onChange && onChange(fixed)
})
const rootStyle: RootStyle = useMemo(() => {
if (!fixed) {
return {
height: '',
width: '',
}
}
const style: CSSProperties = {}
if (rootRect.height) {
style.height = rootRect.height
}
if (rootRect.width) {
style.width = rootRect.width
}
return style
}, [fixed, rootRect.height, rootRect.width])
const stickyStyle = useMemo(() => {
if (!fixed) {
return {
height: '',
width: '',
[position]: '',
}
}
let style: StickyStyle = {}
if (rootRect.height) style.height = rootRect.height
if (rootRect.width) style.width = rootRect.width
style.transform = `translate3d(0, ${transform}px, 0)`
style[position] = offset
style.zIndex = zIndex
return style
}, [fixed, rootRect.height, rootRect.width, transform, position])
const handleScroll: any = async (scrollTop: number) => {
const curRootRect = await getRectByTaro(rootRef.current)
const stickyRect = await getRectByTaro(stickyRef.current)
if (curRootRect && stickyRect) {
setRootRect(curRootRect)
if (position === 'top') {
if (container) {
const containerRect = await getRectByTaro(container.current)
const difference = containerRect.bottom - top - curRootRect.height
const curTransform = difference < 0 ? difference : 0
setTransform(curTransform)
const curFixed = top > curRootRect.top && containerRect.bottom > 0
setFixed(curFixed)
} else {
setFixed(top > curRootRect.top)
}
} else {
const windowHeight = getSystemInfoSync().windowHeight
setFixed(windowHeight - offset < curRootRect.bottom)
}
} else {
console.log('getRectByTaro获取失败', { stickyRect, curRootRect })
}
}
const getElement = useCallback(() => {
return getScrollParent(rootRef.current as HTMLElement)
}, [])
useEffect(() => {
if (getEnv() === 'WEB' && getElement() !== window) {
window.addEventListener('touchmove', handleScroll, true)
window.addEventListener('scroll', handleScroll, true)
return () => {
window.removeEventListener('touchmove', handleScroll)
window.removeEventListener('scroll', handleScroll)
}
}
}, [])
usePageScroll((res: PageScrollObject) => {
if (getEnv() === 'WEAPP') {
handleScroll(res.scrollTop)
}
})
return (
<div
ref={rootRef}
style={rootStyle}
className={`nut-sticky ${className}`}
{...rest}
>
<div
className={`nut-sticky-box ${fixed ? 'nut-sticky-fixed' : ''}`}
ref={stickyRef}
style={stickyStyle}
>
{children}
</div>
</div>
)
}
Sticky.defaultProps = defaultProps
......
......@@ -21,6 +21,13 @@ export interface StickyProps extends BasicComponent {
onChange?: (val: boolean) => void
}
const defaultProps = {
position: 'top',
top: 0,
bottom: 0,
zIndex: 2000,
} as StickyProps
export const Sticky: FunctionComponent<StickyProps> = (props) => {
const {
position = 'top',
......@@ -31,7 +38,6 @@ export const Sticky: FunctionComponent<StickyProps> = (props) => {
container,
className,
onChange,
...rest
} = props
// const { locale } = useConfig()
......@@ -178,5 +184,5 @@ export const Sticky: FunctionComponent<StickyProps> = (props) => {
)
}
// Sticky.defaultProps = defaultProps
Sticky.defaultProps = defaultProps
Sticky.displayName = 'NutSticky'
......@@ -12,7 +12,12 @@ const subPackages = [
},
{
root: 'layout',
pages: ['pages/divider/index', 'pages/grid/index', 'pages/layout/index'],
pages: [
'pages/divider/index',
'pages/grid/index',
'pages/layout/index',
'pages/sticky/index',
],
},
{
root: 'nav',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册