// 带超时的服务市场调用封装
function invokeServiceWithTimeout(
options: any,
timeout: number = 8000 // 设置8秒超时
): Promise<any> {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
reject({ errMsg: `invokeService timeout`, message: `服务调用超时,请检查网络或稍后重试` });
}, timeout);
wx.serviceMarket.invokeService({
...options,
success: (res: any) => {
clearTimeout(timer);
console.log('invokeService success', res);
resolve(res);
},
fail: (err: any) => {
clearTimeout(timer);
console.error('invokeService fail', err);
reject(err);
},
});
});
}
// 识别图片文字
export async function recognize(imagePath: string): Promise<{ texts: string[], regions: { left: number, top: number, width: number, height: number }[] }> {
try {
console.log("进入reco函数, imagePath:", imagePath);
if (!imagePath) {
wx.showToast({ title: '图片路径为空', icon: 'error' });
throw new Error('图片路径为空');
}
wx.showLoading({ title: '正在识别...', mask: true });
const res = await invokeServiceWithTimeout({
service: 'wx79ac3de8be320b71',
api: 'OcrAllInOne',
data: {
img_url: { type: 'filePath', filePath: imagePath },
data_type: 3,
ocr_type: 3,
},
});
console.log("完成const res", res);
if (res.errCode === 0 && res.data && res.data.ocr_comm_res) {
const result = JSON.parse(res.data.ocr_comm_res);
if (!result || !result.items || result.items.length === 0) {
wx.showToast({ title: '未识别到文字', icon: 'none' });
throw new Error('未识别到文字');
}
console.log("获得result", result);
wx.hideLoading();
return {
texts: result.items.map((item: any) => item.text),
regions: result.items.map((item: any) => ({
left: item.pos[0].x,
top: item.pos[0].y,
width: item.pos[1].x - item.pos[0].x,
height: item.pos[2].y - item.pos[1].y,
}))
};
} else {
// 服务调用本身成功,但业务逻辑失败
console.error("OCR 服务返回错误", res);
throw new Error(`服务返回错误: ${res.errMsg || JSON.stringify(res.data)}`);
}
} catch (err: any) {
wx.hideLoading();
console.error("OCR 识别流程异常", err);
wx.showModal({
title: '识别失败',
content: (err && err.message) ? err.message : JSON.stringify(err),
showCancel: false
});
// 重新抛出错误,让上层知道失败了
throw err;
}
}
// 用canvas将翻译文本绘制到原图对应区域,返回新图片路径
export async function drawTranslatedText(
imagePath: string,
regions: any[],
translatedTexts: string[],
width: number,
height: number
): Promise<string> {
return new Promise((resolve, reject) => {
// 确保 canvasId 和页面中的 <canvas> 组件 id 一致
const ctx = wx.createCanvasContext('resultCanvas');
ctx.drawImage(imagePath, 0, 0, width, height);
// 设置文本样式
ctx.setFontSize(20); // 根据实际情况调整
ctx.setFillStyle('#FF0000'); // 红色
ctx.setTextAlign('left');
ctx.setTextBaseline('top');
translatedTexts.forEach((text, i) => {
const region = regions[i];
if (region) {
// 清理原有区域(可选,如果需要完全覆盖)
ctx.clearRect(region.left, region.top, region.width, region.height);
// 在原区域填充白色背景,让新文字更清晰
ctx.setFillStyle('#FFFFFF');
ctx.fillRect(region.left, region.top, region.width, region.height);
// 重新设置文字颜色
ctx.setFillStyle('#FF0000');
// 简单处理文字换行和缩放,以适应区域
const fontSize = Math.min(region.height - 4, (region.width / text.length) * 1.5);
ctx.setFontSize(fontSize > 8 ? fontSize : 8); // 最小字号为8
ctx.fillText(text, region.left, region.top + 2, region.width);
}
});
ctx.draw(false, () => {
wx.canvasToTempFilePath({
canvasId: 'resultCanvas',
width,
height,
success: res => resolve(res.tempFilePath),
fail: reject
});
});
});
}
这是我的ocr调用代码,始终无法成功调用。刚写好代码的时候,wx.serviceMarket.invokeService是有报错的,提示我wx没有serviceMarket这个类,然后我点了一下快速修复,那个报错就没了。但是后续始终无法成功调用这个函数。以下是我实机测试的时候,遇到的报错。
我确认我在服务市场是绑定好了的,如图所示: