1
0
forked from dyf/APP
Files
APP/components/TextToHex/TextToHex.vue
2025-08-07 08:48:02 +08:00

150 lines
3.4 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.

<template>
<view>
<!-- 只创建一个Canvas用于复用 -->
<canvas
type="2d"
canvas-id="reusableCanvas"
:width="currentCanvasWidth"
:height="currentCanvasHeight"
class="offscreen-canvas"
></canvas>
</view>
</template>
<script>
export default {
name: "TextToHex",
props: {
txts: {
type: Array,
default: () => [],
validator: (value) => value.every(item => typeof item === 'string')
},
fontSize: {
type: Number,
default: 16,
validator: (value) => value > 0 && value <= 100
},
bgColor:{
type:String,
default:"#000000"
},
color:{
type:String,
default:"#FFFFFF"
}
},
data() {
return {
// 当前Canvas的宽高动态调整
currentCanvasWidth: 0,
currentCanvasHeight: 0,
// Canvas上下文复用
ctx: null
};
},
computed: {
validTxts() {
return this.txts.filter(line => line.trim() !== '');
}
},
mounted() {
// 初始化Canvas上下文只创建一次
this.ctx = uni.createCanvasContext('reusableCanvas', this);
},
methods: {
/**
* 估算单行文本所需的Canvas宽度
*/
calcLineWidth(textLine) {
return textLine.length * this.fontSize;
},
/**
* 清除Canvas内容
*/
clearCanvas() {
this.ctx.setFillStyle(this.bgColor);
this.ctx.fillRect(0, 0, this.currentCanvasWidth, this.currentCanvasHeight);
},
/**
* 复用单个Canvas处理所有文本行
*/
async drawAndGetPixels() {
if (this.validTxts.length === 0) {
return [];
}
const result = [];
const ctx = this.ctx;
// 循环处理每行文本
for (let i = 0; i < this.validTxts.length; i++) {
const textLine = this.validTxts[i];
// 1. 动态调整Canvas尺寸
this.currentCanvasWidth = this.calcLineWidth(textLine);
this.currentCanvasHeight = this.fontSize;
// 2. 清空Canvas绘制背景
this.clearCanvas();
// 3. 设置文字样式
ctx.setFillStyle(this.color);
ctx.setTextBaseline('middle');
ctx.setFontSize(this.fontSize);
ctx.font = `${this.fontSize}px SimHei, Microsoft YaHei, Arial, sans-serif`;
// 4. 绘制当前行文本
let currentX = 0;
const currentY = this.fontSize / 2;
for (let j = 0; j < textLine.length; j++) {
const char = textLine[j];
ctx.fillText(char, currentX, currentY);
// 按实际字符宽度计算间距
const charWidth = ctx.measureText(char).width;
currentX += charWidth ;
}
// 5. 异步绘制并获取像素数据(串行处理避免冲突)
await new Promise((resolve, reject) => {
ctx.draw(false, () => {
uni.canvasGetImageData({
canvasId: 'reusableCanvas',
x: 0,
y: 0,
width: this.currentCanvasWidth,
height: this.currentCanvasHeight,
success: res => {
result.push({
line: textLine,
pixelData: res.data,
width: this.currentCanvasWidth,
height: this.currentCanvasHeight
});
resolve();
},
fail: err => {
// console.error(`处理第${i+1}行失败:`, err);
reject(err);
}
});
});
});
}
return result;
}
}
};
</script>
<style >
.offscreen-canvas {
position: fixed;
left: -9999px;
top: -9999px;
visibility: hidden;
}
</style>