Files
nl-game/src/components/PixelAvatar.vue
李琦 cd1ab90013 初始化
需要注意的是饥荒不够完善:动作、手持工具、细节交互、系统逻辑
2026-08-15 07:24:34 +08:00

69 lines
2.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 像素头像渲染组件:把 'px:NN' 编码画成像素图8×8 网格放大,锐利无插值)
// 兼容旧 emoji 数据:非像素编码时原样以文字显示,历史用户零迁移
<script setup>
import { computed } from 'vue'
import { AVATAR_SHAPES, AVATAR_PALETTES, decodePixelAvatar } from '../games/pixelAvatars'
const props = defineProps({
// 头像值:'px:NN' 像素编码 或 旧 emoji 字符
code: { type: String, default: '' },
// 渲染尺寸px
size: { type: Number, default: 32 },
})
const px = computed(() => decodePixelAvatar(props.code))
// dataURL 缓存:同 code+size 只画一次(组件实例间不共享,同一实例多次渲染直接命中)
const cache = new Map()
function dataUrl(size) {
const key = props.code + '@' + size
if (cache.has(key)) return cache.get(key)
const p = px.value
if (!p) return ''
const shape = AVATAR_SHAPES[p.shape]
const pal = AVATAR_PALETTES[p.palette]
const cell = Math.max(1, Math.round(size / 8))
const real = cell * 8
const cv = document.createElement('canvas')
cv.width = real
cv.height = real
const ctx = cv.getContext('2d')
const colors = { 1: pal.c1, 2: pal.c2, 3: pal.c3, 4: '#ffffff', 5: '#1a1a24' }
shape.forEach((row, y) => {
for (let x = 0; x < 8; x++) {
const ch = row[x]
if (ch === '.') continue
ctx.fillStyle = colors[ch] || colors[1]
ctx.fillRect(x * cell, y * cell, cell, cell)
}
})
const url = cv.toDataURL()
cache.set(key, url)
return url
}
</script>
<template>
<span class="px-avatar" :style="{ width: size + 'px', height: size + 'px', fontSize: Math.round(size * 0.6) + 'px' }">
<img v-if="px" :src="dataUrl(size)" :width="size" :height="size" alt="" class="px-img" />
<template v-else>{{ code || '🎮' }}</template>
</span>
</template>
<style scoped>
.px-avatar {
display: inline-flex;
align-items: center;
justify-content: center;
overflow: hidden;
line-height: 1;
flex-shrink: 0;
}
.px-img {
display: block;
width: 100%;
height: 100%;
image-rendering: pixelated; /* 像素图放大不模糊 */
}
</style>