предисловие
Недавняя работа была выполнена с использованием проекта Vue + Vux Mobile Terminal, есть спрос на картинки для загрузки фотографий, найти VUX не было достигнуто, через неофициальный опросvux-uploaderПосле не очень хорошо себя чувствую.
На самом деле многие готовые решения, которые были реализованы, уже можно найти в Интернете, но при изучении этого требования я обнаружил, что в различных решениях реализации также есть некоторые точки знаний, поэтому я сделал колесо самостоятельно.vux-uploader-component, и запишите один или два.
нужно
Требования к интерактивным функциям компонентов следующие:
- html5 звонок на камеру телефона
- Изображение рендеринга миниатюру
- Фронтальные сжатые изображения
- Предварительный просмотр большого изображения
- удалить текущую картинку
- автоматическая загрузка
Схема реализации некоторых ключевых технических моментов
использоватьhtml media captureВызов камеры на мобильный телефон
<input type="file" accept="image/*" capture />
Поскольку это входит в спецификацию HTML5, наиболее важным вопросом должна быть совместимость.
Видно, что совместимость приемлема для большинства основных платформ.andriod2-4 поддерживаются, только вiosПоддержка 6-10 не так хороша.
Если вам интересно, вы можете проверить совместимость на своем мобильном телефоне.
использоватьULR.createObjectURLПолучить адрес изображения
blobURL = ULR.createObjectURL(object)
Параметр объекта может быть
File,Blob,MediaSource
Отсюда может возникнуть несколько вопросов:
- Известные способы получения адреса изображения:
URL.createObjectURLа такжеFileReader.readAsDataURL, что следует использовать? Почему? - существует
IOSКартинка, полученная при фотосъемке в камере, будет автоматически поворачиваться, почему? Как с этим бороться? -
Fileа такжеBlobКаковы отношения?Blob URLа такжеData URLКакая разница?Data URLкак конвертироватьBlob?
использоватьcanvasсжимать изображения
Компрессию можно сделать двумя способами:
-
Установите максимальное ограничение ширины, чтобы пропорционально уменьшить ширину и высоту изображения.
canvas.width = Math.min(image.naturalWidth, option.maxWidth) const ratio = canvas.width / image.naturalWidth canvas.height = image.naturalHeight * ratio -
canvas.toDataURLУкажите поколениеjpegилиwebpФормат изображения, вы можете указать от 0 до 1encoderOptionsdataURL = canvas.toDataURL("image/jpeg", encoderOptions)
Окончательный размер сгенерированного изображения = исходный размер изображения *ratio * encoderOption.
использоватьFormDataзагружать
const formData = new FormData()
formData.append('file', blob)
ЭтоXHRПродукт уровня 2, которые можно легко вставить в виде пар ключ-значение.
Самым большим преимуществом является то, что это может бытьXMLHttpRequest.send()отправлять двоичные файлы асинхронно.
Позже вы также можете пройтиBlobизsliceдля расширения функции многокомпонентной загрузки.
Анализ очков знаний
Разница между FileReader и URL.createObjectURL
оFileReaderа такжеURL.createObjectURLИспользование не будет подробно описываться, если вам интересно, вы можете сами погуглить.
Нам просто нужно знать сейчас
-
пройти через
FileReader.readAsDataURL(file)может получитьdata:base64Нить -
пройти через
URL.createObjectURL(blob)Может получить память текущего файлаURL
Поскольку эти два API могут удовлетворить потребности нашего приобретения, ониразницакуда?
1. Время выполнения
-
createObjectURLвыполняется синхронно (немедленно) -
FileReader.readAsDataURLвыполняется асинхронно (через некоторое время)
2. Использование памяти
-
createObjectURLвернуть группуhashизurl, и сохраняется в памяти до тех пор, покаdocumentзапущенныйunloadсобытия (например:document close) или выполнитьrevokeObjectURLосвободить. -
FileReader.readAsDataURLзатем возвращает строку, содержащую много символовbase64и будет сравниться сblob urlПотребляет больше памяти, но будет автоматически очищаться из памяти, когда не используется (через механизм сборки мусора).
3. Совместимость
-
createObjectURLПоддерживает все современные браузеры, начиная с IE10. -
FileReader.readAsDataURLТакже поддерживает все современные браузеры, начиная с IE10.
Из приведенных выше ответов нетрудно увидеть, что преимущества и недостатки двух
- использовать
createObjectURLСохранить производительность и быстрее, но необходимость вручную выпустить без использования памяти - Если вас не волнуют проблемы с производительностью устройства и вы хотите получать изображения
base64, рекомендуется использоватьFileReader.readAsDataURL
Ссылаться на
Изображение, сделанное камерой, будет вращаться
сверхуcreateObjectURLПолучив адрес изображения, мы можем вставить его в элемент страницы.background-imageСобственность показывает это изображение, и симулятор на стороне ПК не показывает проблем, но изображение, сделанное реальным мобильным телефоном, будет иметь поворот на 90 ° против часовой стрелки.
Почему изображение с камеры перевернуто?
Это связано с тем, что EXIF (формат файла сменного изображения) изображения, полученного с камеры, установит значение по умолчанию.orientation tag
:point_up_2: Картинка вышеorientation tagСоответствующая связь с углом поворота изображения
Как решить эту проблему?
1. Получите картинуorientation
- Если необходимо учитывать совместимость, рекомендуется использоватьExif.js
- Если вы не хотите иметь внешние зависимости, а требования совместимости не так высоки, вы можете использовать
DataViewполучить см.ответ высокой оценки stackoverflow
2. Согласно картинкеorientationсделать соответствующий поворот
switch (orientation) {
case 2:
// horizontal flip
ctx.translate(width, 0);
ctx.scale(-1, 1);
break;
case 3:
// 180 rotate left
ctx.translate(width, height);
ctx.rotate(Math.PI);
break;
case 4:
// vertical flip
ctx.translate(0, height);
ctx.scale(1, -1);
break;
case 5:
// vertical flip + 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.scale(1, -1);
break;
case 6:
// 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.translate(0, -height);
break;
case 7:
// horizontal flip + 90 rotate right
ctx.rotate(0.5 * Math.PI);
ctx.translate(width, -height);
ctx.scale(-1, 1);
break;
case 8:
// 90 rotate left
ctx.rotate(-0.5 * Math.PI);
ctx.translate(-width, 0);
break;
Ссылаться на
Отношения между файлом и большим двоичным объектом? Разница между URL-адресом BLOB-объекта и URL-адресом данных? Как преобразовать DataURL в Blob?
Связь между файлом и большим двоичным объектом
отinput onchangeВозвращаемый объект изображения на самом деле являетсяFileобъект.
а такжеBlobОбъект — это контейнер, используемый для упаковки двоичных файлов,Fileунаследовано отBlob.
FileReaderэто API, используемый для чтения файлов в памяти, поддерживающийFileа такжеBlobДва формата.
Разница между URL-адресом BLOB-объекта и URL-адресом данных
Blob Urlдоступно только в браузереURL.createObjectURL(blob)Создать, когда он не используется, требуетURL.revokeObjectURL(blobURL)освободить.
Это можно просто понять как мягкую ссылку в соответствующем файле памяти браузера. Ссылка может существовать только в отдельном экземпляре браузера или соответствующем сеансе (например, жизненный цикл страницы).
blobURL = URL.createObjectURL(blob)
// blob:http://localhost:8000/xxxxxxxx
Data URLsВы можете получить файлbase64.
data:[<mediatype>][;base64],<data>
mediatypeявляется строкой типа MIME, например, "image/jpeg" означает файл изображения в формате JPEG. Если этот параметр опущен, по умолчаниюtext/plain;charset=US-ASCII
в состоянии пройтиFileReader.readAsDataURLПолучать
const reader = new FileReader();
reader.addEventListener("load", e => {
const dataURL = e.target.result;
})
reader.readAsDataURL(blob);
Как преобразовать DataURL в Blob?
function dataURItoBlob(dataURI) {
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
// create a view into the buffer
var ia = new Uint8Array(ab);
// set the bytes of the buffer to the correct values
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([ab], {type: mimeString});
return blob;
}
Ссылаться на
Индикатор выполнения загрузки составляет 100% от начала загрузки, почему?
Как мы все знаем, в настоящее время мониторинг загружаемых файловрасписаниеОсновной способ - использовать XHRonprogressсобытие для достижения, но почему, когда я отлаживаю загрузку локально,onprogressЗвонили только один раз?
В XHR2 есть объект событияProgressEvent, этот объект можно получить из следующих событий прослушивания:
| название события | Время запуска |
|---|---|
| loadstart | инициация запроса |
| progress | передавать данные |
| abort | Запрос был прерван (например,abort()Способ запуска) |
| error | Запрос не выполнен |
| load | После успешного выполнения запроса |
| timeout | Запускается, когда время запроса истекает в течение указанного времени |
| loadend | После завершения запроса (независимо от того, был ли запрос успешным или нет) |
ProgressEventЦикл событий выглядит следующим образом:
-
Запускается первым после инициирования каждого запроса
loadstart, запрос выполненflagдляfalse -
комплектуется по запросу
flagУстановить какtrueраньше, с50msинтервал до триггера опросаprogressмероприятие -
Когда запрос завершается, запрос завершается
flagдляtrue, в зависимости от статуса результата выполнения запроса, триггерabort,error,load,timeoutодин из них. -
Запускается, когда запрос завершен
loadend
На данный момент мы очень четко знаем, почему, даже если мы загружаем локально, иprogressОткат вconsole.logПричина, по которой она выполняется только один раз:Событие локального запроса на загрузку длится менее 50 мс.
Просто настройте сеть на медленный 3G и загрузите большую картинку с пикселями высокой четкости, вы можете видетьprogressМероприятие начнется с50msинтервальные вызовы.
Ссылаться на
- stackoverflow.com/a/5543745
- Производитель DV.I 3.org/Корея/скарлет хот/RAW-...
- Woo Woo Woo.cn Blog On.com/small совпадает ...
наконец
Небольшая волна продвижения основана наweuiКомпонент загрузки изображений Mobile Vue реализован в стилеvux-uploader-component
Добро пожаловать на сканирование кода, опыт, звезда, проблема, пиар :)