202 lines
3.6 KiB
Plaintext
202 lines
3.6 KiB
Plaintext
<template>
|
|
<slot></slot>
|
|
<img />
|
|
</template>
|
|
|
|
<style lang="scss">
|
|
:host {
|
|
overflow: hidden;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: var(--size, 32px);
|
|
height: var(--size, 32px);
|
|
line-height: 1;
|
|
font-size: var(--size, 32px);
|
|
border-radius: 4px;
|
|
color: #fff;
|
|
user-select: none;
|
|
-moz-user-select: none;
|
|
|
|
img {
|
|
display: none;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
slot {
|
|
display: block;
|
|
transform: scale(0.8);
|
|
}
|
|
}
|
|
|
|
:host([src]),
|
|
:host([hash]) {
|
|
slot {
|
|
display: none;
|
|
}
|
|
img {
|
|
display: block;
|
|
}
|
|
}
|
|
|
|
:host([color='red']) {
|
|
background: #ff5061;
|
|
}
|
|
:host([color='teal']) {
|
|
background: #3fc2a7;
|
|
}
|
|
:host([color='purple']) {
|
|
background: #ac61ce;
|
|
}
|
|
:host([color='green']) {
|
|
background: #58d68d;
|
|
}
|
|
:host([color='orange']) {
|
|
background: #ffb618;
|
|
}
|
|
:host([color='dark']) {
|
|
background: #62778d;
|
|
}
|
|
:host([color='blue']) {
|
|
background: #66b1ff;
|
|
}
|
|
|
|
:host([size='large']) {
|
|
width: 50px;
|
|
height: 50px;
|
|
font-size: 36px;
|
|
}
|
|
|
|
:host([size='medium']) {
|
|
width: 40px;
|
|
height: 40px;
|
|
font-size: 28px;
|
|
}
|
|
|
|
:host([size='mini']) {
|
|
width: 24px;
|
|
height: 24px;
|
|
font-size: 16px;
|
|
}
|
|
|
|
:host([circle]) {
|
|
border-radius: 50%;
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
const COLORS = [
|
|
'#3fc2a7', //teal
|
|
'#58d68d', //green
|
|
'#ac61ce', // purple
|
|
'#66b1ff', //blue
|
|
'#ff5061', //red
|
|
'#ffb618', // orange
|
|
'#62778d' //dark
|
|
]
|
|
const COLOR_NAME = ['teal', 'green', 'purple', 'blue', 'red', 'orange', 'dark']
|
|
var canvas = document.createElement('canvas')
|
|
var ctx = canvas.getContext('2d')
|
|
var size = 500
|
|
canvas.width = size
|
|
canvas.height = size
|
|
|
|
function sum(arr) {
|
|
var n = 0
|
|
arr.forEach(a => (n += a))
|
|
return n
|
|
}
|
|
|
|
function createImage(hash) {
|
|
if (!hash) {
|
|
return './def.jpg'
|
|
}
|
|
|
|
var bg = COLORS[parseInt(hash.slice(-1), 16) % 7]
|
|
var color = '#fff'
|
|
var fixColor = color
|
|
var lens = hash.slice(0, 8).split('')
|
|
var pos1 = hash.slice(8, 16).split('')
|
|
var pos2 = hash.slice(16, 24).split('')
|
|
var step = size / 10
|
|
|
|
lens = lens.map(c => {
|
|
c = parseInt(c, 16)
|
|
return c % 8
|
|
})
|
|
pos1 = pos1.map(c => {
|
|
c = parseInt(c, 16)
|
|
return c % 4
|
|
})
|
|
pos2 = pos2.map(c => {
|
|
c = parseInt(c, 16)
|
|
return c % 4
|
|
})
|
|
|
|
fixColor = sum(lens) > 32 ? bg : color
|
|
|
|
ctx.fillStyle = bg
|
|
ctx.fillRect(0, 0, size, size)
|
|
|
|
for (var i = 1; i < 9; i++) {
|
|
var xl = lens[i - 1]
|
|
var xp1 = pos1[i - 1]
|
|
var xp2 = pos2[i - 1]
|
|
|
|
if (xl + xp1 > 8) {
|
|
xl = 8 - xp1
|
|
}
|
|
ctx.fillStyle = color
|
|
ctx.fillRect((xp1 + 1) * step, i * step, xl * step, step)
|
|
|
|
ctx.fillStyle = color
|
|
ctx.fillRect((9 - xp1 - xl) * step, i * step, xl * step, step)
|
|
|
|
ctx.fillStyle = fixColor
|
|
ctx.fillRect((xp2 + 1) * step, i * step, step, step)
|
|
|
|
ctx.fillStyle = fixColor
|
|
ctx.fillRect((8 - xp2) * step, i * step, step, step)
|
|
}
|
|
|
|
return canvas.toDataURL('image/webp')
|
|
}
|
|
export default class Avatar {
|
|
props = {
|
|
hash: '', //哈希头像
|
|
src: '', // 地址头像
|
|
fit: '' // 头像填充方式 fill, contain, cover, scale-down
|
|
}
|
|
|
|
constructor() {
|
|
/* render */
|
|
this.__IMG__ = this.root.lastElementChild
|
|
var text = this.textContent.slice(0, 1)
|
|
this.setAttribute('color', COLOR_NAME[text.charCodeAt(0) % 7])
|
|
this.textContent = text
|
|
}
|
|
|
|
watch(name, old, val) {
|
|
if (old === val) {
|
|
return
|
|
}
|
|
switch (name) {
|
|
case 'src':
|
|
this.removeAttribute('hash')
|
|
this.__IMG__.src = val || './def.jpg'
|
|
break
|
|
case 'hash':
|
|
this.removeAttribute('src')
|
|
this.__IMG__.src = createImage(val)
|
|
break
|
|
|
|
case 'fit':
|
|
if (val) {
|
|
this.__IMG__.style['object-fit'] = val
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
</script>
|
JavaScript
95.2%
CSS
4.8%