Skip to content

Commit

Permalink
[5.2.2]feat: NoticeBar direction add 'up'&'down'(#1171)
Browse files Browse the repository at this point in the history
  • Loading branch information
1uokun committed Aug 10, 2024
1 parent b182377 commit af1c77c
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 39 deletions.
72 changes: 57 additions & 15 deletions components/notice-bar/Marquee.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { MarqueeProps } from './PropsType'

export const Marquee: React.FC<MarqueeProps> = (props) => {
const {
autoFill,
children,
direction = 'left',
fps = 40,
Expand All @@ -22,25 +21,45 @@ export const Marquee: React.FC<MarqueeProps> = (props) => {
spacing,
style,
trailing = 800,
wrapStyle,
} = props

const [parentWidth, setParentWidth] = useState(0)
const [childrenWidth, setChildrenWidth] = useState(0)
const isVertical = useMemo(
() => ['up', 'down'].includes(direction),
[direction],
)
const autoFill = isVertical || props.autoFill

// =========== parent & children onLayout ==============
const [parentLayout, setParentLayout] = useState({ width: 0, height: 0 })
const [childrenLayout, setChildrenLayout] = useState({ width: 0, height: 0 })
const onLayoutContainer = (e: LayoutChangeEvent) => {
setParentWidth(e.nativeEvent.layout.width)
setParentLayout(e.nativeEvent.layout)
}
const onLayoutContent = useCallback((e: LayoutChangeEvent) => {
setChildrenWidth(e.nativeEvent.layout.width)
setChildrenLayout(e.nativeEvent.layout)
}, [])

const parentWidth = useMemo(() => {
if (isVertical) {
return childrenLayout.height
}
return parentLayout.width
}, [childrenLayout.height, isVertical, parentLayout.width])
const childrenWidth = useMemo(() => {
if (isVertical) {
return childrenLayout.height
}
return childrenLayout.width
}, [isVertical, childrenLayout.width, childrenLayout.height])

// =========== fps & direction ==============
const duration = useMemo(() => {
return (1 / fps) * childrenWidth * 1000
}, [fps, childrenWidth])

const coeff = useMemo(() => {
return direction === 'left' ? 1 : -1
return ['left', 'up'].includes(direction) ? 1 : -1
}, [direction])

// =========== loop & onCycleComplete & onFinish ==============
Expand Down Expand Up @@ -97,7 +116,9 @@ export const Marquee: React.FC<MarqueeProps> = (props) => {

// =========== initialPosition & useEffect ==============
const initialPosition = useMemo(() => {
return direction === 'right' && autoFill ? -childrenWidth : 0
return ['right', 'down'].includes(direction) && autoFill
? -childrenWidth
: 0
}, [autoFill, childrenWidth, direction])

useEffect(() => {
Expand All @@ -117,11 +138,12 @@ export const Marquee: React.FC<MarqueeProps> = (props) => {
return {
transform: [
{
translateX: -offset.value + initialPosition,
[isVertical ? 'translateY' : 'translateX']:
-offset.value + initialPosition,
},
],
}
}, [initialPosition])
} as any
}, [initialPosition, direction])

const renderChild = useMemo(() => {
// autoFill multiples
Expand All @@ -134,8 +156,13 @@ export const Marquee: React.FC<MarqueeProps> = (props) => {
return (
<Text
key={index}
style={[spacing ? { paddingRight: spacing } : {}, style]}
numberOfLines={1}
style={[
spacing
? { [isVertical ? 'paddingBottom' : 'paddingRight']: spacing }
: {},
style,
]}
numberOfLines={isVertical ? undefined : 1}
ellipsizeMode="tail"
onLayout={index ? undefined : onLayoutContent}>
{children}
Expand All @@ -146,7 +173,13 @@ export const Marquee: React.FC<MarqueeProps> = (props) => {
<View
key={index}
onLayout={index ? undefined : onLayoutContent}
style={spacing ? { paddingRight: spacing } : undefined}>
style={
spacing
? {
[isVertical ? 'paddingBottom' : 'paddingRight']: spacing,
}
: undefined
}>
{children}
</View>
)
Expand All @@ -156,6 +189,7 @@ export const Marquee: React.FC<MarqueeProps> = (props) => {
autoFill,
children,
childrenWidth,
isVertical,
onLayoutContent,
parentWidth,
spacing,
Expand All @@ -165,10 +199,18 @@ export const Marquee: React.FC<MarqueeProps> = (props) => {
return (
<ScrollView
showsHorizontalScrollIndicator={false}
horizontal
horizontal={!isVertical}
scrollEnabled={false}
onLayout={onLayoutContainer}>
<Animated.View
style={[{ flexDirection: 'row', alignItems: 'center' }, animatedStyle]}>
style={[
wrapStyle,
{
maxHeight: childrenLayout.height || 'auto',
flexDirection: isVertical ? 'column' : 'row',
},
animatedStyle,
]}>
{renderChild}
</Animated.View>
</ScrollView>
Expand Down
4 changes: 2 additions & 2 deletions components/notice-bar/PropsType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export interface NoticeBarProps {
}

export interface MarqueeProps {
autoFill?: boolean // 实现方式:first动画结束后跟上second 参考: announcement/index
direction?: 'left' | 'right'
autoFill?: boolean
direction?: 'left' | 'right' | 'up' | 'down'
fps?: number
leading?: number
loop?: boolean | number
Expand Down
36 changes: 23 additions & 13 deletions components/notice-bar/demo/basic.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import React, { useState } from 'react'
import { ScrollView, Text } from 'react-native'
import { Icon, List, NoticeBar, Slider, Switch, WhiteSpace } from '../../'
import {
Icon,
List,
NoticeBar,
Picker,
Slider,
Switch,
WhiteSpace,
} from '../../'

export default function NoticeBarExample() {
return (
Expand Down Expand Up @@ -87,7 +95,9 @@ export default function NoticeBarExample() {
function ControlDemo() {
const [play, setPlay] = useState(true)
const [autoFill, setAutoFill] = useState(false)
const [direction, setDirection] = useState<'left' | 'right'>('left')
const [direction, setDirection] = useState<'left' | 'right' | 'up' | 'down'>(
'left',
)
const [fps, setFps] = useState(40)
return (
<>
Expand All @@ -110,17 +120,17 @@ function ControlDemo() {
<List.Item extra={<Switch checked={autoFill} onChange={setAutoFill} />}>
AutoFill
</List.Item>
<List.Item
extra={
<Switch
checkedChildren="L"
unCheckedChildren="R"
checked={direction === 'left'}
onChange={(checked) => setDirection(checked ? 'left' : 'right')}
/>
}>
Direction
</List.Item>
<Picker
data={[
{ label: 'Left', value: 'left' },
{ label: 'Right', value: 'right' },
{ label: 'Up', value: 'up' },
{ label: 'Down', value: 'down' },
]}
value={[direction]}
onChange={(val) => setDirection(val[0] as any)}>
<List.Item arrow="horizontal">Direction</List.Item>
</Picker>
<List.Item>
<List.Item.Brief>速度fps: {fps}</List.Item.Brief>
<Slider
Expand Down
6 changes: 3 additions & 3 deletions components/notice-bar/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Component to display a system message, event notice and etc. Which is under the
| Properties | Descrition | Type | Default | Version |
|------------|------------|------|---------|---------|
| autoFill | Whether to automatically fill blank space in the marquee with copies of the children or not | `Boolean` | false | `5.2.1` |
| direction | The direction the marquee slides | `"left"` \| `"right"` | "left" | `5.2.1` |
| direction | The direction the marquee slides | `'left'` \| `'right'` \| `'up'` \| `'down'` | `'left'` | `5.2.2` add `'up'`&`'down'` |
| fps | Speed calculated as pixels/second | `Number` | 40 | |
| leading | Duration to delay the animation after first render, in millisecond | `Number` | 500 | |
| loop | The number of times the marquee should loop, `true/0` is equivalent to infinite | `Boolean` \| `Number` | false | |
Expand All @@ -51,8 +51,8 @@ Component to display a system message, event notice and etc. Which is under the
```ts
interface NoticeBarStyle {
container: ViewStyle, // Outermost container style
font: TextStyle, // Font style, default: {color: theme.brand_error}
container: ViewStyle, // Outermost container style, default: {minHeight: 36(theme.notice_bar_height)}
font: TextStyle, // Font style, default: {color: #f4333c(theme.brand_error)}
background: ViewStyle, // Background color, default: {backgroundColor: #fffada}

marquee: TextStyle, // marquee font style
Expand Down
6 changes: 3 additions & 3 deletions components/notice-bar/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ version: update
| 属性 | 说明 | 类型 | 默认值 | 版本 |
|-----|------|-----|-------|-----|
| autoFill | 是否自动用children的副本填充字幕框中的空白区域 | `Boolean` | `false` | `5.2.1` |
| direction | 字幕滑动的方向 | `'left'` \| `'right'` | `'left'` | `5.2.1` |
| direction | 字幕滑动的方向 | `'left'` \| `'right'` \| `'up'` \| `'down'` | `'left'` | `5.2.2`新增`'up'`&`'down'` |
| fps | 滚动速度,单位 `pixels/second` | `Number` | 40 | |
| leading | 渲染后动画延迟的时间(以毫秒为单位) | `Number` | 500 | |
| loop | 字幕循环的次数, `true``0`表示无限次 | `Boolean` \| `Number` | `false` | |
Expand All @@ -52,8 +52,8 @@ version: update
```ts
interface NoticeBarStyle {
container: ViewStyle, // 最外层容器样式
font: TextStyle, // 字体样式,默认:{color: theme.brand_error}
container: ViewStyle, // 最外层容器样式,默认:{minHeight: 36(theme.notice_bar_height)}
font: TextStyle, // 字体样式,默认:{color: #f4333c(theme.brand_error)}
background: ViewStyle, // 背景颜色,默认:{backgroundColor: #fffada}

marquee: TextStyle, // 滚动字幕字体样式
Expand Down
4 changes: 1 addition & 3 deletions components/notice-bar/style/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default (variables: Theme) =>
backgroundColor: variables.notice_bar_fill,
},
container: {
height: variables.notice_bar_height,
minHeight: variables.notice_bar_height,
overflow: 'hidden',
flexDirection: 'row',
alignItems: 'center',
Expand All @@ -34,7 +34,6 @@ export default (variables: Theme) =>
marginRight: variables.h_spacing_sm,
},
actionWrap: {
height: '100%',
justifyContent: 'center',
paddingRight: variables.h_spacing_lg,
paddingLeft: variables.h_spacing_sm,
Expand All @@ -46,7 +45,6 @@ export default (variables: Theme) =>
},
link: {
transform: [{ rotate: '225deg' }],
fontSize: variables.font_size_icontext,
fontWeight: '500',
textAlign: 'left',
},
Expand Down

0 comments on commit af1c77c

Please sign in to comment.