jimu-mobile
Version:
积木组件库助力移动端开发
195 lines (180 loc) • 5.76 kB
JavaScript
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;