Исходный адрес: github.com/whinc/blog/…
Недавно мы получили запрос на публикацию комментариев: пользователи оставляют комментарии и могут делать фотографии или выбирать изображения из альбома для загрузки, что означает поддержку текстовых и графических комментариев. Его необходимо реализовать одновременно как в H5, так и в мини-программах. Это требование требует много мест для обработки изображений. В этой статье приводится краткое описание практики обработки изображений на стороне H5. Код проекта основан на фреймворке Vue. Чтобы избежать влияния фреймворка, я для пояснения изменил весь код на нативную реализацию API. В то же время есть много других дополнительных деталей и функций (предварительный просмотр, обрезка). , прогресс загрузки и т. д.) в коде проекта здесь. Опустите его и введите только ключевые идеи и коды, связанные с обработкой изображений. Реализация мини программы аналогична H5 и повторяться не будет. Код реализации мини программы приложен в конце статьи.
ФотографияИспользуйте тег <input>, задайте тип файла, чтобы выбрать файл, задайте для принятия значение image/*, чтобы выбрать тип файла и камеру, и задайте Multiple, чтобы поддерживать множественный выбор. Прослушайте событие изменения, чтобы получить выбранный список файлов, каждый файл имеет тип Blob.
<input type=file Accept=image/* Multiple /> <img class=preivew /> <script type=text/javascript> function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files) ) files.forEach(file => console.log('имя файла:', file.name)) } document.querySelector('input').addEventListener('change', onFileChange) </script>Предварительный просмотр изображения
Метод URL.createObjectURL может создать локальный URL-адрес, указывающий на объект локального ресурса. Этот интерфейс используется ниже для создания адреса выбранного изображения и его отображения.
function onFileChange (событие) { const files = Array.prototype.slice.call(event.target.files) const file = files[0] document.querySelector('img').src = window.URL.createObjectURL(файл) }Поворот изображения
Снимки, сделанные камерой, могут быть повернуты из-за направления, в котором камера держится при съемке, и их необходимо исправить. Исправление поворота требует знания информации о повороте изображения. Здесь мы используем библиотеку exif-js, которая может считывать метаданные EXIF изображения, включая направление камеры при съемке. На основе этого направления происходит вращение. Информация об изображении может быть вычислена.
Далее идет бит флага поворота EXIF. Всего их 8 типов. Однако при съемке через камеру могут быть сгенерированы только 1, 3, 6 и 8, которые соответственно соответствуют нормали камеры, 180° по часовой стрелке. вращение, вращение на 90° против часовой стрелки и вращение по часовой стрелке. Фотография сделана под углом 90°.
Следовательно, чтобы исправить угол поворота изображения, вам нужно всего лишь прочитать флаг поворота EXIF изображения, определить угол поворота, повернуть изображение на холсте и повторно экспортировать новое изображение. Что касается операции вращения холста, вы можете обратиться к статье «Поворот изображения холста и разблокировка переворота». Следующая функция реализует коррекцию угла поворота файла изображения, получает файл изображения и возвращает исправленный новый файл изображения.
/** * Исправление проблемы с углом поворота изображения * @param {file} исходное изображение * @return {Promise} решенное обещание Вернуть исправленное новое изображение */function fixImageOrientation (file) { return new Promise((resolve, ignore) => { // Получаем изображение const img = new Image(); img.src = window.URL.createObjectURL(file); img.onerror = () =>solve(file); img.onload = () => { // Получаем метаданные изображения (переменные EXIF — это глобальные переменные, предоставляемые представленной библиотекой exif-js) EXIF.getData(img, function() { // Получаем флаг поворота изображения var Orientation = EXIF.getTag(this, Orientation); // Поворот изображения на холсте в соответствии с углом поворота if (orientation === 3 || ориентация === 6 || ориентация === 8) { const Canvas = document.createElement(canvas); const ctx = Canvas.getContext(2d); switch (orientation) { case 3: // Поворот на 180° Canvas.width = img.width; Canvas.height = img.height( (180 * Math.PI)/180 ctx.drawImage(img, -img.width, -img.height, img.width, img.height); случай 6: // Поворот на 90° Canvas.width = img.height; Canvas.height = img.rotate((90 * Math.PI) / 180); ctx.drawImage(img, 0, -img.height, img.width, img.height); случай 8: // Поворот -90° Canvas.width = img.height; Canvas.height = img.width; ctx.rotate((-90 * Math.PI) / ctx.drawImage(img, -img.width, 0, img); .width, img.height); Break } // Возвращаем новое изображение Canvas.toBlob(file =>solve(file), 'изображение/jpeg', 0.92) } else { returnsolve(file } });Сжатие изображения
В настоящее время эффект камеры мобильных телефонов становится все лучше и лучше, и вместе с этим увеличивается размер изображений, который легко может достигать нескольких МБ или даже более десяти МБ. Непосредственная загрузка исходного изображения выполняется медленно и легко. сбой, а фон также имеет ограничения на размер тела запроса, последующая загрузка отображения изображения также будет медленнее. Если фронтенд сжимает изображение, а затем загружает его, эти проблемы можно решить.
Следующая функция реализует сжатие изображения. Принцип заключается в том, чтобы нарисовать масштабированное изображение на холсте и, наконец, экспортировать сжатое изображение с холста. Существует два способа управления сжатием изображения: один — управлять коэффициентом масштабирования изображения, другой — контролировать качество экспортируемого изображения;
/** * Сжатое изображение * @param {file} Входное изображение * @returns {Promise} решенное обещание Возвращает новое сжатое изображение */function compressImage(file) { return new Promise((resolve, ignore) => { // Get изображение (загрузка изображения предназначена для получения ширины и высоты изображения) const img = new Image(); ignore(error); img.onload = () => { // Ширина и высота холста const CanvasWidth = document.documentElement.clientWidth * window.devicePixelRatio; const CanvasHeight = document.documentElement.clientHeight * window.devicePixelRatio; коэффициент // Здесь я беру больший коэффициент масштабирования по горизонтали и вертикали в качестве коэффициента масштабирования, чтобы обеспечить видимость всего содержимого изображения const ScaleX = CanvasWidth / img.width; const ScaleY = CanvasHeight / img.height; const Scale = Math.min(scaleX, ScaleY // Масштабируем исходное изображение в соответствии с коэффициентом масштабирования и рисуем его на холсте const Canvas = document.createElement); ('холст'); const ctx = Canvas.getContext(2d); Canvas.width = CanvasWidth; Canvas.height = CanvasHeight; const imageWidth; img.width * масштаб; const imageHeight = img.height * масштаб; const dx = (canvasWidth - imageWidth) / 2; const dy = (canvasHeight - imageHeight) / 2; ctx.drawImage(img, dx, dy, imageWidth, imageHeight) ); // Экспортируем новое изображение // Указываем MIME-тип изображения как «image/jpeg», передаем качество Контролируйте качество экспортируемых изображений и реализуйте сжатие изображений constquality = 0,92 Canvas.toBlob(file =>solve(tempFile), image/jpeg,quality });};Загрузка изображения
Создайте данные формы через FormData и инициируйте запрос POST ajax. Следующая функция реализует загрузку файлов.
Примечание. При отправке данных FormData браузер автоматически устанавливает для Content-Type соответствующее значение. Нет необходимости устанавливать Content-Type, в противном случае будет сообщено об ошибке, поскольку граница разделителя тела HTTP-запроса генерируется браузером. и не может быть установлен вручную.
/** * Загрузить файл* @param {File} file Файл для загрузки* @returns {Promise} Возвращает выполненное обещание, если загрузка прошла успешно, в противном случае возвращает отклоненное обещание */function uploadFile (file) { return new Promise((resolve , ignore) = > { // Подготавливаем данные формы const formData = new FormData() formData.append('file', file) // Отправляем запрос const xhr = new XMLHttpRequest() xhr.open('POST', uploadUrl) xhr.onreadystatechange = function () { if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {solve(JSON.parse(this.responseText)) } else {reject(this.responseText) } } xhr.send(formData) })}краткое содержание
С помощью вышеуказанных вспомогательных функций обработка становится намного проще. Окончательный код вызова выглядит следующим образом:
function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files) const file = files[0] // Исправляем поворот изображения fixImageOrientation(file).then(file2 => { // Создаем предварительный просмотр Изображение document.querySelector('img').src = window.URL.createObjectURL(file2) // Возврат сжатия compressImage(file2) }).then(file3 => { // Обновление изображения предварительного просмотра document.querySelector('img').src = window.URL.createObjectURL(file3) // Загрузка возврата uploadFile(file3) }).then(data => { console.log('Загрузка успешна') }).catch(error => { console.error('Загрузка не удалась') })}
H5 предоставляет интерфейс для обработки файлов. С помощью Canvas можно реализовать сложную обработку изображений в браузере. В этой статье обобщаются некоторые методы обработки изображений в сценарии загрузки изображений в H5 на мобильный терминал. частичная ссылка при возникновении аналогичных потребностей в будущем.
Прилагается небольшой справочник по реализации программы.
// Делаем фотографии wx.chooseImage({ sourceType: [camera], Success: ({ tempFiles }) => { const file = tempFiles[0] // Обрабатываем изображения }});/** * Сжимаем изображения* @param { Object } параметры * filePath: String Путь к входному изображению * Success: Функция Вызывается обратно, когда сжатие успешно, и возвращает новый путь к сжатому изображению * Fail: Функция Обратный вызов при сбое сжатия */compressImage({ filePath, Success, Fail }) { // Получаем ширину и высоту изображения wx.getImageInfo({ src: filePath, Success: ({ width, height }) => { const systemInfo = wx .getSystemInfoSync(); const CanvasWidth = systemInfo.screenWidth; const CanvasHeight = systemInfo.screenHeight; Обновите размер холста this.setData({ CanvasWidth, CanvasHeight }) // Вычисляем коэффициент масштабирования const ScaleX = CanvasWidth / Width; const ScaleY = CanvasHeight / Height; const Scale = Math.min(scaleX, ScaleY = width); * Scale ; const imageHeight = height * Scale; // Нарисуйте масштабированное изображение на холсте const ctx = wx.createCanvasContext(hidden-canvas); dx = (canvasWidth - imageWidth) / 2; let dy = (canvasHeight - imageHeight) / 2; ctx.drawImage(filePath, dx, dy, imageWidth, imageHeight); Сжатые изображения во временные файлы wx.canvasToTempFilePath({canvasId:hidden-canvas, width: CanvasWidth, height: CanvasHeight, destWidth: CanvasWidth, destHeight: CanvasHeight, fileType: jpg, качество: 0,92, успех: ({ tempFilePath }) => { // Скрываем холст this.setData({ CanvasWidth: 0, CanvasHeight: 0 } ) // Сжатие завершено успешно({ tempFilePath } }, ошибка: ошибка => { // Скрыть холст this.setData({canvasWidth: 0, CanvasHeight: 0 })fail(error); } }); error: error => {fail(error);}/** * Загрузить файл*/uploadFile({ uploadUrl, filePath, onData, onError }) { wx.uploadFile({ url: uploadUrl filePath: filePath, name: файл, заголовок: {Cookie: cookie}, успех: res => { if (res.statusCode === 200) { onData(res.data) } else { onError(res } }, error: error => {); onError(ошибка);} });}Подвести итог
Вышеуказанное представляет собой HTML5 и небольшую программу, представленную редактором для реализации функций поворота, сжатия и загрузки изображений. Надеюсь, это будет вам полезно. Если у вас есть какие-либо вопросы, оставьте мне сообщение, и редактор ответит. ты вовремя. Я также хотел бы поблагодарить всех за поддержку сайта боевых искусств VeVb!