使用画布元素使用javascript调整图像大小

B_C*_*erA 2 javascript canvas image html5-canvas

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

我正在实现一个调整大小功能,用户可以在其中调整lightbox. 该lightbox会推出之后预览图像被点击。在lightbox元素内部,除了图像本身,还有宽度和高度两个输入字段。

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

问题是我不完全知道如何处理动态创建的canvas元素以及如何使用它在前端调整我的图像大小。

下面是我迄今为止尝试过的结果不佳的方法:

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>
Run Code Online (Sandbox Code Playgroud)

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']);
}
Run Code Online (Sandbox Code Playgroud)

非常感谢任何提示、技巧和建议!

Tee*_*emu 5

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

// 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]);
});
Run Code Online (Sandbox Code Playgroud)
.temp-cnv {
  display: none;
}
Run Code Online (Sandbox Code Playgroud)
<input type="file" id="load">
<button id="resize">Resize</button>
<br>
<img src="" id="img">
Run Code Online (Sandbox Code Playgroud)

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

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

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

很高兴在 MDN 上阅读:

ctx.drawImage 方法
Blob 对象
Canvas.toBlob 方法
CORS 启用图像

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

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);
Run Code Online (Sandbox Code Playgroud)

请注意,POST 参数(在本例中为FormData 对象)作为xhr.send调用参数附加。