国庆头像在线工具开发记录

251 阅读4分钟

一直以来,都想要学习制作头像工具。实际上原理都懂,就是上传一张头像作为背景图,然后覆盖一张透明的装饰图,然后生成一下即可,那么原理知道了,就开始制作吧。

先来上效果图:

截屏2022-10-09 下午8.35.22.png

工具地址:www.zngg.net/tool/detail…

1. 开发前的想法

开发这个工具之前,我首先想了一下如果是我第一次开发这个工具我会如何做呢? 按照我当前的知识储备,我会选择使用dom来实现头像效果,之后使用dom-to-image库将dom转换成图片,这样理论上来讲是没有任何问题的,具体方法为:

  1. 创建一个正方形div,设置position为relative。
  2. 这个div内有两个img标签,宽高同父布局宽高相同,第二个img标签position设置为absolute,left为0,top为0,第一个img图片为头像图片,第二个img为装饰图(例如右下角一个小旗的图),这样就简单实现了dom,当然圆角以及白色边框可以细调。
  3. 使用dom-to-image将这个正方形div转换成图片。ok,完成。

个人认为这种方式已经可以实现国庆头像的制作功能,但天下轮子一大抄,虽然已经有了完整的理论体系,但是我仍然忍不住去学习借鉴已有的项目实现方式。

2. 借鉴后

gayhub上看了一些已有的项目实现方案,发现都是基于canvas实现的,但这方面我一窍不通,因此,那就copy一下吧。 已有的项目大多使用fabric这个库,FabricJS是一个简单而强大的 Javascript HTML5 画布库,它也是一个SVG-to-canvas 解析器。简单理解就是封装了canvas的原生API,使得开发更加简单。

3. 开发

  1. 首先创建一个画布canvasFabric:
let canvasFabric = new fabric.Canvas('canvasAvatar', {
        width: 宽度,
        height: 高度,
        backgroundImage: new fabric.Image(document.getElementById("头像img标签的id"), {
            scaleX: 头像宽度和这个画布宽度的比例,
            scaleY: 头像高度和这个画布高度的比例
        })
    });

这一步相当于我自己想法的第一步以及第二步里面的第一个img标签。接下来我们要开始给这个画布上“覆盖”一个装饰图了。 2. 我们创建一个装饰图对象:

    let avatarInstance = new fabric.Image(document.getElementById("装饰图img标签的id"), {
        top: 0,
        left: 0,
        scaleX: 头像宽度和这个装饰图宽度的比例,
        scaleY: 头像高度和这个装饰图高度的比例,
        cornerColor: "#0b3a42",
        cornerStrokeColor: "#fff",
        cornerStyle: "circle",
        transparentCorners: false,
        rotatingPointOffset: 30,
        lockMovementX: true,
        lockMovementY: true,
    });

这里我们实现了一个装饰图的对象,并且增加了一个圆角白边。 3. 接下来我们把这个装饰图对象画到画布里面去:

canvasFabric.add(avatarInstance);

这样,我们制作好的头像图就生成成功了,之后我们要将这个图片保存下来,我们可以将这个画布转换成base64编码的图片。 4. 生成图片

let base64Data = canvasFabric.toDataURL({
      width: 头像宽度,
      height: 头像高度
    });

这个时候base64Data里面就是我们的base64编码的头像了,经过测试,手机上建议新增一个img标签,src为base64Data,然后让用户长按图片进行下载。pc用户呢?虚拟一个a标签dom进行下载即可:

    let hyperlink = document.createElement("a");
    hyperlink.href = resultData;
    hyperlink.download = 'avatar.png';
    if (typeof hyperlink.click === "function") {
        hyperlink.click();
    } else {
        hyperlink.target = "_blank";
        hyperlink.dispatchEvent(new MouseEvent("click", {
            view: window,
            bubbles: true,
            cancelable: true
        }));
    }
    URL.revokeObjectURL(hyperlink.href)

当然具体有很多不重要的细节我省略掉了,但还是要注意的一点是我发现一个巨坑,也有可能是我对fabric还不够了解,就是fabric的版本不要使用最新的5.2.4,最新版5.2.4生成的图片不够清晰,我一直以为是自己其他代码的问题,后来终于发现别人用的版本比较低,于是我也使用了一个之前的版本:2.0.0-rc.3,完美解决生成的图片不够清晰的问题,但实际上我发现可能是原来和现在的版本都有bug,因为使用原来的版本虽然清晰,但是生成的图片大小是设置大小的两倍,不知所以然...

Github: github.com/ZN-GG/ZNGG-…

原文:www.zngg.net/read/post/1…