这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
介绍
最近的工作是开发一套后台系统的时候,用户头像碎掉了,我很开心,终于可以有用js生成头像的机会了,本期就会把大致如何绘制一个头像的核心功能完成,至于一些条件判断后期可自行扩展。
另外,我本期会用vite+petite-vue+scss完成一个案例,它类似钉钉的消息页面,如下:
正文
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()
我们渲染这个列表,当有头像时就用原来的头像,如果没有我们就用刚才的头像生成器根据昵称生成一个出来,当然在之前先要进行一步实例化才行。总体来说,是非常方便实用的。
结语
我们依然可以在此基础上根据自己的业务去扩展,比如验证数字,英文如何处理,或者验证姓氏分配颜色等等,没有过多需求的,大家也可以直接粘贴第一部分的源码去使用。