Javascript canvas toDataURL未返回完整图像

Javascript canvas toDataURL未返回完整图像,javascript,jquery,html,canvas,Javascript,Jquery,Html,Canvas,我正在构建一个jQuery插件,用于对图像进行水印处理(是的,我很清楚javascript/html5水印系统的诸多缺点,但现在就忽略它了。)每个图像的基本方法是: 将图像粘贴到画布的背景上 在上面添加水印图像的数据, 将原始图像的src替换为画布的src(现在包含水印)。 现在,如果我将图像元素替换为画布本身,它似乎可以正常工作。。所有元素都显示在画布上。但是当我得到画布的dataURL时,除了最后一张画在画布上的图像之外,其他所有的东西都会出现。我甚至不介意,除了这个插件还需要替换到图像

我正在构建一个jQuery插件,用于对图像进行水印处理(是的,我很清楚javascript/html5水印系统的诸多缺点,但现在就忽略它了。)每个图像的基本方法是:

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

现在,如果我将图像元素替换为画布本身,它似乎可以正常工作。。所有元素都显示在画布上。但是当我得到画布的dataURL时,除了最后一张画在画布上的图像之外,其他所有的东西都会出现。我甚至不介意,除了这个插件还需要替换到图像的链接,所以用数据URL(带水印)替换HREF

这是当前代码:

(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);
(函数($){
$.fn.extend({
cmark:功能(选项){
var默认值={
键入:“图像”,
内容:“水印.png”,
过滤器:“较暗”,
比例:300,
方框:{
排名:0.5,
左:0.5,
宽度:0.75,
身高:0.75,
bgcolor:“#000000”,
不透明度:0.5,
不透明度:1
},
不支持的回调函数:函数(obj){
返回obj;
}
}
var getScale=函数(w、h、scale){
比率=数学最小值(标度/w,标度/h);
scalew=数学四舍五入(比率*w);
scaleh=数学四舍五入(比率*h);
返回[scalew,scaleh];
}
var options=$.extend(默认值,选项);
返回此值。每个(函数(){
obj=$(本);
canvas=document.createElement('canvas');
如果(!window.htmlcanvaseElement){
返回选项。不支持回调(obj);
}
/*如果选择图像,请重置图像。否则,
我们正在用数据URL替换链接HREF*/
if(对象属性('src')){
target_img=obj.attr('src');
}
else if(obj.attr('href')){
target_img=obj.attr('href');
}
//获取文件类型,确保它是映像。如果是,则获取mimetype。如果不是,则返回。
ftype=target\u img.substring(target\u img.lastIndexOf(“.”+1).toLowerCase();
canvasbg=新图像();
canvasbg.onload=函数(){
iw=画布bg.width;
ih=画布高度;
scale=getScale(iw、ih、options.scale);
iw=标度[0];
ih=标度[1];
canvas.setAttribute('width',iw);
canvas.setAttribute('height',ih);
ctx=canvas.getContext('2d');
/*将框定义为相对于图像大小的一组尺寸(百分比)*/
bw=数学圆(iw*options.box.width);
bh=数学圆(ih*选项框高度);
//现在,盒子将永远不会居中。
bx=Math.round((iw*options.box.top)-(bw/2));
by=数学圆(ih*options.box.left-(bh/2));
/*除非不透明度为0,否则绘制长方体*/
如果(options.box.bg不透明度>0){
ctx.fillStyle=options.box.bgcolor;
ctx.globalAlpha=options.box.bgopacity;
ctx.fillRect(bx、by、bw、bh);
}
wm=新图像();
wm.onload=函数(){
ww=wm.width;
wh=wm.height;
scalar=Math.max(bw,bh);//缩放到框内尺寸
scale=getScale(ww、wh、标量);
ww=标度[0];
wh=刻度[1];
ctx.globalCompositeOperation=options.filter;
ctx.drawImage(wm、bx、by、ww、wh);
}
wm.src=options.content;
ctx.drawImage(canvasbg,0,0,iw,ih);
对象替换为(画布);
$('body')。追加('');
//obj.attr('src',canvas.toDataURL());
}
canvasbg.src=target\u img;
});
}
})
})(jQuery);
我添加了一行,将带有数据url的图像直接转储到页面上进行测试,这就是我看到的。。。左边是canvas元素,右边是带有数据url的图像:

是的,这已经让我难堪了好几天了。我可能错过了一些非常明显的东西,但我看不到


。。。已编辑,因为示例不再联机。对不起

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

var img = new Image();
img.src = canvas.toDataURL();
$('body').append(img);
或者,如果您愿意:

$('body').append($('<img>').attr('src', canvas.toDataURL()))
$('body')。追加($('body')
第二,在绘制水印之前,您将获得画布的dataURL。绘制发生在
wm.onload
回调函数中,该函数在加载水印时发生。在
canvasbg.onload
触发后,才会触发,这就是您获取dataURL的地方


因此,在
wm.onload
回调结束时,将图像附加到代码中,您应该会很好。

如果您在某个地方主持了一个“工作”示例(显示您的问题),您可能会得到更多帮助,例如,您肯定走在正确的轨道上:我在OP的示例
document.getE上运行了以下行