Skip to content

Instantly share code, notes, and snippets.

@Ser-Gen
Last active August 29, 2015 14:08
Show Gist options
  • Save Ser-Gen/9072670a815a7a2dfdd1 to your computer and use it in GitHub Desktop.
Save Ser-Gen/9072670a815a7a2dfdd1 to your computer and use it in GitHub Desktop.
Генерация миниатюр изображений

Для того, чтобы показывать миниатюры изображений, выбранных соответствующим полем формы, можно использовать возможности FileReader, при помощи метода readAsDataURL() кодируя изображение. Проблема в том, что процесс чтения и кодирования достаточно длителен, отчего выбор нескольких больших фотографий может привести к длительному зависанию вкладки, в которой исполняется скрипт. Пример использования этого способа в файле t0-dataURL.html.

Гораздо быстрей будут генерироваться ссылки на файлы при помощи createObjectURL(), который достаточно широко поддерживается. Этот способ реализован в файле t1-objectURL.html. Сгенерированные ссылки на выбранные файлы указываются в атрибуте src миниатюр, которые при помощи стилей уменьшаются до требуемого размера. Таким образом, изображения уменьшаются браузером, что сильно замедляет его работу при выборе больших изображений.

Чтобы облегчить браузерную участь, можно отрисовать миниатюру на заранее уменьшенном холсте. Отрисовка займёт немного дополнительного времени, но оно окупится в процессе дальнейшей работы. Пример в t2-canvas.html.

Рекомендую эту статью, подробно раскрывающую возможности работы с файлами на клиенте.

Если браузер пользователя не поддерживает какую-то из используемых технологий, скорее всего можно использовать Флеш. Но, мне кажется, лучше просто отказаться от этой возможности и выводить название файла, ведь ОС пользователя и так покажет миниатюру в интерфейсе выбора файла.

Иногда миниатюры генерируют на сервере, возвращая их клиенту. Думаю, этот способ не очень хорош необходимостью в любом случае закачивать изображение, которое может быть довольно большим.

<!doctype html>
<meta charset="utf-8">
<title>FastPreview</title>
<style>
body {
margin: 0;
}
img {
vertical-align: middle;
width: 150px;
height: auto;
}
output {
display: block;
margin-top: 1em;
}
</style>
<input type="file" id="i" multiple>
<output id="o"></output>
<script>
var i = document.getElementById('i');
var o = document.getElementById('o');
i.addEventListener('change', function () {
var files = this.files;
o.innerHTML = '';
for (var i = 0, f; i < files.length; i++) {
f = files[i];
// если загружается картинка
if (f.type.match('image.*')) {
// читаем файл, добавляем его миниатюру
var reader = new FileReader();
reader.onload = function(e) {
var img = document.createElement("img");
img.src = e.target.result;
o.appendChild(img);
}
reader.readAsDataURL(f);
}
};
})
</script>
<!doctype html>
<meta charset="utf-8">
<title>FastPreview</title>
<style>
body {
margin: 0;
}
img {
vertical-align: middle;
width: 150px;
height: auto;
}
output {
display: block;
margin-top: 1em;
}
</style>
<input type="file" id="i" multiple>
<output id="o"></output>
<script>
var i = document.getElementById('i');
var o = document.getElementById('o');
i.addEventListener('change', function () {
var files = this.files;
o.innerHTML = '';
for (var i = 0, f; i < files.length; i++) {
f = files[i];
var URL = window.URL || window.webkitURL;
// если есть нужный метод и загружается картинка
if (URL.createObjectURL && f.type.match('image.*')) {
// получаем ссылку на файл
var imgURL = URL.createObjectURL(f);
var img = document.createElement("img");
// избавляемся от ненужной ссылки
img.onload = function(e) {
window.URL.revokeObjectURL(this.src);
}
// начинаем загружать файл
img.src = imgURL;
// добавляем миниатюру
o.appendChild(img);
}
};
})
</script>
<!doctype html>
<meta charset="utf-8">
<title>FastPreview</title>
<style>
body {
margin: 0;
}
output {
display: block;
margin-top: 1em;
}
canvas {
vertical-align: middle;
}
</style>
<input type="file" id="i" multiple>
<output id="o"></output>
<script>
var i = document.getElementById('i');
var o = document.getElementById('o');
var URL = window.URL || window.webkitURL;
var previewW = 150;
i.addEventListener('change', function () {
var files = this.files;
o.innerHTML = '';
for (var i = 0; i < files.length; i++) {
var f = files[i];
// если есть нужный метод и загружается картинка
if (URL.createObjectURL && f.type.match('image.*')) {
// получаем ссылку на файл и создаём объект изображения
var url = URL.createObjectURL(f);
var img = new Image();
img.onload = function(e) {
// изображение будет отрисовываться в канвас
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// размеры холста нужно будет задавать скриптом
// получаем соотношение сторон изображения
var ratio = this.naturalWidth / this.naturalHeight;
var canvasW = previewW;
var canvasH = canvasW / ratio;
// отрисовываем
canvas.width = canvasW;
canvas.height = canvasH;
ctx.drawImage(this, 0, 0, canvasW, canvasH);
// добавляем миниатюру
o.appendChild(canvas);
// избавляемся от ненужной ссылки
URL.revokeObjectURL(this.src);
}
// начинаем загружать файл
img.src = url;
}
};
})
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment