我很难理解如何使用JavaScript中的canvas
元素。
我正在实现一个调整大小功能,用户可以在lightbox
内调整图像的大小。单击预览图像后,lightbox
将启动。在lightbox
元素内,除了图像本身,还有两个用于输入宽度和高度的字段。
目标是生成base64
格式的原始图像的副本,并将其与给定的宽度和高度一起作为查询参数发送到服务器,并让服务器端执行调整大小操作(我正在使用PHP(对于我的后端,则是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>
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']);
}
任何提示,技巧和建议都非常感谢!
答案 0 :(得分:2)
您也可以在客户端调整图像的大小。下面的示例代码使用从用户本地系统加载的图像来运行该示例,而无需担心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]);
});
.temp-cnv {
display: none;
}
<input type="file" id="load">
<button id="resize">Resize</button>
<br>
<img src="" id="img">
resizeImage
函数创建一个临时画布元素,并计算该画布的尺寸。在这里,映像始终会缩小,但是您可以实现自己的调整大小算法。 img.naturalWidth/Height
属性包含图像的原始大小。
正确设置了画布的大小后,图像被绘制到画布中,此时实际会发生尺寸调整。然后画布返回给调用者,并分配给本地canvas
变量。
然后从新创建的画布创建一个Blob对象。 toBlob
函数采用回调函数,mime类型和可选的quality参数(仅适用于JPEG)作为参数。回调函数将画布附加到图像中,并将创建的Blob对象存储到resizedImage
变量中以供进一步使用,最后删除临时画布元素。
可以在MDN上阅读:
ctx.drawImage method
Blob object
Canvas.toBlob method
CORS enabled images
如果要将尺寸调整后的图像发送到服务器,则可以创建一个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);
请注意,POST参数(在这种情况下为FormData object)作为xhr.send
调用的参数附加。