小程序
小游戏
企业微信
微信支付
扫描小程序码分享
目前调用canvasToTempFilePath绘制canvas,正常返回图片地址,并展示。图片地址:http://tmp/kdGi1n6uNhrp04f4a9e26b0100eb9d363d91e17f7b49.png
然后调用saveImageToPhotosAlbum将图片保存到相册,会出现中间的二维码空白的情况,比如VIVO手机、华为手机都出现过,微信版本都是最新的,是什么原因呢?
2 个回答
加粗
标红
插入代码
插入链接
插入图片
上传视频
你好,麻烦通过点击下方“反馈信息”按钮,提供出现问题的。
提供个代码片段?
关注后,可在微信内接收相应的重要提醒。
请使用微信扫描二维码关注 “微信开放社区” 公众号
提供个代码片段?
import utils from "../utils";
/**
* 通用Canvas类
* Created by dongdongzhang on 2020-02-09.
*/
class BaseCanvas {
/**
* 构造函数
*/
constructor() {
}
/**
* 将当前画布的内容导出生成图片,并返回文件路径
* @param canvas canvas对象
* @param width 宽度
* @param height 高度
* @param callBack 回调函数
* @param failCallBack 失败回调函数
*/
canvasToTempFilePath(canvas, width, height, callBack, failCallBack) {
//微信
//#ifdef MP-WEIXIN
setTimeout(() => {
uni.canvasToTempFilePath({
width: width,
height: height,
destWidth: canvas.width,
destHeight: canvas.height,
canvas: canvas,
success: res => {
if (callBack) {
callBack(res.tempFilePath);
}
},
fail: res => {
if (failCallBack) {
failCallBack(res);
}
}
});
}, 500);
//#endif
//支付宝
//#ifdef MP-ALIPAY
canvas.draw();
setTimeout(() => {
canvas.toTempFilePath({
width: width,
height: height,
destWidth: canvas.width,
destHeight: canvas.height,
canvas: canvas,
success: res => {
if (callBack) {
callBack(res.filePath);
}
},
fail: res => {
if (failCallBack) {
failCallBack(res);
}
}
});
}, 500);
//#endif
}
/**
* 绘制图片
* @param canvas canvas对象
* @param ctx canvas内容context
* @param imgUrl 图片地址
* @param x 起始点X
* @param y 起始点Y
* @param w 图片宽度
* @param h 图片高度
* @param fillet 圆角半径
*/
drawImage(canvas, ctx, imgUrl, x, y, w, h, fillet, callback) {
let drawCircleImg = (img) => {
ctx.beginPath();
ctx.save();
ctx.lineWidth = 1;
ctx.strokeStyle = 'transparent';
ctx.moveTo(x + fillet, y);// 创建开始点
ctx.lineTo(x + w - fillet, y);// 创建水平线
ctx.arcTo(x + w, y, x + w, y + fillet, fillet);// 创建弧
ctx.lineTo(x + w, y + h - fillet);// 创建垂直线
ctx.arcTo(x + w, y + h, x + w - fillet, y + h, fillet);// 创建弧
ctx.lineTo(x + fillet, y + h);// 创建水平线
ctx.arcTo(x, y + h, x, y + h - fillet, fillet);// 创建弧
ctx.lineTo(x, y + fillet);// 创建垂直线
ctx.arcTo(x, y, x + fillet, y, fillet);// 创建弧
ctx.stroke();
ctx.clip();
ctx.drawImage(img, x, y, w, h);
ctx.restore();
ctx.closePath();
};
//微信
//#ifdef MP-WEIXIN
const imgInfo = canvas.createImage();
imgInfo.src = imgUrl;
imgInfo.onload = () => {
if (fillet && fillet > 0) {
if (callback) {
callback();
}
drawCircleImg(imgInfo);
} else {
ctx.drawImage(imgInfo, x, y, w, h);
ctx.restore();
if (callback) {
callback();
}
}
};
//#endif
//支付宝
//#ifdef MP-ALIPAY
if (fillet && fillet > 0) {
drawCircleImg(imgUrl);
} else {
ctx.drawImage(imgUrl, x, y, w, h);
//绘制图片时,保存以绘制的画布(true)
ctx.draw(true);
}
//#endif
}
/**
* 获取canvas对象
* @param pageObj
* @param canvasId
* @param width
* @param height
* @returns {Promise<any>}
*/
getCanvas(pageObj, canvasId, width, height) {
let dpr = utils.public.getSystemInfoSync().pixelRatio;
return new Promise((resolve) => {
//微信
//#ifdef MP-WEIXIN
pageObj.createSelectorQuery()
.select(`#${canvasId}`)
.fields({node: true, size: true})
.exec(res => {
const canvas = res[0].node,
ctx = canvas.getContext('2d');
canvas.width = width * dpr;
canvas.height = height * dpr;
ctx.scale(dpr, dpr);
resolve({canvas, ctx});
});
//#endif
//支付宝
//#ifdef MP-ALIPAY
const canvas = my.createCanvasContext(canvasId);
canvas.width = width * dpr;
canvas.height = height * dpr;
canvas.scale(1, 1);
resolve({canvas, ctx: canvas});
//#endif
});
}
/**
* 删除存储的文件数据
*/
removeSavedFile() {
uni.getSavedFileList({
success: res => {
res.fileList.forEach((val, key) => {
//删除存储的垃圾数据
uni.removeSavedFile({
//#ifdef MP-WEIXIN
filePath: val.filePath,
//#endif
//支付宝
//#ifdef MP-ALIPAY
apFilePath: val.apFilePath
//#endif
});
})
}
});
}
/**
* 绘制圆角矩形
* @param {CanvasContext} ctx canvas上下文
* @param {number} x 圆角矩形选区的左上角 x坐标
* @param {number} y 圆角矩形选区的左上角 y坐标
* @param {number} w 圆角矩形选区的宽度
* @param {number} h 圆角矩形选区的高度
* @param {number} r 圆角的半径
* @param {number} fill 填充色
*/
fillRoundRect(ctx, x, y, w, h, r, fill) {
// 开始绘制
ctx.beginPath();
// 因为边缘描边存在锯齿,最好指定使用 transparent 填充
// 这里是使用 fill 还是 stroke都可以,二选一即可
ctx.fillStyle = fill;
//ctx.setStrokeStyle('#000')
// 左上角
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
// border-top
ctx.moveTo(x + r, y);
ctx.lineTo(x + w - r, y);
ctx.lineTo(x + w, y + r);
// 右上角
ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
// border-right
ctx.lineTo(x + w, y + h - r);
ctx.lineTo(x + w - r, y + h);
// 右下角
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
// border-bottom
ctx.lineTo(x + r, y + h);
ctx.lineTo(x, y + h - r);
// 左下角
ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
// border-left
ctx.lineTo(x, y + r);
ctx.lineTo(x + r, y);
// 这里是使用 fill 还是 stroke都可以,二选一即可,但是需要与上面对应
ctx.fill();
// ctx.stroke()
ctx.closePath()
}
/**
* 绘制文本
* @param ctx
* @param word 文本内容
* @param x 起始点X
* @param y 起始点Y
* @param fontStyle 字体样式
* @param fillStyle 字体颜色
* @param textAlign 字体对齐
*/
fillText(ctx, word, x, y, fontStyle, fillStyle, textAlign) {
if (fontStyle) {
ctx.font = fontStyle;
}
if (fillStyle) {
ctx.fillStyle = fillStyle;
}
if (textAlign) {
ctx.textAlign = textAlign;
}
ctx.fillText(word, x, y);
}
/**
* 文字换行
* @param ctx
* @param str 文本
* @param initX 起始点X
* @param initY 起始点Y
* @param lineHeight 行高
* @param maxWidth 最大宽度
* @param margin 文本距离到边界的距离
*/
fillTextWrap(ctx, str, initX, initY, lineHeight, maxWidth, margin) {
let lineWidth = 0;
let canvasWidth = maxWidth ? maxWidth : 240;
let lastSubStrIndex = 0;
if (!lineHeight) {
lineHeight = 20;
}
for (let i = 0; i < str.length; i++) {
lineWidth += ctx.measureText(str[i]).width;
if (lineWidth > canvasWidth - margin * 2) {//减去保护边界,防止边界出现的问题
ctx.fillText(str.substring(lastSubStrIndex, i), initX, initY);
initY += lineHeight;
lineWidth = 0;
lastSubStrIndex = i;
}
if (i == str.length - 1) {
ctx.fillText(str.substring(lastSubStrIndex, i + 1), initX, initY);
}
}
}
}
export default BaseCanvas