choerodon-ui
Version:
An enterprise-class UI design language and React-based implementation
480 lines (408 loc) • 14.8 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _objectSpread from "@babel/runtime/helpers/objectSpread2";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _inherits from "@babel/runtime/helpers/inherits";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
function _createSuper(Derived) {
function isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
return function () {
var Super = _getPrototypeOf(Derived),
result;
if (isNativeReflectConstruct()) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
/**
* 裁剪组件
*/
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { getPrefixCls } from '../configure';
var relativeX = 0;
var relativeY = 0;
var resizeMode;
var resizeX = 0;
var resizeY = 0;
var resizeSize = 0;
/**
* when can't be exact division it will return false
* @param rotate
*/
function rotateFlag(rotate) {
return rotate / 90 % 2 !== 0;
}
var Crop =
/*#__PURE__*/
function (_Component) {
_inherits(Crop, _Component);
var _super = _createSuper(Crop);
function Crop(props) {
var _this;
_classCallCheck(this, Crop);
_this = _super.call(this, props);
_this.handleMoveStart = function (_ref) {
var clientX = _ref.clientX,
clientY = _ref.clientY;
var _this$state = _this.state,
x = _this$state.x,
y = _this$state.y;
relativeX = clientX - x;
relativeY = clientY - y;
document.addEventListener('mousemove', _this.handleMoving);
document.addEventListener('mouseup', _this.handleMoveEnd);
};
_this.handleMoving = function (_ref2) {
var clientX = _ref2.clientX,
clientY = _ref2.clientY;
var _this$state2 = _this.state,
size = _this$state2.size,
_this$state2$imageSty = _this$state2.imageStyle,
width = _this$state2$imageSty.width,
height = _this$state2$imageSty.height,
rotate = _this$state2.rotate;
var onComplete = _this.props.onComplete;
var flag = rotateFlag(rotate);
var minX = flag ? (width - height) / 2 : 0; // if can't be exact division min is 0
var minY = flag ? (height - width) / 2 : 0; // if can't be exact division min is 0
var maxX = width - size - minX; // the max width is image minus the size , there would minus the sizeWidth
var maxY = height - size - minY; // the max height is image minus the size , there would minus the sizeHeight
var movingXY = {
x: Math.min(Math.max(minX, clientX - relativeX), maxX),
y: Math.min(Math.max(minY, clientY - relativeY), maxY)
};
if (onComplete) {
var completeXY = _objectSpread({}, movingXY, {
size: size
});
onComplete(completeXY);
}
_this.setState(movingXY);
};
_this.handleMoveEnd = function () {
document.removeEventListener('mousemove', _this.handleMoving);
document.removeEventListener('mouseup', _this.handleMoveEnd);
};
_this.handleResizeStart = function (e) {
e.stopPropagation();
var currentTarget = e.currentTarget,
clientX = e.clientX,
clientY = e.clientY; // mouse of body the x y position
var _this$state3 = _this.state,
x = _this$state3.x,
y = _this$state3.y,
size = _this$state3.size;
relativeX = clientX - x; // relativeX
relativeY = clientY - y; // relativeY
resizeMode = currentTarget.className; // to confirm the witch border on handle
resizeX = x; // x of image position
resizeY = y; // y of image position
resizeSize = size; // size of crop area , TODO change to resizeHeight resizeWidth
document.addEventListener('mousemove', _this.handleResizing);
document.addEventListener('mouseup', _this.handleResizeEnd);
};
_this.handleResizing = function (_ref3) {
var clientX = _ref3.clientX,
clientY = _ref3.clientY;
var _this$props = _this.props,
onComplete = _this$props.onComplete,
onCropChange = _this$props.onCropChange,
minRectSize = _this$props.minRectSize;
var _this$state4 = _this.state,
_this$state4$imageSty = _this$state4.imageStyle,
width = _this$state4$imageSty.width,
height = _this$state4$imageSty.height,
rotate = _this$state4.rotate;
var flag = rotateFlag(rotate);
var newX = clientX - relativeX; // mouse x diffrence from before
var newY = clientY - relativeY; // mouse y diffrence from before
var x = resizeX;
var y = resizeY;
var size;
if (resizeMode === 'lt') {
var relative = Math.min(newX - resizeX, newY - resizeY);
x += relative;
y += relative;
size = resizeSize - x + resizeX;
} else if (resizeMode === 'rt') {
var _relative = Math.min(resizeX - newX, newY - resizeY);
y += _relative;
size = resizeSize - y + resizeY;
} else if (resizeMode === 'lb') {
var _relative2 = Math.min(newX - resizeX, resizeY - newY);
x += _relative2;
size = resizeSize - x + resizeX;
} else {
var _relative3 = Math.min(resizeX - newX, resizeY - newY);
size = resizeSize - _relative3;
}
var minX = flag ? (width - height) / 2 : 0;
var minY = flag ? (height - width) / 2 : 0;
var maxWidth = flag ? (width - height) / 2 + height : width;
var maxHeight = flag ? (height - width) / 2 + width : height;
x = Math.min(Math.max(minX, x), resizeSize - minRectSize + resizeX);
y = Math.min(Math.max(minY, y), resizeSize - minRectSize + resizeY);
var cropSize = {
x: x,
y: y,
size: Math.max(Math.min(size, maxWidth - x, maxHeight - y), minRectSize)
};
if (onComplete) {
onComplete(cropSize);
}
if (onCropChange) {
onCropChange(cropSize);
}
_this.setState(cropSize);
};
_this.handleResizeEnd = function () {
document.removeEventListener('mousemove', _this.handleResizing);
document.removeEventListener('mouseup', _this.handleResizeEnd);
};
/** *
* 永远计算理论上来说必须用sin这种方法来计算了
* 最大高度和最小高度
*/
/**
*
* Returns an x,y point once rotated around xMid,yMid
*/
_this.rotateAroundMidPoint = function (x, y, xMid, yMid, degrees) {
var cos = Math.cos;
var sin = Math.sin;
var radian = degrees * Math.PI / 180; // Convert to radians
// Subtract midpoints, so that midpoint is translated to origin
// and add it in the end again
var xr = (x - xMid) * cos(radian) - (y - yMid) * sin(radian) + xMid;
var yr = (x - xMid) * sin(radian) + (y - yMid) * cos(radian) + yMid;
return [xr, yr];
};
/**
* Returns the new bounding area of a rotated rectangle.
*/
_this.translateSize = function (width, height, rotation) {
var centerX = width / 2;
var centerY = height / 2;
var outerBounds = [_this.rotateAroundMidPoint(0, 0, centerX, centerY, rotation), _this.rotateAroundMidPoint(width, 0, centerX, centerY, rotation), _this.rotateAroundMidPoint(width, height, centerX, centerY, rotation), _this.rotateAroundMidPoint(0, height, centerX, centerY, rotation)];
var minX = Math.min.apply(Math, _toConsumableArray(outerBounds.map(function (p) {
return p[0];
})));
var maxX = Math.max.apply(Math, _toConsumableArray(outerBounds.map(function (p) {
return p[0];
})));
var minY = Math.min.apply(Math, _toConsumableArray(outerBounds.map(function (p) {
return p[1];
})));
var maxY = Math.max.apply(Math, _toConsumableArray(outerBounds.map(function (p) {
return p[1];
})));
return {
width: maxX - minX,
height: maxY - minY
};
};
if (props.src) {
_this.loadImage(props.src);
}
var rotate = typeof props.rotation !== 'undefined' ? props.rotation : 0;
var defaultRectSize = typeof props.defaultRectSize !== 'undefined' ? props.defaultRectSize : 200;
_this.state = {
img: null,
size: defaultRectSize,
x: 0,
y: 0,
rotate: rotate,
imageStyle: {}
};
if ('onMaskClick' in props) {
console.warn('`onMaskClick` are removed, please use `onClose` instead.');
}
return _this;
}
_createClass(Crop, [{
key: "componentDidUpdate",
value: function componentDidUpdate(prevProps, prevState) {
var _this$props2 = this.props,
rotation = _this$props2.rotation,
onRotationChange = _this$props2.onRotationChange,
src = _this$props2.src;
var img = prevState.img;
if (img && rotation && prevProps.rotation !== rotation) {
// 旋转触发方法
if (onRotationChange) {
onRotationChange(rotation);
}
this.initImageSize(img, rotation);
} // 修改 src 触发方法
if (src && prevProps.src !== src) {
this.loadImage(src);
}
}
}, {
key: "initImageSize",
value: function initImageSize(img) {
var rotate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
var _this$props3 = this.props,
editorWidth = _this$props3.editorWidth,
editorHeight = _this$props3.editorHeight,
defaultRectSize = _this$props3.defaultRectSize,
minRectSize = _this$props3.minRectSize;
var naturalWidth = img.naturalWidth,
naturalHeight = img.naturalHeight; // to judge the
var flag = rotateFlag(rotate);
var width = flag ? naturalHeight : naturalWidth;
var height = flag ? naturalWidth : naturalHeight;
if (width < minRectSize || height < minRectSize) {
if (width > height) {
width = width / height * minRectSize;
height = minRectSize;
} else {
height = height / width * minRectSize;
width = minRectSize;
}
} 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(defaultRectSize, width, height);
var CropperInfo = {
img: img,
imageStyle: {
width: width,
height: height,
top: (editorHeight - height) / 2,
left: (editorWidth - width) / 2,
transform: "rotate(".concat(rotate, "deg)")
},
size: size,
x: (width - size) / 2,
y: (height - size) / 2,
rotate: rotate
};
this.setState(CropperInfo);
}
}, {
key: "loadImage",
value: function loadImage(src) {
var _this2 = this;
if (typeof window !== 'undefined') {
var _this$props4 = this.props,
crossOrigin = _this$props4.crossOrigin,
rotation = _this$props4.rotation;
var img = new Image();
img.src = src;
if (crossOrigin === 'anonymous' || crossOrigin === 'use-credentials') {
img.crossOrigin = 'anonymous';
}
img.onload = function () {
var imgRotate = rotation || 0;
_this2.initImageSize(img, imgRotate);
};
}
}
}, {
key: "render",
value: function render() {
var _this$state5 = this.state,
img = _this$state5.img,
imageStyle = _this$state5.imageStyle,
size = _this$state5.size,
x = _this$state5.x,
y = _this$state5.y;
var _this$props5 = this.props,
editorHeight = _this$props5.editorHeight,
editorWidth = _this$props5.editorWidth,
customizePrefixCls = _this$props5.prefixCls;
var prefixCls = getPrefixCls('avatar-crop', customizePrefixCls);
if (img) {
var src = img.src;
var left = imageStyle.left,
top = imageStyle.top;
var style = {
width: editorWidth,
height: editorHeight
}; // 通过border位置来控制裁剪高宽
var maskStyle = {
borderTopWidth: y + top,
borderRightWidth: editorWidth - x - left - size,
borderBottomWidth: editorHeight - y - top - size,
borderLeftWidth: x + left
};
return React.createElement("div", {
className: "".concat(prefixCls, "-edit"),
style: style
}, React.createElement("img", {
alt: "",
src: src,
style: imageStyle
}), React.createElement("div", {
className: "".concat(prefixCls, "-edit-mask"),
style: maskStyle
}, React.createElement("div", {
onMouseDown: this.handleMoveStart
}, React.createElement("i", {
className: "lt",
onMouseDown: this.handleResizeStart
}), React.createElement("i", {
className: "rt",
onMouseDown: this.handleResizeStart
}), React.createElement("i", {
className: "lb",
onMouseDown: this.handleResizeStart
}), React.createElement("i", {
className: "rb",
onMouseDown: this.handleResizeStart
}))));
}
return null;
}
}]);
return Crop;
}(Component);
export { Crop as default };
Crop.propTypes = {
crossOrigin: PropTypes.string,
src: PropTypes.string,
rotation: PropTypes.number,
onRotationChange: PropTypes.func,
onComplete: PropTypes.func,
onCropChange: PropTypes.func,
prefixCls: PropTypes.string,
editorWidth: PropTypes.number,
editorHeight: PropTypes.number,
minRectSize: PropTypes.number,
defaultRectSize: PropTypes.number
};
Crop.defaultProps = {
editorWidth: 540,
editorHeight: 300,
minRectSize: 80,
defaultRectSize: 200
};
//# sourceMappingURL=Crop.js.map