предисловие
Недавняя работа была выполнена с использованием проекта Vue + Vux Mobile Terminal, есть спрос на картинки для загрузки фотографий, найти VUX не было достигнуто, через неофициальный опросvux-uploaderПосле не очень хорошо себя чувствую.
На самом деле многие готовые решения, которые были реализованы, уже можно найти в Интернете, но при изучении этого требования я обнаружил, что в различных решениях реализации также есть некоторые точки знаний, поэтому я сделал колесо самостоятельно.vux-uploader-component, и запишите один или два.
нужно
Требования к интерактивным функциям компонентов следующие:
- html5 звонок на камеру телефона
- Изображение рендеринга миниатюру
- Фронтальные сжатые изображения
- Предварительный просмотр большого изображения
- удалить текущую картинку
- автоматическая загрузка
Схема реализации некоторых ключевых технических моментов
использоватьhtml media captureВызов камеры на мобильный телефон
<input type="file" accept="image/*" capture />
Поскольку это входит в спецификацию HTML5, наиболее важным вопросом должна быть совместимость.
Видно, что совместимость приемлема для большинства основных платформ.andriod
2-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 до 1encoderOptions
dataURL = 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
Добро пожаловать на сканирование кода, опыт, звезда, проблема, пиар :)