常见问题
点赞 (帧动画)
-
前言,需求要一个点赞动画 ,给了我48张 帧图
-
初试: 使用 图片src 循环切换地址 来 ,很卡顿,完全不能达到 UI 的要求
-
再试 小程序 canvas 支持 Canvas.requestAnimationFrame,来做帧动画,发现taro 1.3这个版本 获取 对象 为空 然后继续放弃
-
再试: 使用css 动画来实现,也是最终方案
.icon-like{
width:192px;height:192px;
background: url('https://pubimg.xingren.com/969e96c6-baf7-4fea-8081-72980a24e00a.png') no-repeat; //总共16张小图,每个图的大小是192*192
background-position: 0 0;
transform: scale(0.65);
}
.animation{
animation:heart-animated 0.64s 1 steps(15); //这里的steps,15的值是总共16图-1=15,是步长,因为初始就是第一张,所以这里是15
animation-fill-mode: forwards; //动画完成后,保持最后一个属性值 ,backwards初始
}
@keyframes heart-animated {
0%{background-position: left;}
100%{background-position: right;}
}
<View className="item" onClick={this.funLike}>
{curr.userPraised === 1? <View className="item-animation-like"><View className="icon-like my-heart-animation"></View> </View>:''}
<Image className="item-pic" src={pics.defLike} style={{display:curr && curr.userPraised === 1?'none':'inline-block'}}></Image>
<View className="text">{curr.viewNumber}</View>
</View>
loading ~
.icon-loading {
width: 112px;
height: 112px;
background: url('https://pubimg.xingren.com/8a52462a-67a3-4b9b-85ee-9de51036d4d7.png');
//总共16张小图,每个图的大小是60*100 所以width: 60px;height: 100px;
background-size: auto 100%;
// transform: scale(0.5);
}
.loading-animation {
animation: loading-animated 1.72s steps(43, end) infinite; //这里的steps,15的值是总共16图-1=15,是步长,因为初始就是第一张,所以这里是15
}
@keyframes loading-animated {
0% {
background-position: 0 0;
}
100% {
background-position: -4300% 0;
}
}
图片切换为视频后有 按钮闪烁一下
解决方法 :主要是先播放 再隐藏(第一次)
setTimeout(()=>{
this.videoContext.play();
setTimeout(()=>{
this.setData({
showCover:false
});
},0.1*1000)
},1*1000)
资源预加载
在使用前进行预加载 进行 处理
在插件中进行页面处理
可视范围 按照流播放
- 这里 不做代码 讲一下思路
- (利用 Promise)(也可以 在单个视频中 使用 setTimeOut 来处理,但是缺点是 不能按顺序,销毁也不好控制,不推荐)
- 得到 需要view 的高度合集
- 循环 执行 集合中的展示
- 注意: 在执行前需要传入 当前时间戳 ,来处理之前执行的代码,是否 继续执行(目的:按顺序流执行,之前未执行完的直接销毁)
const $t = this;
const playList: PlayList[] = [];
const { windowHeight } = await Taro.getSystemInfoSync();
const {networkType} = await new Promise(resolve => {
Taro.getNetworkType({
complete: function(res) {
// @ts-ignore
resolve(res);
},
});
});
if(networkType !== 'wifi') return;//非wifi 不做切换处理
const getPlayIds = async (timeRun: number) => {
playList.length = 0;
const query = Taro.createSelectorQuery().in($t.$scope);
// 创建节点查询器 query
query.selectAll('.video-card').boundingClientRect();
query.selectViewport().scrollOffset();
let [list, { scrollHeight }] = await new Promise(resolve => {
query.exec((res) => {
resolve(res);
});
});
if (scrollHeight === 0) scrollHeight = scrollHeight;
list = list.sort((a, b) => a.top - b.top);
list.forEach(c => {
const { top, bottom, dataset } = c;
const { id, time } = dataset;
if (top >= 0 && bottom < (windowHeight)) {
playList.push({ id: id, time: time });
}
});
// 在主线程中进行控制
const playFun = async ()=>{
if(timeRun !== $t.time) return;
const funChange = async (obj)=>{
const { time, id } = obj;
await new Promise(resolve => {
setTimeout(()=>{
setTimeout(()=>{eventBus.$emit('video-status', { id, play:true, time });}, 0);
resolve();
}, 300);
});//开始展示
await new Promise(resolve => {
setTimeout(()=>{
resolve();
}, time*1000+300);
});//结束暂时
};
for(let i=0, len = playList.length;i<len;i++){
if(timeRun === $t.time) await funChange(playList[i]);;
}
if(timeRun === $t.time) await playFun();
};
if(playList.length >0){
playFun();
}else{
eventBus.$emit('video-status', { id:'', play:false });
}
};
eventBus.$on('nextTick', () => {
setTimeout(() => {
$t.time = new Date().getTime();
getPlayIds($t.time);
}, 300);
});
// 监听滚动 滚动停止后进行处理 位置进行播放
let now_scrollTop = 0;
eventBus.$on('onScroll', function (data) {
const { scrollTop } = data;
now_scrollTop = scrollTop;
const c = setTimeout(() => {
if (now_scrollTop === scrollTop) {
$t.time = new Date().getTime();
getPlayIds($t.time);
}
clearTimeout(c);
}, 500);
});