滴滴首页动画实现

首先我们得看下具体长啥样

这个不是有手就行?

  • 首屏的车流滚动,经过分析,并不是一个video标签,此处应该做了判断,pc端用video,移动端使用图片的解决方案,

其实到这里大概就清楚了,DOM能很清晰的反应这段代码的逻辑。

so,说干就干。

首先你得拥有一段视频

自己准备

视频如何处理?

选择的工具:nodejsffmpegchild_process

  • 如果视频过长,可以选择先把视频截取自己需要的部分

    
    const { spawn } = require('child_process')
    const videoPath = './video/hot-girl.mp4'
    const outPath = './out'
    const segmentTime = 60 

    
    const ffmpeg = spawn('ffmpeg', [
        '-i', videoPath,
        '-c', 'copy',
        '-map', '0',
        '-f', 'segment',
        '-segment_time', segmentTime,
        `${outPath}/out%03d.mp4`
    ]);
    ffmpeg.on('close', (code) => {
    console.log(`child process exited with code ${code}`)
    })
    ffmpeg.stderr.on('data', (data) => {
        console.log(data.toString())
    })


  • 把视频按帧截图,或者按时间截图

    const picVideoPath = './out/out011.mp4'
    const picOutPath = './out/pic'
    const ffmpegArgs = [
        '-i', picVideoPath,
        '-vf', 'thumbnail',
        '-frames:v', '1',
        '-c:v', 'png',
        '-f', 'image2pipe',
        'pipe:1',
        `${picOutPath}/girl%d.png`
      ];
    const ffmpeg = spawn('ffmpeg', ffmpegArgs);

  • 那么问题来了,如果原视频画质较高,那么截图可能会超过你的想象(1M及以上)

如何处理?

imagemin imagemin-jpegtran imagemin-pngquant imagemin-webp 此处可自行选择使用imagemin-webpor imagemin-pngquant,我自己选择的是webp,因为webp的效率超乎你的想象,举个例子:1.5M经过imagemin-pngquant压缩之后再使用imagemin-webp,最后仅剩下区区20K。

const sourcePath = path.resolve("./out/pic");


const targetPath = path.resolve("./images");


 * 读取文件夹下的所有图片列表
 * @param {Function} cb 
 */
const getImagesList = (cb) => {
  fs.readdir(sourcePath, (err, files) => {
    if (!err) {
      return cb(files.map((name) => path.join(sourcePath, name)));
    }

    console.log(err);
  });
};


 * 压缩图片
 * @param {Array} files 
 */
const compress = async (files) => {
  return await imagemin(files, {
    destination: targetPath,
    plugins: [
      imageminJpegtran(),
      
      
      
      imageminWebp({
        quality: 10,
      })
    ],
  });
};

const run = () => {
  getImagesList(async (files) => {
    for (let index = 0; index < files.length; index++) {
      try {
        console.log(`${index+1}/${files.length}`)

        
        await compress([files[index]]);
      } catch (error) {
        console.log(error);
      }
    }
  });
};

run();


前期工作准备完毕,那么就该直接开始操作了!

此处注意,如果你切割出来的图片较多,请搭建一个静态文件服务或者??,不要放到当前项目下,可能会导致打包失败!超过限制

  1. 根据原有思路,那么我们其实只需要去处理一下url就好了,那其实就是

<template>
    <img v-for="i in 1000" :src="`xxxx.com/img${i}.webp`" v-if="activeIndex ===i">
</template>
....
data () {
    return {
        activeIndex:1
    }
}
...

.... 

setInterVal(this.aciveIndex++,100)


但是这个会有什么问题呢?那就是图片加载速度跟不上你切换的速度,那么会咋样?

中间部分图片加载不出来就会导致看起来画面掉帧,卡顿等

_并且,通过v-if控制图片,还会导致资源反复加载,如果有同学挂着睡觉一晚上,明早起来房子没了,车子没了。。。。 _

  • 仔细观察一下滴滴官网,发现他们的并没有出现这种情况? 没有思考出为什么他们的没有这个情况?可能是请求头的原因?还是什么情况? 大家可以帮忙参考一下

这是我设置的返回响应

滴滴的返回值

目前我为了解决这个问题,使用了用js把图片二进制流获取到,再生成base64,这样虽然也会有请求狂刷,但是不会造成额外的流量开销。

const total = 900;
const isLoaded = ref(0);
const images = ref<Array<string>>([]);
async function preloadImages() {
  for (let i = 1; i <= total; i++) {
    const data = await apis.utils.getImages<Blob>(`girl${i}.webp`);
    const url = URL.createObjectURL(new Blob([data],{type: 'image/webp'}));
    images.value[i] = url;
    isLoaded.value++;
    if(isLoaded.value >= 50) {
      changeActive();
    }
  }
}

(async () => {
  await preloadImages();
})();

const imageUrl = computed(() => {
  return images.value[active.value]
});
....
<template>
      <img :src="imageUrl" />
</template>


预览地址

v4.lvzy.xyz:18888/login

用手机端打开更好~

pc的加载没有做处理,可能会白屏一段时间~

2023-4-3更新

已修复请求刷新的问题。

可以访问地址测试,首屏未作加载动画,已跟滴滴动画一样,不会狂刷请求了。。

期间尝试过很多办法,去处理这个问题

  • ~通过map存储jsx,有这个url就去取值~

  • ~通过map存储Image~

  • ~通过隐藏dom节点,查找对应img,再克隆~

  • ~base64~

  • 通过map存储Image对象,找到图片容器夫父节点,appendClild或者replaceChild处理

通过最后一种方式以解决~

完美撒花~

大家可以自行查看network,试试效果~

Ikun专属源码链接[gitlab](src/components/images-video/index.tsx · master · Administrator / vue2.7\_vite\_ts · GitLab (lvzy.xyz))

更新

关于为什么要用图片,而不是video。或许有了一个答案

  • 浏览器本土化

可能很多同学还不知道什么是本土化。 本土化的概念就是让你的浏览器能对你想要的操作进行预测,并添加到浏览器上。so,现在安卓上的各家浏览器百花齐放。比如: 检测到video标签,并且可播放的时候,直接强制给你添加浏览器厂商提供的控件,包括但不限于:投屏、全屏、下载、浏览器统一的控制条。so

  • 有了以上概念,那么就可以知道在首页放一个video会变成啥样了。为了避免“被本土化”,选了图片强缓存.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Web面试那些事儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值