如何创建一个图像生成器来组合多个图像?

时间:2016-01-26 18:29:01

标签: javascript jquery html5 canvas

我正在使用HTML5 canvas和jQuery / JS开发图像生成器。我想要完成的是以下内容。

用户可以将2个或最多3个图像(类型应为png或jpg)上传到画布。生成的图像应始终为1080x1920。如果哈特仅上传2张图片,则图片为1080x960。如果上传了3张图像,则每张图像的尺寸应为1080x640。

上传2或3张图片后,用户可以点击下载按钮获取合并后的图片,格式为1080x1920px。

应该使用html canvas来完成这项工作。

我想出了这个:

HTML:

 <canvas id="canvas">
        Sorry, canvas not supported
    </canvas><!-- /canvas.offers -->
    <input id="fileInput" type="file" />
<a href="#" class="generate">Generate</a>

jQuery的:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

canvas.height = 400;
canvas.width = 800;


var img1 = loadImage('http://www.shsu.edu/dotAsset/0e829093-971c-4037-9c1b-864a7be1dbe8.png', main);
var img2 = loadImage('https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Ikea_logo.svg/266px-Ikea_logo.svg.png', main);

var minImages = 2;
var imagesLoaded = 0;

function main() {
    imagesLoaded += 1;

    if(imagesLoaded >= minImages) {
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.save();

        ctx.drawImage(img1, 0, 0);

        // ctx.translate(canvas.height/2,canvas.width/2); // move to the center of the canvas
        // ctx.rotate(270*Math.PI/180); // rotate the canvas to the specified degrees
        // ctx.drawImage(img2,0,canvas.height/2);

        ctx.translate(-canvas.height/2,canvas.width/2); // move to the center of the canvas
        ctx.rotate(90*Math.PI/180); // rotate the canvas to the specified degrees
        ctx.drawImage(img2,-img2.width/2,-img2.width/2);

        ctx.restore(); // restore the unrotated context
    }
}


function loadImage(src, onload) {
    var img = new Image();

    img.onload = onload;
    img.src = src;

    console.log(img);
    return img;
}

上面的代码将创建画布并将两个图像(现在在JS中硬编码)放置到创建的画布上。它将旋转90度,但不会定位到右角。第二张图像也应位于第一张图像旁边。

如何并排对每张图像进行旋转和定位?

工作小提琴:https://jsfiddle.net/8ww1x4eq/2/

3 个答案:

答案 0 :(得分:1)

查看更新的jsFiddle,这是你想要的吗?

请看这里有关image rotation

的信息

Updated jsFiddle,绘制多张图片。

<强>注意:

  1. 保存脚本只是一种懒惰的方式,以确保我得到了 保存merged_image之前加载的外部脚本...
  2. 示例脚本中没有同步,请注意addToCanvas 在图像加载事件中被调用,可能存在竞争条件 在这里(但我怀疑它,因为图像被加载到内存中 客户端)
  3. &#13;
    &#13;
    function addToCanvas(img) {
        // resize canvas to fit the image
        // height should be the max width of the images added, since we rotate -90 degree
        // width is just a sum of all images' height
        canvas.height = max(lastHeight, img.width);
        canvas.width = lastWidth + img.height;
        
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        if (lastImage) {
            ctx.drawImage(lastImage, 0, canvas.height - lastImage.height);
        }
        
        ctx.rotate(270 * Math.PI / 180); // rotate the canvas to the specified degrees
        ctx.drawImage(img, -canvas.height, lastWidth);
        
        lastImage = new Image();
        lastImage.src = canvas.toDataURL();
        lastWidth += img.height;
        lastHeight = canvas.height;
        imagesLoaded += 1;
    }
    &#13;
    &#13;
    &#13;

    PS:我已经添加了一些脚本来下载合并的图像,但它会失败。错误消息是:&#34; Uncaught SecurityError:无法执行&#39; toDataURL&#39; on&#39; HTMLCanvasElement&#39;:可能无法导出受污染的画布。&#34;

    我已经快速完成了谷歌搜索,它似乎与跨源资源有关。我认为它不会成为FileReader的问题。 我还没来得及测试,所以请测试一下(请告诉我:): 适用于FileReader!

答案 1 :(得分:0)

您可以使用 toDataURL 。但通过这种方式,用户必须执行类似将图像另存为...

的操作
var img = canvas.toDataURL("image/png");

然后设置为例如img 结果 src:

$("#result").attr("src",img);

答案 2 :(得分:0)

Canvas已经是一张图片。

canvasimg是可以互换的,因此无需根据图像源域添加canvas.toDataURL可能失败的风险步骤。只需将画布看作是img并将其放入DOM中即可。转换为jpg不会节省空间(实际上是资源饥饿的操作),因为img需要在显示之前进行解码。

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.height = 400;
canvas.width = 800;
document.body.appendChild(canvas);  // add to the end of the document

// or add it to a containing element
var container = document.getElementById("containerID"); // or use JQuery
if(container !== null){
    container.appendChild(canvas);
}