75 行
2.9 KiB
JavaScript
75 行
2.9 KiB
JavaScript
// pwuniapp/common/barcode.js
|
|
// 轻量级原生 Code128 条形码编码与图形数据生成器 (零第三方依赖,跨端兼容小程序与H5)
|
|
|
|
const CODE128_PATTERNS = [
|
|
'212222', '222122', '222221', '121223', '121322', '131222', '122213', '122312', '132212', '221213', // 0-9
|
|
'221312', '231212', '112232', '122132', '122231', '113222', '123122', '123221', '223211', '221132', // 10-19
|
|
'221231', '213212', '223112', '312131', '311222', '321122', '321221', '312212', '322112', '322211', // 20-29
|
|
'212123', '212321', '232121', '111323', '131123', '131321', '112313', '132113', '132311', '211313', // 30-39
|
|
'231113', '231311', '112133', '112331', '132131', '113123', '113321', '133121', '313121', '211331', // 40-49
|
|
'231131', '213113', '213311', '213131', '311123', '311321', '331121', '312113', '312311', '332111', // 50-59
|
|
'314111', '221411', '431111', '111224', '111422', '121124', '121421', '141122', '141221', '112214', // 60-69
|
|
'112412', '122114', '122411', '142112', '142211', '241211', '221114', '413111', '241112', '134111', // 70-79
|
|
'111242', '121142', '121241', '114212', '124112', '124211', '411212', '421112', '421211', '212141', // 80-89
|
|
'214121', '412121', '111143', '111341', '131141', '114113', '114311', '411113', '411311', '113141', // 90-99
|
|
'114131', '311141', '411131', '211412', '211214', '211232', '2331112' // 100-106
|
|
];
|
|
|
|
// Start B 对应 index 104
|
|
const START_B_INDEX = 104;
|
|
// Stop 对应 index 106
|
|
const STOP_INDEX = 106;
|
|
|
|
/**
|
|
* 将字符串编码为 Code128B 的条块分布
|
|
* @param {string} text 要编码的文本字符串 (ASCII 32 - 126)
|
|
* @returns {Array<{ isBar: boolean, width: number }>} 条块序列
|
|
*/
|
|
export function encodeCode128B(text) {
|
|
if (!text) text = '0000';
|
|
|
|
const codes = [START_B_INDEX];
|
|
let checkSum = START_B_INDEX;
|
|
|
|
for (let i = 0; i < text.length; i++) {
|
|
const charCode = text.charCodeAt(i);
|
|
// Code 128B 映射: ASCII 32~127 对应 code 0~95
|
|
let val = charCode - 32;
|
|
if (val < 0 || val > 95) val = 0; // 越界字符转为空格
|
|
codes.push(val);
|
|
checkSum += val * (i + 1);
|
|
}
|
|
|
|
const checkVal = checkSum % 103;
|
|
codes.push(checkVal);
|
|
codes.push(STOP_INDEX);
|
|
|
|
// 转换为高精度条空阵列 (Bar and Space array)
|
|
const segments = [];
|
|
codes.forEach((codeIndex) => {
|
|
const pattern = CODE128_PATTERNS[codeIndex];
|
|
if (!pattern) return;
|
|
for (let p = 0; p < pattern.length; p++) {
|
|
const width = parseInt(pattern[p], 10);
|
|
const isBar = p % 2 === 0;
|
|
segments.push({ isBar, width });
|
|
}
|
|
});
|
|
|
|
return segments;
|
|
}
|
|
|
|
/**
|
|
* 转换为 0/1 位图序列 (用于像素级精确渲染)
|
|
* @param {string} text
|
|
* @returns {string} 由 '1' 和 '0' 组成的二进制序列
|
|
*/
|
|
export function getBarcodeBits(text) {
|
|
const segments = encodeCode128B(text);
|
|
let bits = '';
|
|
segments.forEach((seg) => {
|
|
bits += (seg.isBar ? '1' : '0').repeat(seg.width);
|
|
});
|
|
return bits;
|
|
}
|