Изменение размера изображений с помощью JavaScript

У меня есть ввод типа файла со свойством множественного выбора. Когда пользователь выбирает файл, я сжимаю файлы с помощью функции JavaScript. Теперь я хотел изменить длину и ширину изображений с помощью этой функции. Что мне для этого добавить в функцию?

Моя функция заключается в следующем

    const compressImage = async (file, { quality = 1, type = file.type }) => {
            // Get as image data
            const imageBitmap = await createImageBitmap(file);

            // Draw to canvas
            const canvas = document.createElement('canvas');
            canvas.width = imageBitmap.width;
            canvas.height = imageBitmap.height;
            const ctx = canvas.getContext('2d');
            ctx.drawImage(imageBitmap, 0, 0);

            // Turn into Blob
            const blob = await new Promise((resolve) =>
                canvas.toBlob(resolve, type, quality)
            );

            // Turn Blob into File
            return new File([blob], file.name, {
                type: blob.type,
            });
        };

        // Get the selected file from the file input
        const input = document.querySelector('.my-image-field');
        input.addEventListener('change', async (e) => {
            // Get the files
            const { files } = e.target;

            // No files selected
            if (!files.length) return;

            // We'll store the files in this data transfer object
            const dataTransfer = new DataTransfer();

            // For every file in the files list
            for (const file of files) {
                // We don't have to compress files that aren't images
                if (!file.type.startsWith('image')) {
                    // Ignore this file, but do add it to our result
                    dataTransfer.items.add(file);
                    continue;
                }

                // We compress the file by 50%
                const compressedFile = await compressImage(file, {
                    quality: 0.3,
                    type: 'image/jpeg',
                });

                // Save back the compressed file instead of the original file
                dataTransfer.items.add(compressedFile);
            }

            // Set value of the file input to our new files list
            e.target.files = dataTransfer.files;
        });

Я бы предложил провести небольшое исследование, чтобы найти существующую библиотеку манипуляций с изображениями. Масштабирование/обрезание изображений в JS — нетривиальная задача.

Rory McCrossan 16.04.2024 10:30
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть как минимум два варианта:

  1. Контекстный метод scale() :

Метод CanvasRenderingContext2D.scale() API Canvas 2D добавляет преобразование масштабирования к единицам холста по горизонтали и/или вертикали.

  1. Синтаксис с 5 аргументами drawImage():
drawImage(image, dx, dy, dWidth, dHeight)

Ширина для рисования изображения на целевом холсте. Это позволяет масштабировать нарисованное изображение.

Высота рисования изображения на целевом холсте. Это позволяет масштабировать нарисованное изображение.

В следующем примере используется метод scale() с одинаковым коэффициентом масштабирования для ширины и высоты. Модификация ввода изображения files отключена, чтобы избежать повторного масштабирования, но ее можно снова включить, раскомментировав e.target.files = dataTransfer.files;.

const compressImage = async(file, {
  quality = 1,
  type = file.type,
  scalingFactor = 1
}) => {
  // Get as image data
  const imageBitmap = await createImageBitmap(file);

  // Draw to canvas
  const canvas = document.createElement('canvas');
  canvas.width = imageBitmap.width * scalingFactor;
  canvas.height = imageBitmap.height * scalingFactor;

  const ctx = canvas.getContext('2d');
  ctx.scale(scalingFactor, scalingFactor);
  ctx.drawImage(imageBitmap, 0, 0);

  // Turn into Blob
  const blob = await new Promise((resolve) =>
    canvas.toBlob(resolve, type, quality)
  );

  // Turn Blob into File
  return new File([blob], file.name, {
    type: blob.type,
  });
};

// Get the selected file from the file input
const input = document.querySelector('.my-image-field');
input.addEventListener('change', async(e) => {
  // Get the files
  const {
    files
  } = e.target;

  // No files selected
  if (!files.length) return;

  // We'll store the files in this data transfer object
  const dataTransfer = new DataTransfer();

  // Clear the image previews container
  previewsContainer.innerHTML = '';

  // For every file in the files list
  for (const file of files) {
    // We don't have to compress files that aren't images
    if (!file.type.startsWith('image')) {
      // Ignore this file, but do add it to our result
      dataTransfer.items.add(file);
      continue;
    }

    // We compress the file by 50%
    const compressedFile = await compressImage(file, {
      quality: parseFloat(qualityInput.value),
      type: 'image/jpeg',
      scalingFactor: parseFloat(scalingInput.value)
    });

    // Save back the compressed file instead of the original file
    dataTransfer.items.add(compressedFile);

    // Show scaled images
    const img = document.createElement('img');
    img.src = URL.createObjectURL(compressedFile);
    previewsContainer.appendChild(img);
  }

  // UNCOMMENT TO:
  // Set value of the file input to our new files list
  // e.target.files = dataTransfer.files;
});

const previewsContainer = document.querySelector('.image-previews');

const scalingInput = document.querySelector('.scaling-factor');
const qualityInput = document.querySelector('.quality');
const updateRangeOutput = (inp) => {
  inp.nextElementSibling.innerText = inp.value;
};
[scalingInput, qualityInput].forEach(inp => {
  inp.addEventListener('change', () => {
    updateRangeOutput(inp);
    input.dispatchEvent(new Event('change'));
  });
  updateRangeOutput(inp);
});
<p>
  Choose images:
  <input type = "file" accept = "image/*" multiple class = "my-image-field">
</p>
<p>
  Scaling factor:
  <input type = "range" class = "scaling-factor" value = "0.5" min = "0.1" max = "2" step = "0.1">
  <span>0.5</span>
</p>
<p>
  Quality:
  <input type = "range" class = "quality" value = "0.5" min = "0.1" max = "1" step = "0.1">
  <span>0.5</span>
</p>
<p class = "image-previews"></p>

Другие вопросы по теме