zoukankan      html  css  js  c++  java
  • React-native/React 公告滚动组件(原生代码)

    编写不易, 希望大家点赞

    import React, {PureComponent} from 'react';
    import {Animated, Easing, View} from 'react-native';
    
    export default class NoticeScroll extends PureComponent {
      constructor(props) {
        super(props);
        this.state = {
          newChildren: this.props.children,
        };
        this.animation = new Animated.Value(0);
        this.direction = this.props.direction === 'vertical' ? 'height' : 'width';
        this.transationValue = this.props.styles[this.direction];
        this.key = 0;
        this.arr = [];
      }
    
      startAnimation() {
        const meter = this.props.meter || 0;
        Animated.timing(this.animation, {
          toValue: -this.transationValue + meter,
          duration: this.props.scrolltime || 5000,
          easing: Easing.linear,
          useNativeDriver: true,
        }).start(() => {
          this.animation = new Animated.Value(0);
          this.initPosition();
          this.startAnimation();
        });
      }
    
      initPosition() {
        this.key++;
        if (this.key < 2) {
          // React.Children.forEach(this.props.children, (child, index) => {
          //     let props = {
          //         key: `${this.key}${index}`,
          //         ...child.props
          //     };
          //     this.arr.push(React.cloneElement(child, props));
          // });
          React.Children.forEach(this.props.children, (child, index) => {
            let newProps = {
              key: `${this.key}${index}flag`,
              ...child.props,
            };
            this.arr.push(React.cloneElement(child, newProps));
          });
        }
    
        this.setState({
          newChildren: [...this.arr],
        });
      }
    
      componentDidMount() {
        this.initPosition();
        this.startAnimation();
      }
    
      componentWillUnmount() {
        this.startAnimation = () => {};
      }
    
      render() {
        const {styles, direction} = this.props;
        const {newChildren} = this.state;
        return (
          <View style={{overflow: 'hidden', height: 35, justifyContent: 'center'}}>
            <Animated.View
              style={{
                transform: [
                  direction !== 'vertical'
                    ? {translateX: this.animation}
                    : {translateY: this.animation},
                ],
                flexDirection: 'row',
              }}>
              {newChildren}
            </Animated.View>
          </View>
        );
      }
    }

    组件可以在React中直接使用,把Animated.View 改成Animated.div即可

    此代码有一个不好的地方,就是只能读取本地的,否则会有延迟

    优化代码!!!

    import React, { Component } from 'react';
    import { View, Animated, Easing, Text, TouchableOpacity, InteractionManager } from 'react-native';
    
    const styles = {
        bgContainerStyle : {
            flexDirection : 'row',
            alignItems : 'center',
            justifyContent : 'flex-start',
            backgroundColor : '#FFFFFF',
            overflow : 'hidden'
        },
        textMeasuringViewStyle: {
            flexDirection : 'row',
            opacity : 0,
        },
        textMeasuringTextStyle: {
            fontSize : 16,
        },
        textStyle : {
            fontSize : 16,
            color : '#000000',
        }
    };
    
    export default class ScrollAnnounce extends Component {
        constructor(props) {
            super(props);
            this.state = {
                animation : null,
                textList : [],
                textWidth : 0,
                viewWidth : 0,
                start:false
            }
        }
    
        static defaultProps = {
            duration : 10000,
            speed : 0,
            textList : [],
            width : 375,
            height : 50,
            direction : 'left',
            reverse : false,
            separator : 20,
            onTextClick : () => {},
        }
    
        componentWillMount(){
            this.setState({
                textList : this.props.textList || [],
            })
            this.animatedTransformX = new Animated.Value(0);
        }
    
        componentDidUpdate(){
            let { textWidth, viewWidth } = this.state;
            let { duration, speed, width, direction } = this.props;
            let mDuration = duration;
            if(speed && speed > 0){
                mDuration = (width + textWidth) / speed * 1000;
            }
            if(!this.state.animation && textWidth && viewWidth){
                this.animatedTransformX.setValue(direction == 'left' ? width : (direction == 'right' ? -textWidth : width));
                this.setState({
                    animation : Animated.timing(this.animatedTransformX, {
                        toValue: direction == 'left' ? -textWidth : (direction == 'right' ? width : -textWidth),
                        duration: mDuration,
                        useNativeDriver: true,
                        easing: Easing.linear,
                    }),
                }, () => {
                    this.state.animation && this.state.animation.start(() => {
                        this.setState({
                            animation: null,
                        });
                    });
                })
            }
    
        }
    
    
    
    
        componentWillReceiveProps(nextProps){
            let newText = nextProps.textList || [];
            let oldText = this.props.textList || [];
            if (newText !== oldText) {
                this.state.animation && this.state.animation.stop();
                this.setState({
                    textList : newText,
                    animation: null,
                    start:true
                });
            }
        }
    
        componentWillUnmount(){
            this.state.animation && this.state.animation.stop();
        }
    
        textOnLayout = (e) => {
            let width = e.nativeEvent.layout.width;
            let { textList, separator } = this.props;
            this.setState({
                textWidth : width + ((textList.length - 1) * separator),
            })
        }
    
        viewOnLayout = (e) => {
            let width = e.nativeEvent.layout.width;
            this.setState({
                viewWidth : width,
            })
        }
    
        textView(list){
            let { textStyle, onTextClick, reverse, separator } = this.props;
            let itemView = [];
            for(let i = 0;i<list.length;i++){
                let item = list[i];
                if(reverse){
                    item.value = item.value.split("").reverse().join("");
                }
                itemView.push(
                    <TouchableOpacity key = {''+i} activeOpacity = {0.9} onPress = {() => {
                        onTextClick(item)
                    }}>
                        <View style = {{flexDirection : 'row',marginRight : i < list.length - 1 ? separator : 0}}>
                            <Text style = {{
                                ...styles.textStyle,
                                ...textStyle
                            }}
                                  numberOfLines = {1}
                            >{item.value}</Text>
                        </View>
                    </TouchableOpacity>
                );
            }
            return(
                <Animated.View
                    style = {{flexDirection : 'row',width : this.state.textWidth,transform: [{ translateX: this.animatedTransformX }]}}
                    onLayout={(event) => this.viewOnLayout(event)}
                >
                    {itemView}
                </Animated.View>
            )
    
        }
    
        textLengthView(list){
            let { textStyle } = this.props;
            let text = '';
            for(let i = 0;i<list.length;i++){
                text += list[i].value;
            }
            return(
                <View style = {{
                    ...styles.textMeasuringViewStyle,
                    width : list.length * 1024
                }}>
                    <Text style = {{
                        ...styles.textMeasuringTextStyle,
                        ...textStyle
                    }}
                          onLayout={(event) => this.textOnLayout(event)}
                          numberOfLines = {1}
                    >{text}</Text>
                </View>
            )
    
        }
    
        render(){
            let { width, height, bgContainerStyle } = this.props;
            let { textList,start } = this.state;
            return(
                <View style = {{
                    ...styles.bgContainerStyle,
                    width : width,
                    height : height,
                    ...bgContainerStyle,
                }} opacity = {this.state.animation ? 1 : 0}>
                    {start&&this.textView(textList) }
                    {start&&this.textLengthView(textList) }
                </View>
            )
    
        }
    }
    ScrollAnnounce
    <ScrollAnnounce
        textList = {noticeList}
        speed = {60}
        width = {Platform.OS==='ios'?autoWidth(283):autoWidth(295)}
        height = {30}
        direction = {'left'}
        reverse = {false}
        bgContainerStyle = {{backgroundColor : '#f8f8f8'}}
        textStyle = {{fontSize : 12,color : '#D1B793'}}
        onTextClick = {(item) => {
            this._toDetail(item)
        }}
    />
  • 相关阅读:
    传智播客itcastbbs(二)
    传智播客itcastbbs(三)
    传智播客itcastbbs(一)(图文)
    传智播客itcastbbs(四)
    传智播客itcastbbs(六)
    双语美文:我想! 我做! 我得到!
    java邮件开发详解
    JDK_Tomcat_MyEclipse配置
    醋泡大蒜有什么功效
    优盘量产
  • 原文地址:https://www.cnblogs.com/it-Ren/p/12049081.html
Copyright © 2011-2022 走看看