鸽了这么久,一晃2个月过去了。自考+上班没时间记录。
前不久看到移动官网上的时间轴效果,看起来不错,我也来试着做一下。
需要元素滚动到视野内加载动画。
插件地址 https://ext.dcloud.net.cn/plugin?id=906
uniapp不能操作dom,写这个还是思考了很久。效果如下
一、布局
画主轴。内容分割成块,当出现在视野中(滚动监听),加载载入动画。
内容块中分别有一个圆点、详情内容。
<!-- 时间轴 css就不贴出来了--> <view class="time-line-container" :class="addTypeClass"> <!-- 时间轴内容块列表 --> <view class="time-line-list"> <!-- 时间轴内容块 绑定id值--> <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]&¤t[index].is=='ok'?1:0,top:'50px'}" :class="current[index]&¤t[index].is=='ok'?comeani:''"></view> <!-- 内容 --> <view class="info-content-wrap" :style="{ opacity: current[index]&¤t[index].is=='ok'?1:0}" :class="current[index]&¤t[index].is=='ok'?comeani:''"> <!-- 标题 --> <view class="info-title"> {{item.title}}<span>{{item.title_span}}</span> </view> <!-- 内容 --> <view class="info-content"> <!-- 内容 --> <view class="info-txt">{{item.content}}</view> </view> </view> </view> </view> </view> </view>
二、js
首次进入页面,需获取屏幕高度,初始化一个current,开始获取每个元素的位置信息。
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 } },
循环一下所有的元素并获取每个元素的位置信息,得到后加入数组
async getScroll(){ if(!this.isScroll){return;} let info=[]; // 返回位置信息加入数组 等待获取完成再进行loadani操作 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(); }); },
获取到距离顶部的距离就可以判断是否出现在视野内,并把标志位设置为相应状态
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;} },
在主界面,还要监听每次的滚动,看元素是否滚动到视野内了
组件引入:
<time-line ref="timeline" location="center" title="我的时间轴"></time-line>
onPageScroll() { this.$refs.timeline.getScroll(); },
这样就完成了,写的有点繁琐哈哈。省略部分内容,可以看完整示例。
附上GitHub地址: https://github.com/steffenx/timeLine-uniapp.git