使用画布元素使用JavaScript调整图像大小 [英] Resizing images with javascript using canvas elements

查看:101
本文介绍了使用画布元素使用JavaScript调整图像大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难理解如何使用JavaScript中的 canvas 元素。

I'm having a hard time to understand how to work with canvas elements in JavaScript.

I正在实施调整大小功能,用户可以在 lightbox 内部调整图像的大小。点击预览图像后,灯箱将启动。在 lightbox 元素内,除了图像本身,还有两个用于输入宽度和高度的字段。

I'm implementing a resize feature where user can resize image inside the lightbox. The lightbox will launch after preview image is been clicked. Inside the lightbox element, in addition of the image itself, there are two input fields for width and height.

目标是生成 base64 格式的原始图像的副本,并将其与给定宽度和高度作为查询参数,并让服务器端执行调整大小操作(我在后端使用PHP),或者甚至更好,让JavaScript在前端进行调整大小操作并返回新的,调整大小的图像通过 ajax 发送到服务器。

The objective is to generate a copy of the original image in base64 format and send it to the server along with given width and height as query parameters and let the server side do the resize operation (I'm using PHP for my back end) or even better, let JavaScript do the resize operation in the front end and return new, resized image ready to be sent to the server via ajax.

问题是我不知道如何处理动态创建的 canvas 元素,我该如何处理

The problem is that I don't exactly know how to deal with dynamically created canvas elements and how can I use it to resize my image in the front end.

下面是到目前为止我尝试过的结果很差的内容:

Underneath is what I've tried so far with poor results:

index.html (省略了基本的HTML元素和灯箱效果)

<!-- input fields for width and height -->
<div class="container">
    <div class="form-inline">
        <div class="form-group">
            <input type="number" class="form-control" id="width" placeholder="px">
        </div>
        <div class="form-group">
            <input type="number" class="form-control" id="height" placeholder="px">
        </div>
        <button id="resize" type="button" class="btn btn-primary">Resize</button>
    </div>
</div>

<!-- preview image -->
<div class="container">
    <img src="img/img1.jpg" alt="" class="img-responsive" id="preview">
</div>

<script type="text/javascript">
    button = document.getElementById("resize");

    button.addEventListener("click", function() {
        // get image
        const image = document.getElementById('preview');

        // create a canvas element
        var canvas = document.createElement('canvas'),
            ctx = canvas.getContext("2d");

        canvas.width = image.width; // destination canvas size
        canvas.height = canvas.width * image.height / image.width;

        ctx.drawImage(image, 0, 0, image.width, image.height);
        var canvasData = canvas.toDataURL("image/jpeg");


        // ajax call
        var xhr = new XMLHttpRequest();
        var params = "photo=" + encodeURIComponent(canvasData) + "&name=" + encodeURIComponent(name) + "&width="+ encodeURIComponent(width) + "&height=" + encodeURIComponent(height);
        // send request
        xhr.open("POST", "admin.php?" + params);
        xhr.send();
    });
</script>

admin.php (这里没什么特别的,只需解码一下图片并将其写入文件夹)

<?php

if(isset($_POST['photoUpload']) && isset($_POST['name'])) {
// decode base64 formatted image
$data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $_POST['photoUpload']));

if(isset($_POST['width'] && $_POST['height'])) {
    // resize image here using imagemagick
}

// write file to "img" directory
file_put_contents(dataPath.'img/'.$_POST['name'], $data);

// done
exit('OK|'.dataPath.'img/'.$_POST['name']);
}

任何技巧,窍门和建议都非常感谢!

Any tips, tricks and advices are much appreciated !

推荐答案

您也可以在客户端调整图像的大小。下面的示例代码使用从用户本地系统加载的图像来运行该示例,而无需担心CORS问题。该代码段还将图像存储为Blob对象,可以在需要时将其发布到服务器。

You can resize an image also at the client-side. The example code below uses an image loaded from the user's local system, to run the example without need to worry about CORS issues. The snippet also stores the image as a Blob object, which can be posted to the server if needed.

// Creates a canvas containing a resized image
function resizeImage(img) {
  var canvas = document.createElement('canvas'),
    ctx = canvas.getContext('2d'),
    oWidth = img.naturalWidth,
    oHeight = img.naturalHeight,
    ratio = oWidth / oHeight,
    width = (ratio > 1) ? Math.min(200, oWidth) : Math.min(100, oWidth),
    height = Math.round(width / ratio);
  canvas.width = width;
  canvas.height = height;
  canvas.className = 'temp-cnv';
  document.body.appendChild(canvas);
  ctx.drawImage(img, 0, 0, width, height);
  return canvas;
}

// Define UI elements
var img = document.getElementById('img'),
  loadBut = document.getElementById('load'),
  resizeBut = document.getElementById('resize'),
  resizedImage; // This will be sent to the server

// Creates a blob and attaches it to an image element
resizeBut.addEventListener('click', function() {
  var canvas;
  if (img.src === 'https://stacksnippets.net/js') {
    return; // Quit, no image loaded
  }
  canvas = resizeImage(img);
  canvas.toBlob(function(blob) {
    img.src = URL.createObjectURL(blob);
    resizedImage = blob;
    canvas.parentElement.removeChild(canvas);
  }, 'image/jpeg', 0.99);
});

// Reads an image from the user's local system
loadBut.addEventListener('change', function(e) {
  var file = new FileReader();
  file.addEventListener('load', function() {
    img.src = file.result;
  });
  file.readAsDataURL(e.target.files[0]);
});

.temp-cnv {
  display: none;
}

<input type="file" id="load">
<button id="resize">Resize</button>
<br>
<img src="" id="img">

resizeImage 函数创建一个临时画布元素,并为其计算尺寸帆布。在这里,映像始终会缩小,但是您可以实现自己的调整大小算法。 img.naturalWidth / Height 属性包含图像的原始大小。

resizeImage function creates a temporary canvas element, and calculates the dimensions for that canvas. Here the image is always shrinked, but you can implement your own resizing algorithms. img.naturalWidth/Height properties contain the original size of the image.

当画布的大小为正确设置后,图像将被绘制到画布中,此时实际会发生大小调整。然后将画布返回给调用者,并分配给本地 canvas 变量。

When the size of the canvas has been correctly set, the image is drawn into the canvas, at this point the actual resizing happens. Then the canvas is returned to the caller, and assigned to the local canvas variable.

然后创建一个Blob对象从新创建的画布创建的。 toBlob 函数以回调函数,mime类型和可选的quality参数(仅适用于JPEG)作为参数。回调函数将画布附加到图像中,并将创建的Blob对象存储到 resizedImage 变量中以供进一步使用,最后删除临时画布元素。

Then a Blob object is created from the newly-created canvas. toBlob function takes a callback function, mime-type and an optional quality parameter (for JPEGs only) as arguments. The callback function attaches the canvas into the image, and stores the created Blob object to resizedImage variable for the further use, and finally removes the temporary canvas element.

可以在MDN上阅读:

ctx.drawImage方法

Blob对象

Canvas.toBlob方法

启用了CORS的图像

如果您要将调整大小后的图像发送到服务器,您可以创建一个FormData对象,并将图像附加到该对象。然后使用AJAX将对象发布到服务器。像这样:

If you're going to send the resized image to the server, you can create a FormData object, and append the image to that object. Then post the object to the server with AJAX. Something like this:

var xhr = new XMLHttpRequest(),
    form = new FormData();
form.append('imageBlob', resizedImage); // resizedImage is the Blob object created in the first snippet
form.append('imageName', 'THE_NAME_OF_THE_IMAGE');
xhr.addEventListener('load', function (data) {
    // AJAX response handler code
});
xhr.open('POST', 'THE_URL_TO_POST_TO');
xhr.send(form);

请注意,POST参数(在此情况下为FormData对象)作为 xhr.send 通话。

Notice, that the POST parameters (the FormData object in this case) are attached as an argument of xhr.send call.

这篇关于使用画布元素使用JavaScript调整图像大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆