Canvas 第二次draw回调失效,图片不显示
发布于 5 年前 作者 xiayu 17470 次浏览 来自 问答
  • 当前 Bug 的表现(可附上截图)
  • 预期表现
  • 复现路径
  • 提供一个最简复现 Demo

ctx.draw(false, () => {

drawed.call(this);

});

ctx.draw(true, () => {

drawed.call(this);

});

4 回复

const {

    windowWidth,

    pixelRatio,

} = wx.getSystemInfoSync();

const px = (n) => {

    if (typeof n === ‘undefined’) return void 0;

    if (!n) return 0;

    return parseInt(n, 10) / 750 * windowWidth;

}

const fillColor = (ctx, start, end, colorStop, shape) => {

    let grd = null;

    if (shape === ‘Radial’) {

        const [x, y, r] = start;

        grd = ctx.createCircularGradient(…[px(x), px(y), px®]);

    } else {

        const [x0, y0, x1, y1] = start;

        grd = ctx.createLinearGradient(…[px(x0), px(y0), px(x1), px(y1)]);

    }

    colorStop.forEach((cs) => {

        grd.addColorStop(…cs);

    });

    ctx.setFillStyle(grd);

    const [x, y, widht, height] = end;

    ctx.fillRect(…[px(x), px(y), px(widht), px(height)]);

};

const formatBorder = (border) => {

    if (!border) return [0, ‘rgba(0,0,0,0)’];

    const borderArr = border.split(’ ');

    borderArr[0] = px(borderArr[0]);

    if (!borderArr[1]) borderArr[1] = ‘rgba(0,0,0,0)’;

    return borderArr;

}

const formatPadding = (padding) => {

    let paddingArr = [];

    if (typeof padding === ‘number’) {

        paddingArr.length = 4;

        paddingArr.fill(px(padding));

    } else {

        paddingArr = padding.split(’ ').map(p => px§);

    }

    return paddingArr;

}

const formatText = (ctx, text, pxMW, pxLH) => {

    const textArr = [];

    let tempArr = [];

    let tempWidth = 0;

    text.split(’’).forEach(word => {

        const w = ctx.measureText(word).width;

        if (tempWidth + w > pxMW) {

            textArr.push(tempArr.join(’’));

            tempArr = [word];

            tempWidth = 0;

        } else {

            tempArr.push(word);

            tempWidth = w + tempWidth + 1;

        }

    });

    if (tempArr.length > 0) {

        textArr.push(tempArr.join(’’));

    }

    const textWidth = textArr.length > 1 ? pxMW : ctx.measureText(text).width;

    const textHeight = textArr.length * pxLH;

    return { textArr, textWidth, textHeight };

}

function drawed() {

    const {

        width,

        height,

    } = this.data;

    const self = this;

    // 输出的图片的宽度和高度

    const destWidth = px(width) * pixelRatio;

    const destHeight = px(height) * pixelRatio;

    wx.canvasToTempFilePath({

        destWidth,

        destHeight,

        canvasId: ‘draw-canvas’,

        success(res) {

            self.setData({

                imageUrl: res.tempFilePath,

            });

            // 微信小程序自定义事件

            self.triggerEvent(‘toTempFile’, res);

        },

    }, this);

}

Component({

    properties: {

        width: {

            type: Number,

            value: 750,

        },

        height: {

            type: Number,

            value: 500,

        },

        layers: {

            type: Array,

            value: [],

        },

        background: {

            type: Object,

            value: null,

        },

    },

    data: {

        imageUrl: null,

    },

    attached() {

        const {

            background,

            layers,

            width,

            height,

        } = this.data;

        // 创建canvas的绘图上下文

        const ctx = wx.createCanvasContext(‘draw-canvas’, this);

        // 背景图片

        if (background) {

            const {

                imageResource,

                dx = 0,

                dy = 0,

                dWidth = width,

                dHeight = height,

                color,

            } = background;

            // 背景颜色

            if (color) {

                const {

                    start,

                    end,

                    colorStop,

                    shape = ‘Linear’,

                } = color;

                fillColor(ctx, start, end, colorStop, shape);

            }

            // ctx.drawImage()绘制图像到画布

            // imageResource所有绘制的图片资源

            imageResource && ctx.drawImage(imageResource, px(dx), px(dy), px(dWidth), px(dHeight));

        }

        // 图层

        layers.forEach((layer) => {

            if (layer.type === ‘text’) {

                const {

                    // textBaseline = ‘top’,

                    textAlign = ‘left’,

                    fontSize = 32,

                    text = ‘’,

                    x = 0,

                    y = 0,

                    color = ‘#000’,

                    lineHeight = 44,

                    maxWidth = width,

                    border = ‘0’,

                    radius = 0,

                    padding = 0,

                    bgColor = null,

                    maxLine = 0,

                } = layer;

                const pxx = px(x);

                const pxy = px(y);

                const pxFS = px(fontSize);

                const pxLH = px(lineHeight);

                const pxMW = px(maxWidth);

                const pxRadius = px(radius);

                ctx.setFontSize(pxFS);

                // border

                const [pxbw, bc] = formatBorder(border);

                // padding 上右下左

                const [pt, pr, pb, pl] = formatPadding(padding);

                let {textArr, textWidth, textHeight} = formatText(ctx, text, pxMW, pxLH);

                // console.log(textArr, maxLine, textWidth);

                if (maxLine) {

                    const overLine = textArr.length > maxLine;

                    textArr.length = maxLine;

                    if (overLine) {

                        const strArr = textArr[maxLine - 1].split(’’);

                        strArr.splice((strArr.length - 2), 2, ‘…’, ‘…’);

                        textArr.splice(maxLine - 1, 1, strArr.join(’’));

                    }

                }

                // 真实宽高

                const realWidth = textWidth + pl + pr;

                const realHeight = textHeight + pt + pb;

                let realX = pxx - pl;

                let realY = pxy - pt;

                if (textAlign === ‘right’) {

                    realX = pxx - pl - textWidth;

                    realY = pxy - pt;

                } else if (textAlign === ‘center’) {

                    realX = pxx - pl - textWidth / 2;

                    realY = pxy - pt;

                }

                // 边框

                // 保存绘图上下文

                ctx.save();

                ctx.setStrokeStyle(bc);

                if (bgColor) {

                    ctx.setFillStyle(bgColor);

                    ctx.fillRect(realX, realY, realWidth, realHeight);

                }

                ctx.stroke();

                // 恢复之前保存的绘图上下文

                ctx.restore();

                ctx.setFillStyle(color);

                ctx.setTextBaseline(‘top’);

                ctx.setTextAlign(textAlign);

                textArr.forEach((str, i) => {

                    ctx.fillText(str, pxx, pxy + i * pxLH, pxMW);

                });

            }

            if (layer.type === ‘image’) {

                const {

                    imageResource,

                    dx = 0,

                    dy = 0,

                    radius = 0,

                    dWidth = width,

                    dHeight = height,

                    border,

                } = layer;

                const [pxbw, bc] = formatBorder(border);

                const [pxdx, pxdy, pxdWidth, pxdHeight, pxdRadius] =

                    [px(dx), px(dy), px(dWidth), px(dHeight), px(radius)];

                if (radius) {

                    // 保存绘图上下文

                    ctx.save();

                    ctx.setStrokeStyle(bc);

                    // ctx.drawImage()绘制图像到画布

                    ctx.drawImage(imageResource, pxdx, pxdy, pxdWidth, pxdHeight);

                    // 恢复之前保存的绘图上下文

                    ctx.restore();

                } else {

                    // 保存绘图上下文

                    ctx.save();

                    ctx.drawImage(imageResource, pxdx, pxdy, pxdWidth, pxdHeight);

                    // 恢复之前保存的绘图上下文

                    ctx.restore();

                }

            }

        });

        ctx.draw(false, () => {

            console.log(’-------’);

            drawed.call(this);

        });

        ctx.draw(true, () => {

            console.log(’=======’);

            drawed.call(this);

        });

第二次draw回调不执行,加了定时勉强可以实现,但是同时绘制多张图片总不能一直加setTimeout…,有大牛帮看下么?

setTimeout(() => {

        console.log(’=======’);

        drawed.call(this);

}, 1000);

麻烦提供出现问题的机型和微信版本,以及能复现问题的简单代码片段https://developers.weixin.qq.com/miniprogram/dev/devtools/minicode.html

第二次draw的时候如果延时1ms以上就会有回调,测试发现1ms的时候让然不一定有回调,代码片段:https://developers.weixin.qq.com/s/Mj5Jtamm7g4A

能来个代码片段吗?可能是bug,也可能是你写法的问题呢

回到顶部