choerodon-ui
Version:
An enterprise-class UI design language and React-based implementation
637 lines (579 loc) • 19.5 kB
JavaScript
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
import _extends from "@babel/runtime/helpers/extends";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _inherits from "@babel/runtime/helpers/inherits";
import _createSuper from "@babel/runtime/helpers/createSuper";
/**
* 裁剪头像上传
*/
import React, { Component } from 'react';
import axios from 'axios';
import isString from 'lodash/isString';
import Cropper from 'react-easy-crop';
import Button from '../button';
import Icon from '../icon';
import Modal from '../modal';
import message from '../message';
import Upload from '../upload';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import defaultLocale from '../locale-provider/default';
import ConfigContext from '../config-provider/ConfigContext';
var Dragger = Upload.Dragger;
var round = Math.round;
var ButtonGroup = Button.Group;
var maxZoomVal = 3;
var zoomStep = 0.5;
function rotateFlag(rotate) {
return rotate / 90 % 2 !== 0;
}
var Avatarlocale = defaultLocale.imageCrop;
var AvatarUploader = /*#__PURE__*/function (_Component) {
_inherits(AvatarUploader, _Component);
var _super = _createSuper(AvatarUploader);
function AvatarUploader(props, context) {
var _this;
_classCallCheck(this, AvatarUploader);
_this = _super.call(this, props, context);
_this.zoomImage = function (type) {
var zoom = _this.state.zoom;
var _this$state = _this.state,
_this$state$imageStyl = _this$state.imageStyle,
width = _this$state$imageStyl.width,
height = _this$state$imageStyl.height,
cropSize = _this$state.cropSize;
var minZoomVal = cropSize / Math.min(width, height);
switch (type) {
case 'add':
{
zoom = zoom + zoomStep >= maxZoomVal ? maxZoomVal : zoom + zoomStep;
_this.setState({
zoom: zoom
});
break;
}
case 'sub':
{
zoom = zoom - zoomStep <= minZoomVal ? minZoomVal : zoom - zoomStep;
_this.setState({
zoom: zoom
});
break;
}
case 'init':
{
var x = (width - cropSize) / 2 / width;
var y = (height - cropSize) / 2 / width;
_this.setState({
zoom: 1,
rotate: 0,
crop: {
x: x,
y: y
}
});
}
break;
default:
break;
}
};
_this.handleOk = function () {
var _this$state2 = _this.state,
x = _this$state2.x,
y = _this$state2.y,
size = _this$state2.size,
rotate = _this$state2.rotate,
file = _this$state2.file,
_this$state2$imageSty = _this$state2.imageStyle,
width = _this$state2$imageSty.width,
height = _this$state2$imageSty.height,
naturalWidth = _this$state2.img.naturalWidth;
var _this$props = _this.props,
uploadUrl = _this$props.uploadUrl,
uploadFaild = _this$props.uploadFaild,
uploadError = _this$props.uploadError,
handleUpload = _this$props.handleUpload,
axiosConfig = _this$props.axiosConfig;
var flag = rotateFlag(rotate);
var scale = naturalWidth / width;
var startX = flag ? x - (width - height) / 2 : x;
var startY = flag ? y + (width - height) / 2 : y;
var QsData = {
rotate: rotate,
startX: round(startX * scale),
startY: round(startY * scale),
endX: round(size * scale),
endY: round(size * scale)
};
var qs = JSON.stringify(QsData);
var data = new FormData();
data.append('file', file);
_this.setState({
submitting: true
});
if (uploadUrl) {
var config;
if (axiosConfig) {
config = axiosConfig;
}
axios.post("".concat(uploadUrl, "?").concat(qs), data, config).then(function (res) {
if (res.success) {
_this.uploadOk(res);
} else {
message.error(Avatarlocale.avatarUploadError);
_this.setState({
submitting: false
});
if (uploadFaild) {
uploadFaild();
}
}
})["catch"](function (error) {
message.error("".concat(Avatarlocale.avatarServerError).concat(error));
_this.setState({
submitting: false
});
if (uploadError) {
uploadError(error);
}
});
}
if (handleUpload) {
QsData.file = file;
handleUpload(QsData);
}
};
_this.handleCancel = function () {
_this.close();
};
var rectSize = props.rectSize;
_this.state = {
submitting: false,
img: null,
file: '',
imageStyle: {
width: 0,
height: 0
},
crop: {
x: 0,
y: 0
},
rotate: 0,
zoom: 1,
cropSize: rectSize
};
return _this;
}
_createClass(AvatarUploader, [{
key: "close",
value: function close() {
var onClose = this.props.onClose;
this.setState({
img: null
});
if (onClose) {
onClose(false);
}
}
}, {
key: "uploadOk",
value: function uploadOk(res) {
var onUploadOk = this.props.onUploadOk;
this.setState({
img: null,
submitting: false
}, function () {
if (onUploadOk) {
onUploadOk(res);
}
});
}
}, {
key: "initImageSize",
value: function initImageSize(img) {
var rotate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var _this$props2 = this.props,
editorWidth = _this$props2.editorWidth,
editorHeight = _this$props2.editorHeight,
rectSize = _this$props2.rectSize;
var naturalWidth = img.naturalWidth,
naturalHeight = img.naturalHeight;
var flag = rotateFlag(rotate);
var width = flag ? naturalHeight : naturalWidth;
var height = flag ? naturalWidth : naturalHeight;
if (width < rectSize || height < rectSize) {
if (width > height) {
width = width / height * rectSize;
height = rectSize;
} else {
height = height / width * rectSize;
width = rectSize;
}
} else if (width > editorWidth || height > editorHeight) {
if (width / editorWidth > height / editorHeight) {
height = height / width * editorWidth;
width = editorWidth;
} else {
width = width / height * editorHeight;
height = editorHeight;
}
}
if (flag) {
var tmp = width;
width = height;
height = tmp;
}
var size = Math.min(rectSize, width, height);
this.setState({
img: img,
imageStyle: {
width: width,
height: height,
top: (editorHeight - height) / 2,
left: (editorWidth - width) / 2,
transform: "rotate(".concat(rotate, "deg)")
},
size: size,
cropSize: size,
x: (width - size) / 2,
y: (height - size) / 2,
rotate: rotate
});
}
}, {
key: "onComplete",
value: function onComplete(imgState) {
var _this$state3 = this.state,
zoom = _this$state3.zoom,
_this$state3$imageSty = _this$state3.imageStyle,
width = _this$state3$imageSty.width,
height = _this$state3$imageSty.height,
cropSize = _this$state3.cropSize;
var x = imgState.x,
y = imgState.y;
x = Math.ceil(x * width / 100);
y = Math.ceil(y * height / 100);
var imageState = {
x: x,
y: y,
size: cropSize / zoom
};
var cropComplete = this.props.cropComplete;
this.setState(imageState);
if (cropComplete) {
cropComplete(imageState);
}
}
}, {
key: "loadImage",
value: function loadImage(src) {
var _this2 = this;
if (typeof window !== 'undefined') {
var img = new Image();
img.src = src;
img.onload = function () {
_this2.initImageSize(img);
};
}
}
}, {
key: "getPreviewProps",
value: function getPreviewProps(previewSize) {
var _this$state4 = this.state,
size = _this$state4.size,
x = _this$state4.x,
y = _this$state4.y,
src = _this$state4.img.src,
rotate = _this$state4.rotate,
_this$state4$imageSty = _this$state4.imageStyle,
width = _this$state4$imageSty.width,
height = _this$state4$imageSty.height;
var previewScale = previewSize / size;
var radius = rotate % 360 / 90;
var px = -x;
var py = -y;
if (radius < 0) radius += 4;
if (radius === 1) {
py = x + (height - width) / 2 - height + size;
px = (height - width) / 2 - y;
} else if (radius === 2) {
px = x - width + size;
py = y - height + size;
} else if (radius === 3) {
px = y + (width - height) / 2 - width + size;
py = (width - height) / 2 - x;
}
return {
style: {
width: previewSize,
height: previewSize,
backgroundImage: "url('".concat(src, "')"),
backgroundSize: "".concat(width * previewScale, "px ").concat(height * previewScale, "px"),
backgroundPosition: "".concat(px * previewScale, "px ").concat(py * previewScale, "px"),
transform: "rotate(".concat(rotate, "deg)")
}
};
}
}, {
key: "renderPreviewItem",
value: function renderPreviewItem(previewSizeList) {
var _this3 = this;
var customizePrefixCls = this.props.prefixCls;
var getPrefixCls = this.context.getPrefixCls;
var prefixCls = getPrefixCls('avatar-crop-edit', customizePrefixCls);
return previewSizeList.map(function (itemSize) {
return /*#__PURE__*/React.createElement("div", {
key: itemSize,
className: "".concat(prefixCls, "-preview-item")
}, /*#__PURE__*/React.createElement("i", _extends({}, _this3.getPreviewProps(itemSize))), /*#__PURE__*/React.createElement("p", null, "".concat(itemSize, "\uFF0A").concat(itemSize)));
});
}
}, {
key: "renderEditor",
value: function renderEditor(props) {
var _this4 = this;
var _this$state5 = this.state,
img = _this$state5.img,
rotate = _this$state5.rotate,
zoom = _this$state5.zoom,
crop = _this$state5.crop,
_this$state5$imageSty = _this$state5.imageStyle,
width = _this$state5$imageSty.width,
height = _this$state5$imageSty.height,
cropSize = _this$state5.cropSize;
var _this$props3 = this.props,
customizePrefixCls = _this$props3.prefixCls,
previewList = _this$props3.previewList,
editorWidth = _this$props3.editorWidth,
editorHeight = _this$props3.editorHeight,
previewTitle = _this$props3.previewTitle,
reloadTitle = _this$props3.reloadTitle;
var getPrefixCls = this.context.getPrefixCls;
var src = img.src;
var style = {
width: editorWidth,
height: editorHeight,
position: 'relative'
};
var minZoomVal = cropSize / Math.min(width, height);
var isMinZoom = zoom === minZoomVal;
var isMaxZoom = zoom === maxZoomVal;
var prefixCls = getPrefixCls('avatar-crop-edit', customizePrefixCls);
var previewTitleFlag = isString(previewTitle) || /*#__PURE__*/React.isValidElement(previewTitle);
var renderPreviewTitle = function renderPreviewTitle() {
if (!previewTitleFlag || !previewTitle) return null;
if (isString(previewTitle)) {
return /*#__PURE__*/React.createElement("h5", {
className: "".concat(prefixCls, "-preview-title")
}, /*#__PURE__*/React.createElement("span", null, previewTitle));
}
return previewTitle;
};
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-wraper")
}, /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-edit"),
style: style
}, /*#__PURE__*/React.createElement(Cropper, {
image: src,
crop: crop,
showGrid: false,
cropSize: {
width: cropSize,
height: cropSize
},
zoom: zoom,
minZoom: minZoomVal,
rotation: rotate,
aspect: 1 / 1,
onCropChange: function onCropChange(crop) {
return _this4.setState({
crop: crop
});
},
onCropComplete: function onCropComplete(_ref) {
var x = _ref.x,
y = _ref.y;
return _this4.onComplete({
x: x,
y: y,
cropSize: cropSize
});
},
onZoomChange: function onZoomChange(zoom) {
_this4.setState({
zoom: zoom
});
}
})), /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-preview")
}, renderPreviewTitle(), this.renderPreviewItem(previewList))), /*#__PURE__*/React.createElement("div", {
className: "".concat(prefixCls, "-button"),
style: {
width: editorWidth
}
}, /*#__PURE__*/React.createElement(ButtonGroup, null, /*#__PURE__*/React.createElement(Button, {
funcType: "raised",
icon: "zoom_in",
disabled: isMaxZoom,
onClick: function onClick() {
return _this4.zoomImage('add');
}
}), /*#__PURE__*/React.createElement(Button, {
funcType: "raised",
icon: "zoom_out",
disabled: isMinZoom,
onClick: function onClick() {
return _this4.zoomImage('sub');
}
})), /*#__PURE__*/React.createElement(Button, {
funcType: "raised",
icon: "play_90",
onClick: function onClick() {
return _this4.setState({
rotate: rotate + 90 >= 360 ? 0 : rotate + 90
});
}
}), /*#__PURE__*/React.createElement(Button, {
funcType: "raised",
onClick: function onClick() {
return _this4.zoomImage('init');
}
}, "1:1"), /*#__PURE__*/React.createElement(Upload, _extends({}, props), /*#__PURE__*/React.createElement(Button, {
funcType: "raised",
icon: "file_upload"
}, /*#__PURE__*/React.createElement("span", null, reloadTitle || Avatarlocale.reUpload)))));
}
}, {
key: "getUploadProps",
value: function getUploadProps() {
var _this5 = this;
var _this$props4 = this.props,
_this$props4$limit = _this$props4.limit,
limitSize = _this$props4$limit.size,
type = _this$props4$limit.type,
uploadProps = _this$props4.uploadProps;
var typeLimit = type.split(',').map(function (item) {
return "image/".concat(item);
}).join(',');
return _objectSpread(_objectSpread({
multiple: false,
name: 'file',
accept: typeLimit,
headers: {
Authorization: "bearer"
},
showUploadList: false
}, uploadProps), {}, {
beforeUpload: function beforeUpload(file) {
var size = file.size;
if (size > limitSize * 1024) {
message.warning(Avatarlocale.imageTooLarge);
return false;
}
_this5.setState({
file: file
});
var windowURL = window.URL || window.webkitURL;
if (windowURL && windowURL.createObjectURL) {
_this5.loadImage(windowURL.createObjectURL(file));
return false;
}
return false;
},
onChange: function onChange(_ref2) {
var file = _ref2.file;
var status = file.status,
response = file.response;
if (status === 'done') {
_this5.loadImage(response);
} else if (status === 'error') {
message.error(Avatarlocale.imageUploadError);
}
}
});
}
}, {
key: "renderContainer",
value: function renderContainer() {
var _this$props5 = this.props,
customizePrefixCls = _this$props5.prefixCls,
_this$props5$limit = _this$props5.limit,
limitSize = _this$props5$limit.size,
type = _this$props5$limit.type;
var img = this.state.img;
var getPrefixCls = this.context.getPrefixCls;
var prefixCls = getPrefixCls('avatar-crop', customizePrefixCls);
var props = this.getUploadProps();
return img ? this.renderEditor(props) : /*#__PURE__*/React.createElement(Dragger, _extends({
className: "".concat(prefixCls, "-dragger")
}, props), /*#__PURE__*/React.createElement(Icon, {
type: "inbox"
}), /*#__PURE__*/React.createElement("h3", {
className: "".concat(prefixCls, "-dragger-text")
}, /*#__PURE__*/React.createElement("span", null, Avatarlocale.imageDragHere)), /*#__PURE__*/React.createElement("h4", {
className: "".concat(prefixCls, "-dragger-hint")
}, /*#__PURE__*/React.createElement("span", null, "".concat(Avatarlocale.pleaseUpload).concat(limitSize / 1024, "M,").concat(Avatarlocale.uploadType).concat(type).concat(Avatarlocale.picture))));
}
}, {
key: "render",
value: function render() {
var _this6 = this;
var _this$props6 = this.props,
visible = _this$props6.visible,
modalProps = _this$props6.modalProps,
title = _this$props6.title;
var _this$state6 = this.state,
img = _this$state6.img,
submitting = _this$state6.submitting;
var cancelButtonProps = {
disabled: submitting,
funcType: 'raised'
};
var okButtonProps = {
funcType: 'raised',
type: 'primary',
disabled: !img,
loading: submitting
};
return /*#__PURE__*/React.createElement(LocaleReceiver, {
componentName: "imageCrop",
defaultLocale: defaultLocale.imageCrop
}, function (locale) {
Avatarlocale = locale || defaultLocale.imageCrop;
return /*#__PURE__*/React.createElement(Modal, _extends({
title: title || /*#__PURE__*/React.createElement("span", null, Avatarlocale.changeAvatar),
className: "avatar-modal",
visible: visible,
width: 600,
closable: true,
maskClosable: false,
onOk: _this6.handleOk,
onCancel: _this6.handleCancel,
okButtonProps: okButtonProps,
cancelButtonProps: cancelButtonProps
}, modalProps), _this6.renderContainer());
});
}
}], [{
key: "contextType",
get: function get() {
return ConfigContext;
}
}]);
return AvatarUploader;
}(Component);
export { AvatarUploader as default };
AvatarUploader.defaultProps = {
limit: {
type: 'jpeg,png,jpg',
size: 1024
},
previewList: [80, 48, 34],
editorWidth: 380,
editorHeight: 380,
rectSize: 280
};
//# sourceMappingURL=avatarUpload.js.map