UNPKG

choerodon-ui

Version:

An enterprise-class UI design language and React-based implementation

480 lines (408 loc) 14.8 kB
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