react - native 文字跑马灯组件上下滚动

import React, { Component } from 'react'
import {
Text,
View,
Animated,
Easing,
StyleSheet,
} from 'react-native'
import PropTypes from 'prop-types'

export default class ScrollVertical extends Component {

static defaultProps = { enableAnimation: true }

constructor(props) {
    super(props)
    const translateValue = new Animated.ValueXY({ x: 0, y: 0 })
    this.state = {
        translateValue,
        // 滚屏高度
        scrollHeight: this.props.scrollHeight || 32,
        // 滚屏内容
        kb_content: [],
        // Animated.View 滚动到的 y轴坐标
        kb_tempValue: 0,
        // 最大偏移量
        kb_contentOffsetY: 0,
        // 每一次滚动切换之前延迟的时间
        delay: this.props.delay || 500,
        // 每一次滚动切换的持续时间
        duration: this.props.duration || 500,
        enableAnimation: true,
    }
    this.createKbItem = this.createKbItem.bind(this)
}

componentDidMount() {
    const content = this.props.data || []
    if (content.length !== 0) {
        const h = (content.length + 1) * this.state.scrollHeight
        this.setState({
            kb_content: content.concat(content[0]),
            kb_contentOffsetY: h
        })
        // 开始动画
        this.startAnimation()
    }
}
componentWillReceiveProps(nextProps) {
    const context = nextProps.data;
    if (context.length !== 0) {
        const h = (context.length + 1) * this.state.scrollHeight;
        this.setState({
            kb_content: context.concat(context[0]),
            kb_contentOffsetY: h
        });
    }
    this.setState({
        enableAnimation: !!nextProps.enableAnimation
    }, () => {
        this.startAnimation()
    });
}

componentWillUnmount() {
    if (this.animation) {
        clearTimeout(this.animation)
    }
    if (this.state.translateValue) {
        this.state.translateValue.removeAllListeners()
    }
}

overStep(name, num = 13) {
    if (name.length > num) {
        return `${name.substring(0, num)}...`
    }
    return name
}

createKbItem(kbItem, index) {
    return (
        <View key={index}
              style={[{justifyContent: 'center', height: this.state.scrollHeight }, this.props.scrollStyle]}>
            <Text style={[styles.kb_text_c, this.props.textStyle]}>
                {this.overStep(kbItem.title)}
            </Text>
        </View>
    )
}
startAnimation = () => {
    if (this.state.enableAnimation) {
        if (!this.animation) {
            this.animation = setTimeout(() => {
                this.animation = null
                this.startAnimationSeamless()
            }, this.state.delay)
        }
    }
}

startAnimationSeamless = () => {
    this.state.kb_tempValue -= this.state.scrollHeight
    if (this.props.onChange) {
        const index = Math.abs(this.state.kb_tempValue) / (this.state.scrollHeight)
        this.props.onChange(index < this.state.kb_content.length - 1 ? index : 0)
    }
    Animated.sequence([
        Animated.timing(
            this.state.translateValue, {
                isInteraction: false,
                toValue: { x: 0, y: this.state.kb_tempValue },
                duration: this.state.duration, // 动画持续的时间(单位是毫秒),默认为500
                easing: Easing.linear
            }),
    ])
        .start(() => {
            // 无缝切换
            if (this.state.kb_tempValue - this.state.scrollHeight === -this.state.kb_contentOffsetY) {
                // 快速拉回到初始状态
                this.state.translateValue.setValue({ x: 0, y: 0 })
                this.state.kb_tempValue = 0
            }
            this.startAnimation()
        })
}

render() {
    return (
        <View style={[styles.kbContainer, { height: this.state.scrollHeight }, this.props.kbContainer]}>
            {
                this.state.kb_content.length !== 0 ?
                    <Animated.View style={[{ flexDirection: 'column' }, { transform: [{ translateY: this.state.translateValue.y }]}]}>
                        {this.state.kb_content.map(this.createKbItem)}
                    </Animated.View> : null
            }
            </View>
    )
}

}

const styles = StyleSheet.create({
kbContainer: {
// 必须要有一个背景或者一个border,否则本身高度将不起作用
backgroundColor: 'transparent',
overflow: 'hidden'
},
kb_text_c: {
fontSize: 18,
color: '#181818'
}
})

// PropTypes类型
ScrollVertical.propTypes={
scrollHeight: PropTypes.number,
data: PropTypes.array,
textStyle: PropTypes.object,
scrollStyle: PropTypes.object,
kbContainer: PropTypes.object,
onChange: PropTypes.func,
enableAnimation: PropTypes.bool,
duration: PropTypes.number,
delay: PropTypes.number,
onPress: PropTypes.func
}

// 默认属性
ScrollVertical.defaultProps = {
translateValue: [],
scrollHeight: 34,
kb_content: [],
kb_tempValue: 0,
kb_contentOffsetY: 0,
delay: 500,
duration: 500,
enableAnimation: true
}

                                   跑马灯的使用

const dataArray = [{title: '保险全场五折'}, {title: '打到骨折'},{ title: '骨折甩卖,全场骨折甩卖'},{title: '保险全场五折,你买不了吃亏买不了上当嗷嗷嗷'}]
<ScrollVertical
onChange={(index => {this.index = index})}
onPress={(value) => {this.setModalVisible(value)}}
enableAnimation
data={arrayContent}
delay={1000}
duration={300}
scrollHeight={20}
scrollStyle={{ alignItems: 'flex-start' }}
textStyle={{ fontSize: 12, color: 'red' }}
/>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容

  • 今天星期四,天气阴,下雨。 查房病人病情简介: 38床,新住院病人,检查和抽血。明天手术 46床:石膏不合适 16...
    38671d38a1bc阅读 271评论 0 0
  • 一、header   在需要设置为标题的文字前加#来表示  一个#表示一级标题,两个#表示二级标题,依次类推,直到...
    gallo_beb6阅读 406评论 0 0
  • 小程序总结 最近公司要开发一款电商小程序,匆忙看了一遍文档就开始干活了。整体开发体验个人感觉不太好,特别是如果之前...
    水手008阅读 218评论 0 0
  • 孩子你听 海风带着贝壳吹奏长笛 吹起每一朵浪花 我愿你听见这自然的呼吸 孩子你看 晚霞绯红了黄昏的脸颊 星星躲躲闪...
    斯人会阅读 223评论 0 0
  • 好雨知时节,今夜又发生。雷电潜入夜,润物发出声。三更没睡着,吟诗好心情。
    诗诗如意阅读 114评论 3 1