当用户上传图片时,我想用画布调整图片大小。您只需上传一张图片即可使用以下代码。但是如果您选择多个图像,画布项目不显示图像(仅在最后一个画布元素上),是否有人知道出了什么问题?
https://jsfiddle.net/4ycgqyau/
function prepPreview(input) {
var container = document.getElementById("preview");
var files = jQuery(input).get(0).files;
for (var i = 0; i < files.length; i++) {
// create canvas element & resize image
var canvasEl = document.createElement("canvas");
canvasEl.id = 'canvas_' + i;
canvasEl.width = "250";
canvasEl.height = "140";
container.appendChild(canvasEl);
var canvas = document.getElementById('canvas_' + i);
var context = canvas.getContext('2d');
var reader = new FileReader();
reader.onload = function(event) {
var imageObj = new Image();
imageObj.onload = function() {
var wrh = imageObj.width / imageObj.height;
var newWidth = canvas.width;
var newHeight = newWidth / wrh;
if (newHeight > canvas.height) {
newHeight = canvas.height;
newWidth = newHeight * wrh;
}
context.drawImage(imageObj, 0, 0, newWidth, newHeight);
};
imageObj.src = reader.result;
}
reader.readAsDataURL(files[i], 'canvas_' + i);
console.log(files[i], 'canvas_' + i);
// create input
var input = document.createElement("input");
input.type = "text";
input.setAttribute('maxLength', 150);
input.name = "caption[" + i + "]";
container.appendChild(input);
// create row around image/input
var row = document.createElement("div");
row.className = 'user-uploads__row';
canvasEl.parentNode.insertBefore(row, canvasEl, input);
row.appendChild(canvasEl);
row.appendChild(input);
}
}
答案 0 :(得分:2)
JavaScript具有function-level
范围,它意味着在function-block
中创建的变量将在函数中具有范围。在for-loop
中,正在创建block-level({//code})
,其中变量的值在嵌套迭代中被覆盖,因此onload
仅考虑最后一个画布,因为asynchronous
性质事件
更简单的解决方案是使用Array#forEach
,其中handler-function
每个文件都有自己的scope
使用[].forEach.call
使用必须迭代的array-like
对象的数组原型
同样不是jQuery(input).get(0).files
太丑了,因为你没有使用jQuery
的任何内容,因此只能访问files
的{{1}}属性
input
jQuery("#uploads").change(function() {
prepPreview(this);
});
function prepPreview(input) {
var container = document.getElementById("preview");
var files = input.files;
[].forEach.call(files, function(inp, i) {
var canvasEl = document.createElement("canvas");
canvasEl.id = 'canvas_' + i;
canvasEl.width = "250";
canvasEl.height = "140";
container.appendChild(canvasEl);
var canvas = document.getElementById('canvas_' + i);
var context = canvas.getContext('2d');
var reader = new FileReader();
reader.onload = function(event) {
var imageObj = new Image();
imageObj.onload = function() {
var wrh = imageObj.width / imageObj.height;
var newWidth = canvas.width;
var newHeight = newWidth / wrh;
if (newHeight > canvas.height) {
newHeight = canvas.height;
newWidth = newHeight * wrh;
}
context.drawImage(imageObj, 0, 0, newWidth, newHeight);
};
imageObj.src = reader.result;
}
reader.readAsDataURL(files[i], 'canvas_' + i);
var input = document.createElement("input");
input.type = "text";
input.setAttribute('maxLength', 150);
input.name = "caption[" + i + "]";
container.appendChild(input);
var row = document.createElement("div");
row.className = 'user-uploads__row';
canvasEl.parentNode.insertBefore(row, canvasEl, input);
row.appendChild(canvasEl);
row.appendChild(input);
});
}
.user-uploads__row {
background: #fff;
padding: 20px;
border: 1px solid #888;
margin: 20px;
}
答案 1 :(得分:1)
查看此代码jsbin - create canvas images
<强>更新强>
你遇到的问题是javascript关闭问题。
查看以下链接,了解如何在循环中使用异步函数;
JavaScript closure inside loops – simple practical example
Asynchronous Process inside a javascript for loop
http://www.javascriptcookbook.com/article/Preserving-variables-inside-async-calls-called-in-a-loop/
答案 2 :(得分:1)
请查看此版本:https://jsfiddle.net/4ycgqyau/6/
您需要创建一个闭包环境来存储canvas,context
,并将其传递给onload
事件。
理解它的简单方法,如何创建一个闭包?
imageObj.onload = (function(canvas,context) {
return function (){
// write your code
}})(canvas,context)