UNPKG

jimu-mobile

Version:

积木组件库助力移动端开发

195 lines (180 loc) 5.76 kB
import React, { Component } from 'react'; import classNames from 'classnames'; import './binaryFile'; import './exif'; import './canvasResize'; // 早期版本的浏览器需要用BlobBuilder来构造Blob,创建一个通用构造器来兼容早期版本 const BlobConstructor = ((function () { try { return new Blob() && true; } catch (e) { return false; } })()) ? window.Blob : function (parts, opts) { const bb = new ( window.BlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder || window.MozBlobBuilder )(); parts.forEach((p) => { bb.append(p); }); return bb.getBlob(opts ? opts.type : undefined); }; // dataURL转换为Blob对象 const dataURLtoBlob = function (base64, type) { const data = window.atob(base64); const ia = new Uint8Array(data.length); for (let i = 0; i < data.length; i++) { ia[i] = data.charCodeAt(i); } return new BlobConstructor([ia], { type: `image/${type}` }); }; const isEmptyObject = function (e) { let t; for (t in e) { return false; } return true; }; const propTypes = { plusDesc: React.PropTypes.string, // 图片上传文字提示 accept: React.PropTypes.string, // 上传文件格式 imageArray: React.PropTypes.array, // 图片默认展示 imageMaxLen: React.PropTypes.number, // 图片上传最大个数 imageMaxWidth: React.PropTypes.number, // 图片展示最大宽度 imageQuality: React.PropTypes.number, // 压缩图片的质量 onLoadSuccess: React.PropTypes.func, // 成功上传时回调 onLoadError: React.PropTypes.func, // 上传失败回调 }; const defaultProps = { imgURI: null, plusDesc: '添加图片', accept: 'image/*', imageQuality: 0.8, imageMaxWidth: 600, imageArray: [], onLoadSuccess: null, onLoadError: null, imageMaxLen: 5, }; class UploadImageArray extends Component { constructor(props) { super(props); this.state = { imgURI: props.imgURI || '', imageBase64: null, originalWidth: 0, originalHeight: 0, originalBase64Length: 0, compressedWidth: 0, compressedHeight: 0, compressedBase64Length: 0, imageArray: props.imageArray || [], orientation: 1, fileType: '', compressedFileType: '', }; this.addImage = this.addImage.bind(this); } componentWillReceiveProps(nextProps) { if (nextProps.imageArray.toString() !== this.props.imageArray.toString()) { this.setState({ imageArray: Array.from(nextProps.imageArray), }); } } outputImageArray(imageArray) { const { onLoadSuccess } = this.props; onLoadSuccess && onLoadSuccess(imageArray); } getBlob(outputImageType) { const { imageBase64 } = this.state; return dataURLtoBlob(imageBase64, outputImageType); } addImage(e) { e.stopPropagation(); const self = this; const file = e.target.files[0]; const { imageMaxWidth, imageQuality } = this.props; const { imageArray } = this.state; window.canvasResize(file, { width: imageMaxWidth, quality: imageQuality, callback(dataUri, width, height, attributes) { const b64Str = dataUri.substr(dataUri.indexOf('base64') + 7); const imageBlob = dataURLtoBlob(b64Str, attributes.compressedFileType); imageArray.push({ blob: imageBlob, blobSize: imageBlob.size, imgURI: dataUri, imageBase64: b64Str, originalWidth: attributes.originalWidth, originalHeight: attributes.originalHeight, originalBase64Length: attributes.originalBase64Length, compressedWidth: width, compressedHeight: height, compressedBase64Length: attributes.compressedBase64Length, orientation: attributes.orientation, fileType: attributes.fileType, compressedFileType: attributes.compressedFileType, file, }); self.setState({ imageArray, }); setTimeout(() => { self.outputImageArray(imageArray); }, 0); }, onerror(e) { onLoadError && onLoadError(); }, }); } deleteImageArray(n) { const { imageArray } = this.state; const newArr = imageArray; newArr.splice(n, 1); this.setState({ imageArray: newArr, }); } render() { const { plusDesc, className, accept, imageMaxLen, } = this.props; const { imageArray } = this.state; const cls = classNames({ 'jimu-upload-wrap': true, [className]: className, }); return ( <div className={cls}> {imageArray.map((item, index) => ( <div key={index} className={classNames('jimu-uploadImage-wrapper', className)}> <img className="jimu-uploadImage-preview" src={item.imgURI} /> <div className="jimu-uploadImage-plus-wrapper"> <span className="jimu-uploadImage-delete icon-jimu-error" onClick={() => { this.deleteImageArray(index); }} /> </div> </div> ))} {imageMaxLen > imageArray.length && ( <div className="jimu-uploadImage-add"> <div className="jimu-uploadImage-plus-wrapper" > <span className="car-icons-add jimu-uploadImage-plus" /> <p className="jimu-uploadImage-desc" /> </div> <label className="jimu-uploadImage-label"> <input className="jimu-uploadImage-input width-100" type="file" onChange={this.addImage.bind(this)} accept={accept} multiple /> </label> </div> )} </div> ); } } UploadImageArray.propTypes = propTypes; UploadImageArray.defaultProps = defaultProps; export default UploadImageArray;