完善上传页面的放大查看功能
This commit is contained in:
父節點
1b66a5467a
當前提交
1815a1c160
@ -1,10 +1,14 @@
|
|||||||
import './upload.css';
|
import './upload.css';
|
||||||
|
|
||||||
import { Component, Fragment } from "react";
|
import { Component, createRef, Fragment } from "react";
|
||||||
import { apis } from '../../helper/apis';
|
import { apis } from '../../helper/apis';
|
||||||
import Spinner from '../Spinner/Spinner';
|
import Spinner from '../Spinner/Spinner';
|
||||||
|
|
||||||
export default class UploadUnit extends Component {
|
export default class UploadUnit extends Component {
|
||||||
|
imgRef = createRef();
|
||||||
|
imgWidth;
|
||||||
|
imgHeight;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
@ -13,10 +17,14 @@ export default class UploadUnit extends Component {
|
|||||||
src: null,
|
src: null,
|
||||||
file: null,
|
file: null,
|
||||||
progress: 0,
|
progress: 0,
|
||||||
width: 0
|
width: 0,
|
||||||
|
isScaled: false,
|
||||||
|
transform: ''
|
||||||
};
|
};
|
||||||
this.upload = this.upload.bind(this);
|
this.upload = this.upload.bind(this);
|
||||||
this.handleCancel = this.handleCancel.bind(this);
|
this.handleCancel = this.handleCancel.bind(this);
|
||||||
|
this.scale = this.scale.bind(this);
|
||||||
|
this.unscale = this.unscale.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -73,10 +81,12 @@ export default class UploadUnit extends Component {
|
|||||||
}
|
}
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
|
this.imgWidth = width;
|
||||||
|
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', 0.8), status: 2, file: blob, width: width / height * 200 });
|
this.setState({ src: canvas.toDataURL('image/jpeg', 1), status: 2, file: blob, width: width / height * 200 });
|
||||||
}, 'image/jpeg', 0.8);
|
}, 'image/jpeg', 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
async upload() {
|
async upload() {
|
||||||
@ -119,13 +129,41 @@ export default class UploadUnit extends Component {
|
|||||||
this.setState({ status: 3, progress: 0 });
|
this.setState({ status: 3, progress: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scale() {
|
||||||
|
if (this.state.isScaled) return;
|
||||||
|
let el = this.imgRef.current;
|
||||||
|
let { x, y } = el.getBoundingClientRect();
|
||||||
|
let { innerWidth, innerHeight } = window;
|
||||||
|
console.log(x, y, innerWidth, innerHeight);
|
||||||
|
let initialScale = 200 / this.imgHeight,
|
||||||
|
terminalScale = Math.min(1, Math.min(innerWidth / this.imgWidth, innerHeight / this.imgHeight));
|
||||||
|
this.setState({ transform: `translate(${x - (innerWidth - this.imgWidth * terminalScale) / 2}px, ${y - (innerHeight - this.imgHeight * terminalScale) / 2}px) scale(${initialScale})`, isScaled: true });
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState({ transform: `translate(0, 0) scale(${terminalScale})` });
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unscale() {
|
||||||
|
if (!this.state.isScaled) return;
|
||||||
|
let el = this.imgRef.current;
|
||||||
|
let { x, y } = el.getBoundingClientRect();
|
||||||
|
let { innerWidth, innerHeight } = window;
|
||||||
|
let initialScale = 200 / this.imgHeight,
|
||||||
|
terminalScale = Math.min(1, Math.min(innerWidth / this.imgWidth, innerHeight / this.imgHeight));
|
||||||
|
this.setState({ transform: `translate(${x - (innerWidth - this.imgWidth * terminalScale) / 2}px, ${y - (innerHeight - this.imgHeight * terminalScale) / 2}px) scale(${initialScale})`, isScaled: true });
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setState({ isScaled: false });
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const angle = this.state.progress / 100 * Math.PI * 2;
|
const angle = this.state.progress / 100 * Math.PI * 2;
|
||||||
|
console.log(this.state.transform);
|
||||||
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` }}>
|
||||||
{this.state.src
|
{this.state.src
|
||||||
? <img src={this.state.src} alt="压缩后的图片" style={{ filter: this.state.status === -1 ? 'opacity(0)' : '' }} />
|
? <img src={this.state.src} alt="压缩后的图片" style={{ filter: this.state.status === -1 ? 'opacity(0)' : '' }} ref={this.imgRef} />
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
{this.state.status >= 0
|
{this.state.status >= 0
|
||||||
@ -173,7 +211,7 @@ export default class UploadUnit extends Component {
|
|||||||
}
|
}
|
||||||
{this.state.status === 2 || this.state.status === 4
|
{this.state.status === 2 || this.state.status === 4
|
||||||
? (
|
? (
|
||||||
<button className="btn btn-circle btn-primary">
|
<button className="btn btn-circle btn-primary" onClick={this.scale}>
|
||||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M959.488 920.32l-39.168 39.168a27.676444 27.676444 0 0 1-39.139556 0l-162.133333-162.133333a27.648 27.648 0 0 1 0-39.168l39.139556-39.139556a27.648 27.648 0 0 1 39.168 0l162.133333 162.104889c10.808889 10.837333 10.808889 28.359111 0 39.168zM169.358222 712.419556c-149.959111-149.959111-149.959111-393.102222 0-543.061334 149.959111-149.959111 393.073778-149.959111 543.061334 0 149.959111 149.959111 149.959111 393.102222 0 543.061334-149.987556 149.959111-393.102222 149.959111-543.061334 0zM631.324444 249.742222c-105.358222-105.386667-276.195556-105.386667-381.582222 0a269.824 269.824 0 0 0 0 381.610667A269.824 269.824 0 1 0 631.324444 249.742222z" fill="#ffffff"></path><path d="M959.488 920.32l-39.168 39.168a27.676444 27.676444 0 0 1-39.139556 0l-162.133333-162.133333a27.648 27.648 0 0 1 0-39.168l39.139556-39.139556a27.648 27.648 0 0 1 39.168 0l162.133333 162.104889c10.808889 10.837333 10.808889 28.359111 0 39.168zM169.358222 712.419556c-149.959111-149.959111-149.959111-393.102222 0-543.061334 149.959111-149.959111 393.073778-149.959111 543.061334 0 149.959111 149.959111 149.959111 393.102222 0 543.061334-149.987556 149.959111-393.102222 149.959111-543.061334 0zM631.324444 249.742222c-105.358222-105.386667-276.195556-105.386667-381.582222 0a269.824 269.824 0 0 0 0 381.610667A269.824 269.824 0 1 0 631.324444 249.742222z" fill="#ffffff"></path></svg>
|
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M959.488 920.32l-39.168 39.168a27.676444 27.676444 0 0 1-39.139556 0l-162.133333-162.133333a27.648 27.648 0 0 1 0-39.168l39.139556-39.139556a27.648 27.648 0 0 1 39.168 0l162.133333 162.104889c10.808889 10.837333 10.808889 28.359111 0 39.168zM169.358222 712.419556c-149.959111-149.959111-149.959111-393.102222 0-543.061334 149.959111-149.959111 393.073778-149.959111 543.061334 0 149.959111 149.959111 149.959111 393.102222 0 543.061334-149.987556 149.959111-393.102222 149.959111-543.061334 0zM631.324444 249.742222c-105.358222-105.386667-276.195556-105.386667-381.582222 0a269.824 269.824 0 0 0 0 381.610667A269.824 269.824 0 1 0 631.324444 249.742222z" fill="#ffffff"></path><path d="M959.488 920.32l-39.168 39.168a27.676444 27.676444 0 0 1-39.139556 0l-162.133333-162.133333a27.648 27.648 0 0 1 0-39.168l39.139556-39.139556a27.648 27.648 0 0 1 39.168 0l162.133333 162.104889c10.808889 10.837333 10.808889 28.359111 0 39.168zM169.358222 712.419556c-149.959111-149.959111-149.959111-393.102222 0-543.061334 149.959111-149.959111 393.073778-149.959111 543.061334 0 149.959111 149.959111 149.959111 393.102222 0 543.061334-149.987556 149.959111-393.102222 149.959111-543.061334 0zM631.324444 249.742222c-105.358222-105.386667-276.195556-105.386667-381.582222 0a269.824 269.824 0 0 0 0 381.610667A269.824 269.824 0 1 0 631.324444 249.742222z" fill="#ffffff"></path></svg>
|
||||||
</button>
|
</button>
|
||||||
) : null
|
) : null
|
||||||
@ -186,6 +224,9 @@ export default class UploadUnit extends Component {
|
|||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
<div className={this.state.isScaled ? 'scaled-wrap open' : 'scaled-wrap'} onClick={this.unscale}>
|
||||||
|
<img className="scaled-image" src={this.state.src} alt="压缩后的图片" style={{ transform: this.state.transform }} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -80,3 +80,23 @@
|
|||||||
filter: opacity(1);
|
filter: opacity(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scaled-wrap {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
display: none;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.scaled-wrap.open {
|
||||||
|
display: flex;
|
||||||
|
background-color: #0008;
|
||||||
|
}
|
||||||
|
.scaled-wrap > img {
|
||||||
|
transition: transform .3s ease-out;
|
||||||
|
transform-origin: top left;
|
||||||
|
}
|
@ -5,6 +5,7 @@ import Spinner from '../Spinner/Spinner';
|
|||||||
import { get } from '../../helper/axios';
|
import { get } from '../../helper/axios';
|
||||||
import { apis } from '../../helper/apis';
|
import { apis } from '../../helper/apis';
|
||||||
import { alert } from '../../helper/alert';
|
import { alert } from '../../helper/alert';
|
||||||
|
import History from '../../helper/history';
|
||||||
|
|
||||||
export default function UserControl(props) {
|
export default function UserControl(props) {
|
||||||
return (
|
return (
|
||||||
@ -33,6 +34,8 @@ export default function UserControl(props) {
|
|||||||
<div className="user-name">{userData.name || "加载中"}</div>
|
<div className="user-name">{userData.name || "加载中"}</div>
|
||||||
{
|
{
|
||||||
(() => {
|
(() => {
|
||||||
|
if (userData.role !== 2 && History.getHref().match(/^\/admin.*/))
|
||||||
|
History.force('/');
|
||||||
if (userData.role !== -1) return null;
|
if (userData.role !== -1) return null;
|
||||||
get(apis.getProfile).then(({ data, status, networkStatus }) => {
|
get(apis.getProfile).then(({ data, status, networkStatus }) => {
|
||||||
if (networkStatus !== 200) return;
|
if (networkStatus !== 200) return;
|
||||||
|
@ -2,11 +2,10 @@ import Swal from 'sweetalert2';
|
|||||||
|
|
||||||
const SelfSwal = Swal.mixin({
|
const SelfSwal = Swal.mixin({
|
||||||
customClass: {
|
customClass: {
|
||||||
confirmButton: 'btn-round-full-single',
|
confirmButton: 'btn btn-primary',
|
||||||
cancelButton: 'btn-round-full-single',
|
cancelButton: 'btn btn-gray',
|
||||||
},
|
},
|
||||||
buttonsStyling: false,
|
buttonsStyling: false,
|
||||||
heightAuto: false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// ajax
|
// ajax
|
||||||
|
@ -11,7 +11,7 @@ export function get(url) {
|
|||||||
"Allow-Control-Allow-Origin": "*"
|
"Allow-Control-Allow-Origin": "*"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
() => get(url)
|
() => ({ fn: get(url), identifier: 'get:' + url })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export function post(url, data) {
|
export function post(url, data) {
|
||||||
@ -22,15 +22,16 @@ export function post(url, data) {
|
|||||||
"Allow-Control-Allow-Origin": "*"
|
"Allow-Control-Allow-Origin": "*"
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
() => post(url, data)
|
() => ({ fn: post(url, data), identifier: 'post:' + url + ' ' + JSON.stringify(data) })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const waitToSend = [];
|
const waitToSend = [];
|
||||||
|
|
||||||
async function send(xhr, retryFunc) {
|
async function send(xhr, retryConf) {
|
||||||
if (waitToSend.length) {
|
if (waitToSend.length) {
|
||||||
waitToSend.push(retryFunc);
|
if (waitToSend.every(retryConfItem => retryConfItem.identifier !== retryConf.identifier))
|
||||||
|
waitToSend.push(retryConf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -50,7 +51,7 @@ async function send(xhr, retryFunc) {
|
|||||||
History.force('/login');
|
History.force('/login');
|
||||||
return failData;
|
return failData;
|
||||||
}
|
}
|
||||||
waitToSend.push(retryFunc);
|
waitToSend.push(retryConf);
|
||||||
if (err.message === 'Network Error')
|
if (err.message === 'Network Error')
|
||||||
return await failed('您的设备似乎断网了,请检查网络后重试或刷新', flushWaitList) || failData;
|
return await failed('您的设备似乎断网了,请检查网络后重试或刷新', flushWaitList) || failData;
|
||||||
if (err?.response?.status === 504)
|
if (err?.response?.status === 504)
|
||||||
|
@ -44,7 +44,10 @@ export class UploadContainer extends Component {
|
|||||||
post(apis.submitMessage, { content: this.state.msg, image: this.state.url })
|
post(apis.submitMessage, { content: this.state.msg, image: this.state.url })
|
||||||
.then(({ data, status, networkStatus }) => {
|
.then(({ data, status, networkStatus }) => {
|
||||||
if (networkStatus !== 200) return;
|
if (networkStatus !== 200) return;
|
||||||
if (!status) return alert('提交内容失败:' + data);
|
if (!status) {
|
||||||
|
this.setState({ submitting: false });
|
||||||
|
return alert('提交内容失败:' + data);
|
||||||
|
}
|
||||||
this.setState({ submitting: false, msg: "", url: "", file: null });
|
this.setState({ submitting: false, msg: "", url: "", file: null });
|
||||||
alert('内容提交成功啦').then(({ isConfirmed }) => {
|
alert('内容提交成功啦').then(({ isConfirmed }) => {
|
||||||
if (isConfirmed) window.close();
|
if (isConfirmed) window.close();
|
||||||
|
載入中…
x
新增問題並參考
Block a user