改进上传模块

This commit is contained in:
wzhqwq 2021-08-01 12:38:24 +08:00
父節點 b8f99f4e4c
當前提交 7c6a84b9a0

查看文件

@ -8,6 +8,8 @@ export default class UploadUnit extends Component {
imgRef = createRef(); imgRef = createRef();
imgWidth; imgWidth;
imgHeight; imgHeight;
imgType;
uploadXhr = null;
constructor(props) { constructor(props) {
super(props); super(props);
@ -40,6 +42,7 @@ export default class UploadUnit extends Component {
handleCancel() { handleCancel() {
this.setState({ status: -1 }); this.setState({ status: -1 });
if (this.uploadXhr) this.uploadXhr.abort();
setTimeout(() => { setTimeout(() => {
this.props.onCancel(); this.props.onCancel();
}, 300); }, 300);
@ -51,12 +54,13 @@ export default class UploadUnit extends Component {
this.handleCancel(); this.handleCancel();
return; return;
} }
this.imgType = file.type;
let reader = new FileReader(); let reader = new FileReader();
this.setState({ status: -2 }); this.setState({ status: -2 });
setTimeout(() => { setTimeout(() => {
this.setState({ status: 0 }); this.setState({ status: 0 });
reader.onload = () => { reader.onload = () => {
var image = new Image(); let image = new Image();
// 被注释掉的是用来应对ios巨大图片没来得及加载的问题 // 被注释掉的是用来应对ios巨大图片没来得及加载的问题
// image.onload = () => setTimeout(() => this.convert(image), 1000); // image.onload = () => setTimeout(() => this.convert(image), 1000);
image.onload = () => this.convert(image); image.onload = () => this.convert(image);
@ -69,8 +73,8 @@ export default class UploadUnit extends Component {
convert(img) { convert(img) {
if (this.converted) return; if (this.converted) return;
var canvas = document.createElement('canvas'); let canvas = document.createElement('canvas');
var { width, height } = img; let { width, height } = img;
if (width > 1600) { if (width > 1600) {
height *= 1600 / width; height *= 1600 / width;
width = 1600; width = 1600;
@ -85,16 +89,16 @@ export default class UploadUnit extends Component {
this.imgHeight = height; this.imgHeight = height;
canvas.getContext('2d').drawImage(img, 0, 0, width, height); canvas.getContext('2d').drawImage(img, 0, 0, width, height);
canvas.toBlob(blob => { canvas.toBlob(blob => {
this.setState({ src: canvas.toDataURL('image/jpeg', 1), status: 2, file: blob, width: width / height * 200 }); this.setState({ src: canvas.toDataURL(this.imgType, 1), status: 2, file: blob, width: width / height * 200 });
}, 'image/jpeg', 1); }, this.imgType, 1);
} }
async upload() { async upload() {
var xhr = new XMLHttpRequest(); let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => { xhr.onreadystatechange = () => {
if (xhr.readyState === 4) { if (xhr.readyState === 4) {
if (xhr.status === 200) { if (xhr.status === 200) {
var data = JSON.parse(xhr.responseText); let data = JSON.parse(xhr.responseText);
if (data.code === 200) { if (data.code === 200) {
this.setState({ status: 4 }); this.setState({ status: 4 });
this.props.onUpload(data.data.url); this.props.onUpload(data.data.url);
@ -114,19 +118,19 @@ export default class UploadUnit extends Component {
this.setState({ status: 2 }); this.setState({ status: 2 });
this.props.onUploadError('请求失败,请检查网络'); this.props.onUploadError('请求失败,请检查网络');
} }
xhr.onprogress = e => { xhr.upload.onprogress = e => {
if (e.lengthComputable) { console.log(e.loaded, e.total, e.lengthComputable);
var percent = Math.round(e.loaded * 100 / e.total); if (e.lengthComputable)
this.setState({ progress: percent }); this.setState({ progress: e.loaded / e.total });
}
}; };
xhr.open("POST", apis.uploadImage, true); xhr.open("POST", apis.uploadImage, true);
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest"); xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
var fd = new FormData(); let fd = new FormData();
fd.append("image", this.state.file, 'image.jpg'); fd.append("image", this.state.file, 'image.jpg');
xhr.send(fd);
this.setState({ status: 3, progress: 0 }); this.setState({ status: 3, progress: 0 });
this.uploadXhr = xhr;
xhr.send(fd);
} }
scale() { scale() {
@ -134,10 +138,9 @@ export default class UploadUnit extends Component {
let el = this.imgRef.current; let el = this.imgRef.current;
let { x, y } = el.getBoundingClientRect(); let { x, y } = el.getBoundingClientRect();
let { innerWidth, innerHeight } = window; let { innerWidth, innerHeight } = window;
console.log(x, y, innerWidth, innerHeight);
let initialScale = 200 / this.imgHeight, let initialScale = 200 / this.imgHeight,
terminalScale = Math.min(1, Math.min(innerWidth / this.imgWidth, innerHeight / this.imgHeight)); terminalScale = Math.min(1, Math.min((innerWidth - 10) / this.imgWidth, (innerHeight - 10) / this.imgHeight));
this.setState({ transform: `translate(${x - (innerWidth - this.imgWidth * terminalScale) / 2}px, ${y - (innerHeight - this.imgHeight * terminalScale) / 2}px) scale(${initialScale})`, isScaled: true }); this.setState({ transform: `translate(${x + (this.imgWidth * initialScale - innerWidth) / 2}px, ${y + (200 - innerHeight) / 2}px) scale(${initialScale})`, isScaled: true });
setTimeout(() => { setTimeout(() => {
this.setState({ transform: `translate(0, 0) scale(${terminalScale})` }); this.setState({ transform: `translate(0, 0) scale(${terminalScale})` });
}, 0); }, 0);
@ -148,17 +151,16 @@ export default class UploadUnit extends Component {
let el = this.imgRef.current; let el = this.imgRef.current;
let { x, y } = el.getBoundingClientRect(); let { x, y } = el.getBoundingClientRect();
let { innerWidth, innerHeight } = window; let { innerWidth, innerHeight } = window;
let initialScale = 200 / this.imgHeight, let initialScale = 200 / this.imgHeight;
terminalScale = Math.min(1, Math.min(innerWidth / this.imgWidth, innerHeight / this.imgHeight)); this.setState({ transform: `translate(${x + (this.imgWidth * initialScale - innerWidth) / 2}px, ${y + (200 - innerHeight) / 2}px) scale(${initialScale})`, isScaled: true });
this.setState({ transform: `translate(${x - (innerWidth - this.imgWidth * terminalScale) / 2}px, ${y - (innerHeight - this.imgHeight * terminalScale) / 2}px) scale(${initialScale})`, isScaled: true });
setTimeout(() => { setTimeout(() => {
this.setState({ isScaled: false }); this.setState({ isScaled: false });
}, 300); }, 300);
} }
render() { render() {
const angle = this.state.progress / 100 * Math.PI * 2; const angle = Math.min(this.state.progress, 0.99) * Math.PI * 2;
console.log(this.state.transform); console.log(this.state.progress);
return ( return (
<div className="upload-wrap"> <div className="upload-wrap">
<div className={this.state.status === -1 ? 'upload-unit' : 'upload-unit open'} style={{ width: this.state.status <= 1 ? '' : `${this.state.width}px` }}> <div className={this.state.status === -1 ? 'upload-unit' : 'upload-unit open'} style={{ width: this.state.status <= 1 ? '' : `${this.state.width}px` }}>
@ -179,7 +181,7 @@ export default class UploadUnit extends Component {
<div className="progress-circle"> <div className="progress-circle">
<svg viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d={ <path d={
`M 50,3 A 47,47 0 ${this.state.progress < 50 ? 0 : 1},1 ${50 + Math.sin(angle) * 47},${50 - Math.cos(angle) * 47}` `M 50,3 A 47,47 0 ${this.state.progress < 0.5 ? 0 : 1},1 ${50 + Math.sin(angle) * 47},${50 - Math.cos(angle) * 47}`
} fill="transparent" stroke="#FFF" strokeWidth="6" strokeLinecap="round"></path> } fill="transparent" stroke="#FFF" strokeWidth="6" strokeLinecap="round"></path>
</svg> </svg>
</div> </div>