关于PAG在vue2中的简单应用

1,292 阅读2分钟

导言

苦恼于前端动画不够复杂,老大去b站逛了下,找了好几个动画解决方案,有svg和pag以及其他什么来着,一眼就看中了PAG,因为三个字母很短,也有腾讯背书,想必会好使一点吧?蛮记录一下,有刚好看到本文章并且有意见的老哥希望可以留言让我改进一下。

一.什么是PAG

PAG是一套完整的动效工作流解决方案,目标是降低或消除动效相关的研发成本,能够一键将设计师在AE中制作的动效内容导出成素材文件,并快速上线应用于几平所有的主流平台。

关于PAG在掘金已经有很多文章说明了,其中包括优缺点以及框架源码等。这边简单记录一下第一次使用PAG的流程

二.使用

安装libpag插件

npm i libpag

vue2.xx安装rollup-plugin-copy插件并配置(已经安装的可以省略)

npm i rollup-plugin-copy

然后在build的webpack.dev.conf配置

   ...
  plugins: [
   ...
    // copy custom static assets
    new CopyWebpackPlugin([
      ...
      {
        from: path.resolve(__dirname, '../node_modules/libpag/lib/libpag.wasm'),
        to: config.build.assetsPublicPath,
      }

    ])
  ]
  ...

然后在build的webpack.prod.conf配置

...
plugins:[
...
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../node_modules/libpag/lib/libpag.wasm'),
        to: config.build.assetsSubDirectory,
      },
    ])

]

vue3.xx rollup-plugin-copy的配置

const path = require('path');
const config = require('./config');
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
  configureWebpack: {
    entry: {
      app: './src/main.js',
    },
    output: {
      path: config.build.assetsRoot,
      filename: '[name].js',
    },
    plugins: [
      new CopyWebpackPlugin([
        {
          from: path.resolve(__dirname, './node_modules/libpag/lib/libpag.wasm'),
          to: config.build.assetsPublicPath,
        },
      ]),
    ],
  },
  publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
};

使用前封装一下

import { PAGInit } from 'libpag'
// pag文件(支持本地相对路径), canvas 的id名,播放次数
 const initPag2 = async (url, id, num=0) => {
  PAGInit().then((PAG) => {
    fetch(url)
      .then((response) => response.blob())
      .then(async (blob) => {
        const file = new window.File([blob], url.replace(/(.*\/)*([^.]+)/i, '$2'));
        const pagFile = await PAG.PAGFile.load(file);
        document.getElementById(id).width = pagFile.width();
        document.getElementById(id).height = pagFile.height();
        const pagView = await PAG.PAGView.init(pagFile,`#${id}`);
        //循环次数
        pagView.setRepeatCount(num);
        await pagView.play();
      });
  });
}
export default initPag2

使用封装的方法:这里的url似乎不能填写相对路径,填写网络路径是没问题的,比如pag.art/file/like.p…

<template>
  <div id="container">
    <canvas class="canvas" id="pag"></canvas>
  </div>
</template>

<script>
import initPag from '@/utils/pagInit.js'
export default {
  name: "pagTest",
  mounted() {
    initPag('./static/testHtml/test1.pag', 'pag')
  },
  methods: {
  },
};
</script>


<style scoped>
#container {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
</style>

也可以在index.html直接引入,无需其他配置

<script src="https://cdn.jsdelivr.net/npm/libpag@latest/lib/libpag.min.js"></script>

然后封装一下

export const initPag = async (url, id, num=0) => {
  // 实例化 PAG
  const PAG = await window.libpag.PAGInit()
  // 获取 PAG 素材数据
  // https://pag.art/file/like.pag
  const buffer = await fetch(url).then((response) => {
    console.log(response);
    return response.arrayBuffer()
  }
  )
  // 加载 PAG 素材为 PAGFile 对象
  const pagFile = await PAG.PAGFile.load(buffer)
  // 将画布尺寸设置为 PAGFile的尺寸
  const canvas = document.getElementById(id)
  canvas.width = pagFile.width()
  canvas.height = pagFile.height()
  // 实例化 PAGView 对象
  const pagView = await PAG.PAGView.init(pagFile, canvas)
  // 循环播放
  pagView.setRepeatCount(num)
  await pagView.play()
}