有点意思的gif动图生成平台开发实战(二)

时间:2021-1-8 作者:admin

前言

笔者之前利于业余时间开发了一个gif动图生成平台, 具体开发背景我也在上一篇文章手把手教你撸一个能生成抖音风格动图的gif制作平台中介绍过了, 我们今天继续来实现该平台, gif动图平台的实现方式比较将完全用前端的手段来实现, 所以大家在接下来的内容中会发现很多有意思的前端插件. 接下来我们看看主要要实现的功能点:

  • 纯前端实现图片上传和预览
  • 基于react-beautiful-dnd实现元素自由拖动排序
  • 使用javascript实现生成uuid的函数
  • 使用file-saver实现前端下载文件
  • 使用gif.js实现基于图片生成gif动图
  • 控制gif动图播放速度的方法

正文

还是按照笔者一贯的风格, 在实现功能之前我们先看看实现后的预览效果:

gif动图生成平台

1. 基本页面搭建

在开始之前我们先要理清基本的页面结构, 笔者划分为如下结构:

2. 实现图片上传预览功能

对于第一步骤的界面我想大家都能实现, 我们现在具体一步步落实到功能实现. 我们先来实现一下图片的上传预览. 由于我们这里没有借助服务器, 完全由前端的方式实现图片预览, 所以我们需要用到FileReader对象.

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。

其中File对象可以是来自用户在一个input元素上选择文件后返回的FileList对象,也可以来自拖放操作生成的DataTransfer对象,还可以是来自在一个HTMLCanvasElement上执行mozGetAsFile()方法后返回结果。 接下来我们看看如何利用antdUpload组件和FileReader实现图片预览, 具体代码如下:

const uploadprops = useMemo(() => ({
    name: 'file',
    multiple: true,
    listType:"picture-card",
    onPreview: () => {},
    showUploadList: false,
    beforeUpload(file, fileList) {
      // 解析并提取excel数据
      let reader = new FileReader();
      reader.onload = function(e) {
        let url = e.target.result;
        setImageList(prev => [...prev, {id: uuid(6, 16), url}])
      };
      reader.readAsDataURL(file);
    }
  }), []);

uploadprops即为Upload组件需要的属性配置, 通过代码我们可以知道, 我们在beforeUpload阶段拦截了图片, 通过FileReader对象的readAsDataURL API将读取到的文件转化为base64的地址, 这样我们就能通过如下方式展示图片了:

<img src={item.url} id={item.id} alt=""/>

在代码中我们将图片数据存储到一个对象里, 对象包括由uuid函数生成的唯一idurl组成, 至于为何生成唯一id, 这里笔者将在下文中介绍.

3. 使用react-beautiful-dnd实现元素自由拖动排序

大家在研究过H5-Dooring | 一款强大的开源H5编辑器 后就会发现react-dnd这个模块很熟悉, 因为该开源编辑器就使用了react-dnd实现的组件拖拽和组件数据传递的. 笔者在社区又发现了一个比较有意思的拖拽库react-beautiful-dnd, 同样可以实现优雅平滑的智能拖拽效果, 基本案例如下:

const imgList = [
    {
        id: uuid(6, 10),
        url: '图片的base64位地址'
    }
]

为了限制图片上传过大, 我们还可以在Upload组件的beforeUpload阶段限制图片上传大小, 这个根据使用而定. uuid的实现方式很多, 笔者这里送上一个实现方式:

// 生成uuid
function uuid(len: number, radix: number) {
  let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
  let uuid = [],
    i;
  radix = radix || chars.length;

  if (len) {
    for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
  } else {
    let r;
    uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
    uuid[14] = '4';

    for (i = 0; i < 36; i++) {
      if (!uuid[i]) {
        r = 0 | (Math.random() * 16);
        uuid[i] = chars[i === 19 ? (r & 0x3) | 0x8 : r];
      }
    }
  }

  return uuid.join('');
}

实现后的效果如下图:

4. 控制gif动图播放速度的方法

控制gif的播放速度方法我们可以用slider组件实现, gif.js也提供速度的接口, 我们只需要实现速度值的计算即可. 我们都知道滑块滑动越长, 数值越大, 与之对应的 速度越大, 时间间隔越小, 所以我们在前端层设计的展示效果如下:

具体代码如下:

const handleSpeed = (v) => {
  let realSpeed = (20 - v + 1) / 10;
  setSpeed(realSpeed)
}

当然大家可以用更简单的方式来实现, slider组件也提供反向取值的操作.

5. 基于图片序列生成gif动图

基于图片序列生成gif的方式也很简单, 我们通过批量获取图片拖动区的图片, 组装成数组传给gif.js即可. 我们直接看效果:

6. 使用file-saver实现前端下载文件

我们只需要把生成的gif图片, 传递给file-saver模块中, 使用其提供的API即可下载文件, 这里在之前文章笔者也介绍过了, 这里直接上代码:

import { saveAs } from 'file-saver';

// resultImage为gif生成的gif图片对象
saveAs(resultImage, `${uuid(6, 10)}.gif`);

最后

如果想学习更多H5游戏, webpacknodegulpcss3javascriptnodeJScanvas数据可视化等前端知识和实战,欢迎在《趣谈前端》一起学习讨论,共同探索前端的边界。

更多推荐

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。