【问题标题】:How to create an image generator for combining multiple images?如何创建用于组合多个图像的图像生成器?
【发布时间】:2016-05-03 10:44:02
【问题描述】:

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

用户可以上传 2 张或最多 3 张图片(类型应为 png 或 jpg)到画布。生成的图像应始终为 1080x1920。如果 hart 只上传 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/

【问题讨论】:

    标签: javascript jquery html canvas


    【解决方案1】:

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

    在这里查看image rotation

    Updated jsFiddle,绘制多张图片。

    注意:

    1. 保存脚本只是一种懒惰的方式来确保我有 在我保存 merge_image 之前加载的外部脚本...
    2. 示例脚本中没有同步,请注意addToCanvas 在图像加载事件中调用,可能存在竞争条件 在这里(但我对此表示怀疑,因为图像已加载到内存中 客户端)

    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;
    }

    PS:我已经添加了一些脚本来下载合并的图像,但它会失败。错误消息是:“未捕获的 SecurityError:无法在 'HTMLCanvasElement' 上执行 'toDataURL':可能无法导出受污染的画布。”

    我做了一个快速的谷歌搜索,它似乎与跨域资源有关。我认为这不会是 FileReader 的问题。 我没有时间测试,所以请测试它(并请告诉我:) 它适用于 FileReader!

    【讨论】:

    • 感谢您的回答。正如我在上面的问题中提到的,还有一种方法可以上传更多图像,并且每张图像都将一个接一个地放置。我将检查 SecurityError。如果我有解决方案,我会告诉你。
    • 您需要将当前画布保存为图像并在每次添加新图像时重新绘制它。我已经用链接更新了我的答案。注意:我不确定内存和性能,但我认为绘制和重新绘制不同类型的图像是一个资源匮乏的过程......
    • 看来我误解了你关于 merge_image 的问题。你想上传图片,而不是保存它,不是吗?如果是这样,您需要在上传正文中将 dataURL 发送到服务器,而不是将其保存到文件中...
    • 我也更新了我的答案。有一些变化。提前致谢。
    • 你试过我更新的 JSFiddle 链接了吗?尝试选择一些图像,然后下载合并后的图像。
    【解决方案2】:

    您可以使用 toDataURL。但这样用户必须执行类似 Save image as...

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

    然后设置例如img result src:

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

    【讨论】:

    • 谢谢。那么图像旋转呢,你能帮我解决一下吗?
    【解决方案3】:

    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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-02-08
      • 2021-06-02
      • 2019-12-31
      • 2020-05-11
      • 2014-05-18
      • 2021-07-12
      • 1970-01-01
      相关资源
      最近更新 更多