随笔 - 73,  文章 - 0,  评论 - 6,  阅读 - 91824

前言

  通常情况端上做刷礼物动画时,需要播放背景透明的礼物特效动画,这种情况map4相对其他json/webgl/gif/svga等等格式的动画来说体积往往更小且像素会更清晰,更能打动大哥们得打赏~,端上一般引用QGVAPlayer插件播放,而h5需要引入video-animation-player

 

  直接上代码

  第一步:

cnpm i video-animation-player 

 

  第二步:

复制代码
<template>
  <van-image ref="vedioRef" :src="urlImg" class="mp4-transparent-vedio" />
</template>

<script lang='ts' setup>
import { ref, nextTick } from 'vue'
import Vap from 'video-animation-player'

const show = ref<boolean>(false)
const vedioRef = ref()
const url = ref<string>('')
const urlImg = ref<string>('')
const vapPlayer = ref()

const playVideo = (animation:string = '', animationUrl:string = '', json:string = '', fps:number = 30) => {
  url.value = animation
  urlImg.value = animationUrl
  show.value = true

  nextTick(() => {
    vapPlayer.value = new Vap({
      container: vedioRef.value, // 要渲染的载体,dom元素
      src: url.value, // vap动画地址
      config: json, // 播放vap动画需要的 json文件。必填
      width: window.innerWidth, // 容器宽度
      height: window.innerHeight, // 容器高度
      fps, // 帧数,json文件中有这个视频的帧数的,可以看一下,
      mute: true, // 静音
      type: 2, // 组件基于type字段做了实例化缓存,不同的VAP实例应该使用不同的type值(如0、1、2等)
      loop: false, // 循环
      precache: false, // 预加载视频,下载完再播。小动画建议边下边播,大动画还是先下后播吧,因为太大了或者网络不好,会一卡一卡的。
      beginPoint: 0, // 起始播放时间点(单位秒),在一些浏览器中可能无效
      accurate: true, // 是否启用精准模式(使用requestVideoFrameCallback提升融合效果,浏览器不兼容时自动降级)
    })

    vapPlayer.value.play() // 开始播放
    vapPlayer.value.on("ended", () => {
      // 监听播放完成的事件
      closeVedio()
    })
  })
}

const closeVedio = () => {
  vapPlayer.value.destroy()
  vapPlayer.value = null
  show.value = false
}

defineExpose({
  playVideo,
  closeVedio,
});
</script>

<style scoped lang="scss">
.mp4-transparent-vedio {
  width: 100vw;
  height: 100vh;
}
</style>
复制代码

 

上面那种方式需要nodejs起本地服务,如果要本地直接利用html播放(flutter中也是将html和对应的js放入并启动即可),则需要自己解析mp4中的json并播放

复制代码
// JSON配置解析器
    const VapConfigParser = async (file) => {
      const buffer = await file.slice(0, 1024 * 1024).arrayBuffer();
      const uint8 = new Uint8Array(buffer);

      // 查找配置起始标记 {"info":
      const startMark = [0x7B, 0x22, 0x69, 0x6E, 0x66, 0x6F, 0x22, 0x3A];
      let startIndex = -1;

      for (let i = 0; i < uint8.length - startMark.length; i++) {
        if (startMark.every((v, j) => uint8[i + j] === v)) {
          startIndex = i;
          break;
        }
      }

      if (startIndex === -1) throw new Error('未找到JSON配置');

      // 解析完整JSON结构
      let braceCount = 0;
      let inString = false;
      let endIndex = startIndex;

      for (let i = startIndex; i < uint8.length; i++) {
        const char = String.fromCharCode(uint8[i]);

        if (char === '"' && (i === 0 || uint8[i - 1] !== 0x5C)) {
          inString = !inString;
        }

        if (!inString) {
          if (char === '{') braceCount++;
          if (char === '}') {
            braceCount--;
            if (braceCount === 0) {
              endIndex = i;
              break;
            }
          }
        }
      }

      const jsonStr = new TextDecoder().decode(uint8.slice(startIndex, endIndex + 1))
      return JSON.parse(jsonStr)
    }
复制代码

 

完整demo:https://github.com/zengxudong-bit/vap

posted on   Tom最好的朋友是Jerry  阅读(97)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示