【龙珠专场】用js仿制钉钉头像生成器,我们拒绝996!

2,129 阅读3分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

介绍

最近的工作是开发一套后台系统的时候,用户头像碎掉了,我很开心,终于可以有用js生成头像的机会了,本期就会把大致如何绘制一个头像的核心功能完成,至于一些条件判断后期可自行扩展。

另外,我本期会用vite+petite-vue+scss完成一个案例,它类似钉钉的消息页面,如下:

VID_20211101_212319.gif

正文

1.制作

我先想生成头像应该用到的是画布,然后获取到名字,可以设置字体大小,图片尺寸和背景色,生成图片。对,生成一个基础的头像就是这样。

/* Avatar.js */
class Avator {
    constructor(args) {
        this.nickname = "用户";       // 名字
        this.fontSize = 32;          // 字体大小
        this.size = 100;             // 画布大小
        this.colors = ["#1e80ff"];   // 背景色
        this.fontWeight = "normal";  // 文字粗细
        Object.assign(this, args)
        this.canvas = null;          // 画布
        this.ctx = null;             // 环境
        this.init();
        return this;
    }
    init() {
        // 初始化
        this.canvas = document.createElement("canvas")
        this.canvas.width = this.size;
        this.canvas.height = this.size;
        this.ctx = this.canvas.getContext('2d');
        return this;
    }
    create(name, color) {
        // 生成头像
        const { ctx, canvas, fontWeight, fontSize, colors, nickname, size } = this;
        let _name = (name || nickname) + "";
        switch (_name.length) {
            case 1:
            case 2:
                break;
            default:
                _name = _name.substring(_name.length - 2, _name.length)
                break;
        }

        let _color = color || colors[~~(colors.length * Math.random())]
        ctx.clearRect(0,0,size,size)
        ctx.fillStyle = _color;
        ctx.fillRect(0, 0, size, size);
        ctx.fillStyle = '#FFFFFF';
        ctx.font = `${fontWeight} ${fontSize}px serif`;
        ctx.textAlign = 'center';
        ctx.textBaseline = "middle";
        ctx.fillText(_name, size / 2, size / 2);
        return canvas.toDataURL("image/jpeg");
    }
}
export default Avator;
  • 初始化我们不做赘述,我们期望的实例化一次后,可以反复使用实例去根据传入姓名生成头像,所以多数情况,从外界传入的基本都是姓名,最多会改变颜色。所以我们只接受这两个参数,如果没传则使用默认昵称和颜色。
  • 我们处理姓名的时候,一般只取后面两个字作为内容,所以我们用switch...case去判断字符串长度,让他获取到期望的内容。另外,颜色也是,本身是一个数组,只是目前数组里就有一个色值,我们如果后期想随机生成更多颜色,也可以注入更多色值在里面。
  • 接下来,就是画布基本功了,先清空下画布,然后绘制背景色,再设置字体样式去绘制,当然我们要绘制到屏幕中央,故要传入宽高都要等于画布宽高的一半,因为上面设置了textAlign和textBaseline都是居中,这样操作就能保证字体从中间显示,不论长度。
  • 最后,通过画布导出jpeg图片。

2.使用

上面说了我们本次将使用petite-vue来编写,废话不多说,直接上代码吧。

<div @mounted="mounted">
    <ul class="chat-list">
        <li v-for="(item,index) in list" :key="index">
            <img :src="item.avatar" alt="" srcset="">
            <div>
                <h5>{{item.nickname}}<span>{{item.date}}</span></h5>
                <p>{{item.chat}}<span>{{item.num}}</span></p>
            </div>
        </li>
    </ul>
</div>

petite-vue书写起来和vue大致相同,一眼就明白。

import "./style.scss"
import Avatar from "./tools/Avatar"
import { createApp } from 'https://unpkg.com/petite-vue?module'

createApp({
    list: [{
        avatar:"./assets/avatar/sadan.jpg",
        nickname: "撒旦",
        chat: "疯狂内卷中~~",
        num: 99,
        date: "22:30"
    },{
        nickname: "贝吉塔",
        chat: "我拒绝996!!",
        num: 4,
        date: "15:30"
    },
    // ...
    ],
    mounted() {
        const avatar = new Avatar();
        this.list = this.list.map(item => {
            item.avatar = item.avatar || avatar.create(item.nickname)
            return item;
        })
    }
}).mount()

我们渲染这个列表,当有头像时就用原来的头像,如果没有我们就用刚才的头像生成器根据昵称生成一个出来,当然在之前先要进行一步实例化才行。总体来说,是非常方便实用的。

微信截图_20211101220959.png

结语

我们依然可以在此基础上根据自己的业务去扩展,比如验证数字,英文如何处理,或者验证姓氏分配颜色等等,没有过多需求的,大家也可以直接粘贴第一部分的源码去使用。