uniapp 时间轴

先上图看图说话

时间轴的轴线可以居中分两边,也可以像上图一样。

上代码:

<view class="content">
    <time-line ref="timeline" location="left"></time-line>
</view>
<script>
    import timeLine from '../../components/xuan-timeLine/xuan-timeLine.vue'
    export default {
        components:{
            timeLine
        },
        data() {
            return {
                time:0,
                isclick:true,
            };
        },
        onLoad() {
            
        },
        onPageScroll() {
            if(this.isclick){
                this.timer();
                this.$refs.timeline.getScroll();
            }
        },
        onReady() {
            
        },
        methods: {
            timer(){
                if(this.time>0){
                    this.isclick=false;
                    this.time--;
                    setTimeout(this.timer,1)
                }
                else{
                    this.isclick=true;
                    this.time=10
                }
            }
            
        }
    };
</script>
xuan-timeLine.vue代码
<template>
    <scroll-view class="time-line-wrap">
        <view class="time-line">
            <!-- 时间轴 -->
            <view class="time-line-container" :class="addTypeClass">
                <!-- 时间轴内容块列表 -->
                <view class="time-line-list">
                    
                    <!-- 时间轴内容块 -->
                    <view class="time-line-info" :key="index" :class="[layoutClass(index)]" :id="'timeline'+index" v-for="(item,index) of time_line_list">
                        
                        
                        <!-- 内容块内容 -->
                        <view class="line-info-content" >
                            
                            <!-- 时间轴圆点 -->
                            <view class="line-on-round" :style="{ opacity: current[index]&&current[index].is=='ok'?1:0,top:'12rpx'}" :class="current[index]&&current[index].is=='ok'?comeani:''"></view>
                            
                            <view class="info-content-wrap" :style="{ opacity: current[index]&&current[index].is=='ok'?1:0}" :class="current[index]&&current[index].is=='ok'?comeani:''">
                                <!-- 标题 -->
                                <view class="info-title">
                                    {{item.title}}
                                </view>
                                <view class="bmjg">报名<text>2</text>个培训机构,<text>4</text>节培训课程</view>
                                <!-- 内容 -->
                                <view class="info-content">
                                    <view class="jg_bg">
                                        <view class="">
                                            <view class="jg_name">思语校外培训学校</view>
                                            <view class="jg_pf_ico">
                                                <image src="../../static/index/pfxx.png" mode=""></image>
                                                <image src="../../static/index/pfxx.png" mode=""></image>
                                                <image src="../../static/index/pfxx.png" mode=""></image>
                                                <image src="../../static/index/pfxx.png" mode=""></image>
                                                <image src="../../static/index/pfwxz.png" mode=""></image>
                                                <view class="rzbm">4星·成教部门认证</view>
                                            </view>
                                        </view>
                                        <view class="">
                                            <view class="jg_num">8.5</view>
                                            <view class="jg_pftxt">评分</view>
                                        </view>
                                    </view>
                                    <view class="kc_bg">
                                        <image class="kc_logo" src="../../static/index/xsfmlist2@2x.png" mode=""></image>
                                        <view class="">
                                            <view class="kc_name">初中年级户外研学</view>
                                            <view class="kc_time">6月14日-6月20日 · 共三章</view>
                                            <view class="jiaoyu">中学教育 · 历史</view>
                                        </view>
                                    </view>
                                    <view class="kc_bg">
                                        <image class="kc_logo" src="../../static/index/xsfmlist2@2x.png" mode=""></image>
                                        <view class="">
                                            <view class="kc_name">初中年级户外研学</view>
                                            <view class="kc_time">6月14日-6月20日 · 共三章</view>
                                            <view class="jiaoyu">中学教育 · 历史</view>
                                        </view>
                                    </view>
                                </view>
                                <view class="info-content">
                                    <!-- 内容 -->
                                    <view class="jg_bg">
                                        <view class="">
                                            <view class="jg_name">思语校外培训学校</view>
                                            <view class="jg_pf_ico">
                                                <image src="../../static/index/pfxx.png" mode=""></image>
                                                <image src="../../static/index/pfxx.png" mode=""></image>
                                                <image src="../../static/index/pfxx.png" mode=""></image>
                                                <image src="../../static/index/pfxx.png" mode=""></image>
                                                <image src="../../static/index/pfwxz.png" mode=""></image>
                                                <view class="rzbm">4星·成教部门认证</view>
                                            </view>
                                        </view>
                                        <view class="">
                                            <view class="jg_num">8.5</view>
                                            <view class="jg_pftxt">评分</view>
                                        </view>
                                    </view>
                                    <view class="kc_bg">
                                        <image class="kc_logo" src="../../static/index/xsfmlist2@2x.png" mode=""></image>
                                        <view class="">
                                            <view class="kc_name">初中年级户外研学</view>
                                            <view class="kc_time">6月14日-6月20日 · 共三章</view>
                                            <view class="jiaoyu">中学教育 · 历史</view>
                                        </view>
                                    </view>
                                    <view class="kc_bg">
                                        <image class="kc_logo" src="../../static/index/xsfmlist2@2x.png" mode=""></image>
                                        <view class="">
                                            <view class="kc_name">初中年级户外研学</view>
                                            <view class="kc_time">6月14日-6月20日 · 共三章</view>
                                            <view class="jiaoyu">中学教育 · 历史</view>
                                        </view>
                                    </view>
                                </view>
                                
                                
                                
                            </view>
                            
                        </view>
                    </view>
                </view>
            </view>
        </view>
    </scroll-view>
</template>

<script>
    export default{
        data(){
            return{
                // 数据
                time_line_list:[
                    {
                        title:'6月',
                    },
                    {
                        title:'2020年12月',
                    },
                ],
                HEIGHT:0,//屏幕高度
                result:[],//监听的结果
                current:[],//当前在屏幕内的
                sum:0,//加载完成个数
                comeani:'come-ani',//入场动画
                isScroll:true,//是否加载动画
            }
        },
        props:{
            location:{
                type:String,
                default:'center',
            },
            title:{
                type:String,
                default:'时间轴'
            },
        },
        computed:{
            addTypeClass(){
                let _class="";
                let arrType =["left","right","center"];
                if (arrType.indexOf(this.location)!==-1&&this.location!=='center') {
                    _class+=this.location+"-time-line";
                }
                return _class;
            }
        },
        mounted() {
            this.init();
        },
        methods:{
            init(){
                try {
                    // 获取屏幕高度
                    const res = uni.getSystemInfoSync();
                    this.HEIGHT=res.screenHeight;
                    // 添加标志位
                    for(let i=0;i<this.time_line_list.length;i++){
                        this.current.push({tag:'timeline'+i,is:'no'});
                    }    
                    // 开始获取位置信息
                    this.getScroll();        
                } catch (e) {
                    // error
                }
                
            },
            loadani(){
                for(let i=0;i<this.result.length;i++){
                    for(let j=0;j<this.result[i].info.length;j++){
                        // 是否没加载动画
                        if(this.current[j].is!='ok'){
                            // 是否进入视野
                            if(this.current[j].tag==this.result[i].info[j].tag &&
                               this.result[i].info[j].domTop+90<this.HEIGHT){
                                // 加载动画
                                this.current[j].is='ok';
                                this.sum=j+1;
                            }
                        }
                    }
                    // 移除当前
                    this.result.splice(i,1);
                }
                // 是否全部加载完成
                if(this.sum==this.time_line_list.length){this.isScroll=false;}
            },
            async getScroll(){
                if(!this.isScroll){return;}
                let info=[];
                // 返回位置信息加入数组
                for(let i=0;i<this.time_line_list.length;i++){
                    await this.getNodeList('timeline'+i,i).then(res => {
                        info.push(res);
                    });
                }
                this.result.push({info:info});
                // 加载动画
                this.loadani();
            },
            getNodeList(id,i){
                // 获取位置信息并返回
                return new Promise(resolve=>{
                    const query = uni.createSelectorQuery().in(this);
                    query.select('#'+id).boundingClientRect(data => {
                      // console.log("得到布局位置信息" + JSON.stringify(data));
                      // console.log("节点离页面顶部的距离为" + data.top);
                      resolve({domInfo:data.height,domTop:data.top,tag:id})
                    }).exec();
                });
            },
            // 添加动画
            layoutClass(index){
                let _class="";
                if(this.location=='center'&&index%2!=0){
                    _class='right-info';
                }
                return _class;
            }
        },
    }
</script>
style
<style lang="scss">
    // 
    .bmjg{
        font-size: 24rpx;
        color: #757575;
        margin-top: 20rpx;
    }
    .bmjg>text{
        color: #E18326;
    }
    .jg_bg{
        display: flex;
        align-items: center;
        justify-content: space-between;
        height: 149rpx;
        // border-bottom: 2rpx solid #EAEAEA;
    }
    .jg_name{
        font-size: 28rpx;
        color: #323232;
        font-weight: bold;
    }
    .jg_num{
        font-size: 36rpx;
        color: #E18326;
        font-weight: bold;
    }
    .jg_pftxt{
        font-size: 20rpx;
        color: #757575;
        text-align: center;
        margin-top: 10rpx;
    }
    .jg_pf_ico{
        display: flex;
        align-items: center;
        margin-top: 20rpx;
    }
    .jg_pf_ico>image{
         24rpx;
        height: 24rpx;
        margin-right: 4rpx;
    }
    .rzbm{
        font-size: 20rpx;
        color: #E18326;
    }
    .kc_bg{
        height: 180rpx;
        border-top: 2rpx solid #EAEAEA;
        display: flex;
        align-items: center;
    }
    .kc_logo{
         174rpx;
        height: 116rpx;
        border-radius: 8rpx;
        margin-right: 20rpx;
    }
    .kc_name{
        font-size: 28rpx;
        color: #323232;
        font-weight: bold;
    }
    .kc_time{
        font-size: 20rpx;
        color: #323232;
        margin: 14rpx 0;
    }
    .jiaoyu{
        font-size: 20rpx;
        color: #757575;
    }
    
    
    // 
    .time-line-wrap{
         100%;
        overflow-x: hidden;
    }
    .time-line-wrap{
        font-family: sans-serif;
        .time-line{
            padding: 4% 1%;
            .time-line-title{
                font-size: 25rpx;
                font-weight: 800;
                text-align: center;
                margin-bottom: 15rpx;
            }
            // 中间的轴
            .time-line-container{
                padding: 3% 1%;
                position: relative;
                &::before{
                    content: '';
                    position: absolute;
                    top: 0;
                    left: 0;
                    right: 0;
                    margin: 0 auto;
                    height: 100%;
                     4rpx;
                    background: #F0F0F0;
                }
                .time-line-list{
                     100%;
                    .time-line-info{    
                        position: relative;
                        .line-info-content{
                            will-change: auto;
                             43%;
                            display: flex;
                            flex-direction: column;
                            .line-on-round{
                                height: 20rpx;
                                 20rpx;
                                border: 4rpx solid #E18427;
                                border-radius: 50%;
                                background: #fff;
                                position: absolute;
                                left: 0;
                                right: 0;
                                margin: 0 auto;
                                top: 50rpx;
                                box-shadow: 0rpx 2rpx 1rpx 1rpx rgba(0,0,0,.1);
                                z-index: 10;
                                &.come-ani{
                                    animation: come-round .8s ease-in-out;
                                }
                            }
                            .info-content-wrap{
                                position: relative;
                                .info-title{
                                    min-height: 30rpx;
                                    word-break: break-word;
                                    text-align: right;
                                    margin: 5rpx 0;
                                    font-size: 34rrpx;
                                    font-weight: 500;
                                    color: #E18427;
                                    font-weight: bold;
                                }
                                .info-content{
                                    box-shadow: 1rpx 1rpx 1rpx 1rpx #d7e4ed;
                                    border-radius: 8rpx;
                                    padding: 30rpx;
                                    min-height: 40rpx;
                                    position: relative;    
                                    margin-top: 20rpx;
                                    .info-txt{}
                                    // &::before{
                                    //     content: '';
                                    //     border: 7rpx solid;
                                    //     border-color: transparent transparent transparent #aaa;
                                    //     position: absolute;
                                    //     left: 100%;
                                    //     top: 18rpx;
                                    // }
                                }
                                &.come-ani{
                                    animation: come-in-left .6s ease-in-out;
                                }        
                            }
                        }
                    }
                    .right-info{
                        transform: rotateY(180deg);
                        .line-info-content{
                            .info-content-wrap{
                                .info-title{
                                    transform: rotateY(180deg);
                                    text-align: left;
                                }
                                .info-content{
                                    .info-txt{transform: rotateY(180deg)}
                                }
                            }
                        }
                    }
                }
            }
            
            // 轴在左边
            .left-time-line{
                &::before{
                    margin: 0;
                    left: 15rpx;
                }
                .time-line-list{
                    .time-line-info{    
                        .line-info-content{
                             auto;
                            .line-on-round{
                                left: -4rpx;
                                margin: 0;
                            }
                            .info-content-wrap{
                                margin-left: 45rpx;
                                margin-bottom: 15rpx;
                                .info-title{
                                    text-align: left;    
                                }
                                .info-content{
                                    &::before{
                                        border-color: transparent #aaa transparent transparent;
                                        left: -15rpx;
                                    }
                                }
                                &.come-ani{
                                    animation: come-in-right .6s ease-in-out;
                                }
                            }
                        }
                    }
                }
            }
            
            // 轴在右边
            .right-time-line{
                &::before{
                    margin: 0;
                    left: 92.8%;
                }
                .time-line-list{
                    .time-line-info{    
                        .line-info-content{
                             auto;
                            .line-on-round{
                                left: 90%;
                                margin: 0;
                            }
                            .info-content-wrap{
                                margin-right: 55rpx;
                                margin-bottom: 15rpx;
                                .info-content{
                                    &::before{
                                        border-color: transparent transparent transparent #aaa;
                                    }
                                }
                                
                            }
                        }
                    }
                }
            }
        }
    }
    
    @keyframes come-in-left {
        0% {
            transform: translateX(-120%);
        }
        70% {
            transform: translateX(8%);
        }
        100% {
            transform: translateX(0);
        }
    }
    @keyframes come-in-right {
        0% {
            transform: translateX(120%);
        }
        70% {
            transform: translateX(-8%);
        }
        100% {
            transform: translateX(0);
        }
    }
    @keyframes come-round {
        0% {
            transform: scale(0);
            opacity: 0;
        }
        40% {
            opacity: 0;
        }
        60% {
            transform: scale(1.2);
        }
        100% {
            transform: scale(1);
        }
    }
</style>
原文地址:https://www.cnblogs.com/8023-CHD/p/14959699.html