canvas toDataURL 未返回完整图像

2024-02-21

我正在构建一个为图像添加水印的 jQuery 插件(是的,我很清楚 javascript/html5 水印系统的多重缺点,但现在忽略它。)每个图像的基本方法是:

  • 将图像粘贴到画布的背景
  • 添加水印图像的数据,
  • 将原始图像的 src 替换为画布的 src(现在包含水印。)

现在,如果我用画布本身替换图像元素,它似乎工作正常。所有元素都出现在画布上。但是当我获取画布的 dataURL 时,除了最后绘制到其上的图像之外的所有内容都会出现。我什至不介意,除了这个插件还需要替换图像的链接,因此将 href 替换为数据 url(带有水印)。

这是当前的代码:

(function($){

    $.fn.extend({

        cmark: function(options) {

            var defaults = {
                type: 'image',
                content: 'watermark.png',
                filter: 'darker',
                scale:300,
                box: {
                    top         :   0.5,
                    left        :   0.5,
                    width       :   0.75,
                    height      :   0.75,
                    bgcolor     :   '#000000',
                    bgopacity   :   0.5,
                    fgopacity   :   1
                },

                callback_unsupported: function(obj){
                    return obj;
                }

            }

            var getScale = function(w, h, scale){
                ratio = Math.min(scale/w, scale/h);
                scalew = Math.round(ratio*w);
                scaleh = Math.round(ratio*h);
                return [scalew,scaleh];
            }



            var options =  $.extend(defaults, options);

            return this.each(function() {

                obj = $(this);

                canvas = document.createElement('canvas');

                if(!window.HTMLCanvasElement){
                    return options.callback_unsupported(obj);
                }


                /*  if selecting for images, reset the images. Otherwise, 
                    we're replacing link hrefs with data urls. */

                if(obj.attr('src')){
                    target_img = obj.attr('src');
                }

                else if (obj.attr('href')){
                    target_img = obj.attr('href');
                }

                // get the filetype, make sure it's an image. If it is, get a mimetype. If not, return.

                ftype = target_img.substring(target_img.lastIndexOf(".")+1).toLowerCase();

                canvasbg = new Image();

                canvasbg.onload = function(){
                    iw = canvasbg.width;
                    ih = canvasbg.height;

                    scale = getScale(iw, ih, options.scale);

                    iw = scale[0];
                    ih = scale[1];

                    canvas.setAttribute('width', iw);
                    canvas.setAttribute('height', ih);

                    ctx = canvas.getContext('2d');

                    /* define the box as a set of dimensions relative to the size of the image (percentages) */

                    bw = Math.round(iw * options.box.width);
                    bh = Math.round(ih * options.box.height);

                    // for now the box will only ever be centered.
                    bx = Math.round((iw * options.box.top) - (bw/2));
                    by = Math.round(ih * options.box.left - (bh/2));

                    /* draw the box unless the opacity is 0 */
                    if(options.box.bgopacity > 0){
                        ctx.fillStyle = options.box.bgcolor;
                        ctx.globalAlpha = options.box.bgopacity;
                        ctx.fillRect(bx, by, bw, bh);
                    }

                    wm = new Image();

                    wm.onload = function(){
                        ww = wm.width;
                        wh = wm.height;

                        scalar = Math.max(bw, bh); // scale to within the box dimensions
                        scale = getScale(ww, wh, scalar);
                        ww = scale[0];
                        wh = scale[1];

                        ctx.globalCompositeOperation = options.filter;
                        ctx.drawImage(wm, bx, by, ww, wh);
                    }

                    wm.src = options.content;

                    ctx.drawImage(canvasbg, 0, 0, iw, ih);

                    obj.replaceWith(canvas);

                    $('body').append('<img src="'+canvas.toDataURL()+'">');

                    //obj.attr('src', canvas.toDataURL());
                }

                canvasbg.src = target_img;



            });
        }
    })
})(jQuery);

我添加了一行,将带有数据 url 的图像直接转储到页面上进行测试,这就是我所看到的...左侧是画布元素,右侧是带有数据 url 的图像:

是的,这让我困惑了好几天。我可能错过了一些非常明显的东西,但我看不到它。

...已编辑,因为该示例不再在线。对不起。


首先,不要为标签构建那么大的字符串缓冲区。

var img = new Image();
img.src = canvas.toDataURL();
$('body').append(img);

或者如果您愿意:

$('body').append($('<img>').attr('src', canvas.toDataURL()))

其次,在绘制水印之前,您需要获取画布的 dataURL。绘图发生在wm.onload回调函数,在水印加载时发生。那可能要等到很久之后才会触发canvasbg.onload触发,这是您获取 dataURL 的地方。

因此,将图像附加移动到代码末尾wm.onload回调,你应该很好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

canvas toDataURL 未返回完整图像 的相关文章

随机推荐