Создаю миниатюру загруженного изображения. Отрисовываю её в canvas. Задаю ему статическую высоту, а ширину - авто, чтобы изображение не растягивалось. Есть ли какой-то способ, чтобы задать для canvas статические высоту и ширину, а уже изображение внутри масштабировать, по типу как работает свойство:
object-fit: cover;
object-position: 50% 50%;
Привожу пример скрипта:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<div>
<input type="file" multiple="" id="photo">
</div>
<div>
<ul id="preview-photo">
</ul>
</div>
<script>
var previewWidth = 150, // ширина превью
previewHeight = 150, // высота превью
maxFileSize = 2 * 1024 * 1024, // (байт) Максимальный размер файла (2мб)
selectedFiles = {},// объект, в котором будут храниться выбранные файлы
queue = [],
image = new Image(),
imgLoadHandler,
isProcessing = false,
errorMsg, // сообщение об ошибке при валидации файла
previewPhotoContainer = document.querySelector('#preview-photo'); // контейнер, в котором будут отображаться превью
// Когда пользователь выбрал файлы, обрабатываем их
$('input[type=file][id=photo]').on('change', function() {
var newFiles = $(this)[0].files; // массив с выбранными файлами
for (var i = 0; i < newFiles.length; i++) {
var file = newFiles[i];
// В качестве "ключей" в объекте selectedFiles используем названия файлов
// чтобы пользователь не мог добавлять один и тот же файл
// Если файл с текущим названием уже существует в массиве, переходим к следующему файлу
if (selectedFiles[file.name] != undefined) continue;
// Валидация файлов (проверяем формат и размер)
if ( errorMsg = validateFile(file) ) {
alert(errorMsg);
return;
}
// Добавляем файл в объект selectedFiles
selectedFiles[file.name] = file;
queue.push(file);
}
$(this).val('');
processQueue(); // запускаем процесс создания миниатюр
});
// Валидация выбранного файла (формат, размер)
var validateFile = function(file)
{
if ( !file.type.match(/image\/(jpeg|jpg|png|gif)/) ) {
return 'Фотография должна быть в формате jpg, png или gif';
}
if ( file.size > maxFileSize ) {
return 'Размер фотографии не должен превышать 2 Мб';
}
};
var listen = function(element, event, fn) {
return element.addEventListener(event, fn, false);
};
// Создание миниатюры
var processQueue = function()
{
// Миниатюры будут создаваться поочередно
// чтобы в один момент времени не происходило создание нескольких миниатюр
// проверяем запущен ли процесс
if (isProcessing) { return; }
// Если файлы в очереди закончились, завершаем процесс
if (queue.length == 0) {
isProcessing = false;
return;
}
isProcessing = true;
var file = queue.pop(); // Берем один файл из очереди
var li = document.createElement('LI');
var span = document.createElement('SPAN');
var spanDel = document.createElement('SPAN');
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
span.setAttribute('class', 'img');
spanDel.setAttribute('class', 'delete');
spanDel.innerHTML = '<img src="/public/images/deletes.svg">';
li.appendChild(span);
li.appendChild(spanDel);
li.setAttribute('data-id', file.name);
image.removeEventListener('load', imgLoadHandler, false);
// создаем миниатюру
imgLoadHandler = function() {
ratio = realW/realH;
previewHeight = 100;
previewWidth = 100 * ratio;
canvas.setAttribute('width', previewWidth); //ширина области отображения превью
canvas.setAttribute('height', previewHeight); //высота области отображения превью
ctx.drawImage(image, 0, 0, previewWidth, previewHeight);
URL.revokeObjectURL(image.src);
span.appendChild(canvas);
isProcessing = false;
setTimeout(processQueue, 200); // запускаем процесс создания миниатюры для следующего изображения
};
// Выводим миниатюру в контейнере previewPhotoContainer
previewPhotoContainer.appendChild(li);
listen(image, 'load', imgLoadHandler);
image.src = URL.createObjectURL(file);
// Сохраняем содержимое оригинального файла в base64 в отдельном поле формы
// чтобы при отправке формы файл был передан на сервер
var fr = new FileReader();
fr.readAsDataURL(file);
fr.onload = (function (file){
return function (e) {
realW = image.width;
realH = image.height;
$('#preview-photo').append(
'<input type="hidden" name="photos[]" value="' + e.target.result + '" data-id="' + file.name+ '">'
);
}
}) (file);
};
// Удаление фотографии
$(document).on('click', '#preview-photo li span.delete', function() {
var fileId = $(this).parents('li').attr('data-id');
if (selectedFiles[fileId] != undefined) delete selectedFiles[fileId]; // Удаляем файл из объекта selectedFiles
$(this).parents('li').remove(); // Удаляем превью
$('input[name^=photo][data-id="' + fileId + '"]').remove(); // Удаляем поле с содержимым файла
});
</script>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Задача том, что бы он выводил на экран одну большую картинку, под ней несколько превью , которые листаются и при нажатии на них на месте большой...