UNPKG

@tarojs/taro-h5

Version:
211 lines (208 loc) 8.97 kB
import { __awaiter } from 'tslib'; import { isMobile } from 'is-mobile'; import { getDeviceInfo } from '../../base/system.js'; import '../../ui/index.js'; import { shouldBeObject, getParameterError } from '../../../utils/index.js'; import { MethodHandler } from '../../../utils/handler.js'; import { showActionSheet } from '../../ui/interaction/index.js'; /** * 拍摄或从手机相册中选择图片或视频。 */ const chooseMedia = function (options_1) { return __awaiter(this, arguments, void 0, function* (options, methodName = 'chooseMedia') { var _a; // options must be an Object const isObject = shouldBeObject(options); if (!isObject.flag) { const res = { errMsg: `${methodName}:fail ${isObject.msg}` }; console.error(res.errMsg); return Promise.reject(res); } const { count = 9, mediaId = 'taroChooseMedia', mediaType = ['image', 'video'], sourceType = ['album', 'camera'], // sizeType = ['original', 'compressed'], // TODO 考虑通过 ffmpeg 支持压缩 // maxDuration = 10, // TODO 考虑通过 ffmpeg 剪裁视频 camera = 'back', success, fail, complete, } = options; const handle = new MethodHandler({ name: methodName, success, fail, complete }); const withImage = mediaType.length < 1 || mediaType.indexOf('image') > -1; const withVideo = mediaType.length < 1 || mediaType.indexOf('video') > -1; const res = { tempFiles: [], type: withImage && withVideo ? 'mix' : withImage ? 'image' : 'video', }; if (count && typeof count !== 'number') { res.errMsg = getParameterError({ para: 'count', correct: 'Number', wrong: count }); return handle.fail(res); } let el = document.getElementById(mediaId); if (!el) { el = document.createElement('input'); el.setAttribute('type', 'file'); el.setAttribute('id', mediaId); el.setAttribute('style', 'position: fixed; top: -4000px; left: -3000px; z-index: -300;'); } if (count > 1) { el.setAttribute('multiple', 'multiple'); } else { el.removeAttribute('multiple'); } // Note: Input 仅在移动端支持 capture 属性,可以使用 getUserMedia 替代(暂不考虑) if (isMobile()) { if (sourceType.length > 1 || sourceType.length < 1) { try { const { tapIndex } = yield showActionSheet({ itemList: ['拍摄', '从相册选择'], }, methodName); sourceType.splice(0, sourceType.length, tapIndex === 0 ? 'camera' : 'album'); } catch (e) { return handle.fail({ errMsg: (_a = e.errMsg) === null || _a === void 0 ? void 0 : _a.replace('^.*:fail ', '') }); } } } if (sourceType.includes('camera')) { el.setAttribute('capture', camera === 'front' ? 'user' : 'environment'); } else { el.removeAttribute('capture'); } if (res.type === 'image') { el.setAttribute('accept', 'image/*'); } else if (res.type === 'video') { el.setAttribute('accept', 'video/*'); } else { el.setAttribute('accept', 'image/*, video/*'); } return new Promise((resolve, reject) => { if (!el) return; document.body.appendChild(el); el.onchange = function (e) { return __awaiter(this, void 0, void 0, function* () { const target = e.target; if (target) { const files = target.files || []; const arr = [...files]; yield Promise.all(arr.map((item) => __awaiter(this, void 0, void 0, function* () { var _a; try { (_a = res.tempFiles) === null || _a === void 0 ? void 0 : _a.push(yield loadMedia(item)); } catch (error) { console.error(error); } }))); } handle.success(res, { resolve, reject }); target.value = ''; }); }; el.onabort = () => handle.fail({ errMsg: 'abort' }, { resolve, reject }); el.oncancel = () => handle.fail({ errMsg: 'cancel' }, { resolve, reject }); el.onerror = e => handle.fail({ errMsg: e.toString() }, { resolve, reject }); el.click(); }).finally(() => { if (!el) return; document.body.removeChild(el); }); function loadMedia(file) { const dataUrl = URL.createObjectURL(file); const res = { tempFilePath: dataUrl, size: file.size, duration: 0, height: 0, width: 0, thumbTempFilePath: '', fileType: file.type, originalFileObj: file }; if (/^video\//.test(res.fileType)) { // Video const isIOS = getDeviceInfo().system.toLowerCase().includes('ios'); const video = document.createElement('video'); const reader = new FileReader(); video.crossOrigin = 'Anonymous'; video.preload = 'metadata'; video.src = res.tempFilePath; return new Promise((resolve, reject) => { // 对齐旧版本实现 reader.onload = (event) => { var _a; res.tempFilePath = (_a = event.target) === null || _a === void 0 ? void 0 : _a.result; }; reader.onerror = e => reject(e); reader.readAsDataURL(res.originalFileObj); video.onloadedmetadata = () => { res.duration = video.duration; res.height = video.videoHeight; res.width = video.videoWidth; }; video.oncanplay = () => { res.thumbTempFilePath = getThumbTempFilePath(video, res.height, res.width, 0.8); resolve(res); }; video.onerror = e => reject(e); isIOS && video.load(); }); } else { // Image const img = new Image(); /** 允许图片和 canvas 跨源使用 * https://developer.mozilla.org/zh-CN/docs/Web/HTML/CORS_enabled_image */ img.crossOrigin = 'Anonymous'; img.src = res.tempFilePath; return new Promise((resolve, reject) => { if (img.complete) { res.height = img.height; res.width = img.width; res.thumbTempFilePath = getThumbTempFilePath(img, res.height, res.width, 0.8); resolve(res); } else { img.onload = () => { res.height = img.height; res.width = img.width; res.thumbTempFilePath = getThumbTempFilePath(img, res.height, res.width, 0.8); resolve(res); }; img.onerror = e => reject(e); } }); } } function getThumbTempFilePath(el, height = 0, width = height, quality = 0.8) { const max = 256; const canvas = document.createElement('canvas'); if (height > max || width > max) { const radio = height / width; if (radio > 1) { height = max; width = height / radio; } else { width = max; height = width * radio; } } canvas.height = height; canvas.width = width; const ctx = canvas.getContext('2d'); ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(el, 0, 0, canvas.width, canvas.height); return canvas.toDataURL('image/jpeg', quality); } }); }; export { chooseMedia }; //# sourceMappingURL=chooseMedia.js.map