UNPKG

@antmjs/vantui

Version:

一套适用于Taro3及React的vantui组件库

515 lines (514 loc) 20.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = ImageCropper; var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _components = require("@tarojs/components"); var _react = require("react"); var _taro = require("@tarojs/taro"); var _utils = require("../common/utils"); var _button = require("../button"); var _icon = require("../icon"); var _defaultProps = require("../default-props"); var _utils2 = require("./utils"); var _h = require("./h5"); var _jsxRuntime = require("react/jsx-runtime"); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } var initPercent = 0.9; var pageRects = { windowWidth: 0, windowHeight: 0, pixelRatio: 1 }; var res = (0, _taro.getWindowInfo)(); var windowWidth = res.windowWidth, windowHeight = res.windowHeight, pixelRatio = res.pixelRatio; pageRects.windowWidth = windowWidth; pageRects.windowHeight = windowHeight; pageRects.pixelRatio = pixelRatio; function ImageCropper(props) { var _useState = (0, _react.useState)((0, _defaultProps.get)().ImageCropper), _useState2 = (0, _slicedToArray2.default)(_useState, 1), d = _useState2[0]; var _d$props = _objectSpread(_objectSpread({}, d), props), _d$props$allowScale = _d$props.allowScale, allowScale = _d$props$allowScale === void 0 ? true : _d$props$allowScale, image = _d$props.image, _d$props$scale = _d$props.scale, scale = _d$props$scale === void 0 ? 2 : _d$props$scale, _d$props$fixScale = _d$props.fixScale, fixScale = _d$props$fixScale === void 0 ? false : _d$props$fixScale; var _useState3 = (0, _react.useState)(0), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), imageRotate = _useState4[0], setimageRotate = _useState4[1]; // eslint-disable-next-line prefer-const var _useState5 = (0, _react.useState)({ left: 0, top: 0, width: 0, height: 0, realScale: 0, $width: 0, $height: 0 }), _useState6 = (0, _slicedToArray2.default)(_useState5, 2), imageRect = _useState6[0], setimageRect = _useState6[1]; var _useState7 = (0, _react.useState)({ dl: 0 }), _useState8 = (0, _slicedToArray2.default)(_useState7, 2), imageRectY = _useState8[0], setimageRectY = _useState8[1]; var _useState9 = (0, _react.useState)({}), _useState10 = (0, _slicedToArray2.default)(_useState9, 2), borderBoxRect = _useState10[0], setborderBoxRect = _useState10[1]; var _useState11 = (0, _react.useState)({ x: 0, y: 0 }), _useState12 = (0, _slicedToArray2.default)(_useState11, 1), scaleRect = _useState12[0]; var ctxRotate = (0, _react.useRef)(); var ctx = (0, _react.useRef)(); var _useState13 = (0, _react.useState)({ width: initPercent * pageRects.windowWidth + 'px', height: initPercent * pageRects.windowWidth / scale + 'px', widthBase: initPercent * pageRects.windowWidth, heightBase: initPercent * pageRects.windowWidth / scale, transform: 'translate(0, 0)', base: 0, nextBase: 0, baseX: 0, nextBaseX: 0 }), _useState14 = (0, _slicedToArray2.default)(_useState13, 2), borderBoxStyle = _useState14[0], setborderBoxStyle = _useState14[1]; var rects = (0, _react.useRef)({ x: 0, y: 0, deltaX: 0, deltaY: 0 }); var getImage = function getImage(image) { (0, _taro.showLoading)(); (0, _taro.getImageInfo)({ src: props.image || image, fail: function fail(err) { console.info(err); (0, _taro.hideLoading)(); }, success: function success(res) { setTimeout(function () { (0, _utils.getRect)(null, '#cropper-image', '#van-cropper').then(function (aa) { var rect = _objectSpread(_objectSpread({}, aa), {}, { $width: res.width, $height: res.height, realScale: res.width / aa.width }); setimageRect(rect); getBorderRects(rect).then(function () { (0, _taro.hideLoading)(); }); }); }, 200); } }); }; (0, _react.useEffect)(function () { setTimeout(function () { ctx.current = (0, _taro.createCanvasContext)('cropper-canvas'); ctxRotate.current = (0, _taro.createCanvasContext)('cropper-canvas-rotate'); getImage(); }, 100); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); var getBorderRects = function getBorderRects(imgRects) { return new Promise(function (resolve) { (0, _utils.getRect)(null, '#cropper-border-box', '#van-cropper').then(function (res) { setborderBoxRect(res); if (imgRects) { var dd = imgRects.top + (imgRects.height - res.height) / 2; rects.current.deltaY = (imgRects.height - res.height) / 2; borderBoxStyle.base = dd; borderBoxStyle.nextBase = dd; var xx = imgRects.left + (imgRects.width - res.width) / 2; rects.current.deltaX = (imgRects.width - res.width) / 2; borderBoxStyle.baseX = xx; borderBoxStyle.nextBaseX = xx; borderBoxStyle.transform = "translate(".concat(xx, "px, ").concat(dd, "px)"); } resolve(true); }); }); }; var updateImageRect = /*#__PURE__*/function () { var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() { return _regenerator.default.wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: return _context.abrupt("return", new Promise(function (resolve) { (0, _utils.getRect)(null, '#cropper-image', '#van-cropper').then(function (aa) { imageRect = _objectSpread(_objectSpread(_objectSpread({}, imageRect), aa), {}, { realScale: imageRotate % 180 === 0 ? imageRect.$width / aa.width : imageRect.$height / aa.width }); setimageRect(_objectSpread({}, imageRect)); resolve(true); }); })); case 1: case "end": return _context.stop(); } }, _callee); })); return function updateImageRect() { return _ref.apply(this, arguments); }; }(); var draw = /*#__PURE__*/function () { var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(e) { var displayWidth, displayHeight, img, _props$onCropper, _res, image, _res2; return _regenerator.default.wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: e.stopPropagation(); (0, _taro.showLoading)({ title: '图片生成中...' }); if (ctx.current) { _context2.next = 4; break; } return _context2.abrupt("return"); case 4: displayWidth = Number(borderBoxStyle.width.replace('px', '')); displayHeight = Number(borderBoxStyle.height.replace('px', '')); if (!(process.env.TARO_ENV === 'h5')) { _context2.next = 22; break; } if (!(imageRotate !== 0)) { _context2.next = 12; break; } _context2.next = 10; return updateImageRect(); case 10: rects.current.deltaY = borderBoxStyle.base - imageRect.top; rects.current.deltaX = borderBoxStyle.baseX - imageRect.left; case 12: _context2.next = 14; return (0, _h.drawImageWithRotation)({ src: props.image, angle: imageRotate }); case 14: img = _context2.sent; if (!img) { _context2.next = 21; break; } _context2.next = 18; return (0, _h.drawCropperImage)({ x: rects.current.deltaX * imageRect.realScale, y: rects.current.deltaY * imageRect.realScale, w: displayWidth * imageRect.realScale, h: displayHeight * imageRect.realScale, src: img }); case 18: _res = _context2.sent; (_props$onCropper = props.onCropper) === null || _props$onCropper === void 0 ? void 0 : _props$onCropper.call(props, _res); (0, _taro.hideLoading)(); case 21: return _context2.abrupt("return"); case 22: image = props.image; if (!(imageRotate !== 0)) { _context2.next = 32; break; } _context2.next = 26; return (0, _utils2.rotateImage)({ imagePath: image, imageWidth: imageRect.$width, imageHeight: imageRect.$height, ctx: ctxRotate.current, rotate: imageRotate, canvasId: 'cropper-canvas-rotate' }); case 26: _res2 = _context2.sent; image = _res2; _context2.next = 30; return updateImageRect(); case 30: rects.current.deltaY = borderBoxStyle.base - imageRect.top; rects.current.deltaX = borderBoxStyle.baseX - imageRect.left; case 32: // 绘制图片 // @ts-ignore ctx.current.drawImage(image, -rects.current.deltaX, -rects.current.deltaY, imageRect.width, imageRect.height, displayWidth, displayHeight); ctx.current.draw(false, function () { (0, _taro.canvasToTempFilePath)({ canvasId: 'cropper-canvas', width: displayWidth, height: displayHeight, destWidth: displayWidth * pageRects.pixelRatio, destHeight: displayHeight * pageRects.pixelRatio, success: function success(res) { var _props$onCropper2; (_props$onCropper2 = props.onCropper) === null || _props$onCropper2 === void 0 ? void 0 : _props$onCropper2.call(props, res.tempFilePath); (0, _taro.hideLoading)(); }, fail: function fail(err) { (0, _taro.hideLoading)(); console.error('cropper-canvas save image failed:', err); } }); }); case 34: case "end": return _context2.stop(); } }, _callee2); })); return function draw(_x) { return _ref2.apply(this, arguments); }; }(); var onTouchStart = function onTouchStart(e) { e.stopPropagation(); rects.current.x = e.touches[0].clientX; rects.current.y = e.touches[0].clientY; }; var onTouchMove = function onTouchMove(e) { e.stopPropagation(); var yy = e.touches[0].clientY; var xx = e.touches[0].clientX; var cc = borderBoxStyle.baseX + xx - rects.current.x; var dd = borderBoxStyle.base + yy - rects.current.y; if (cc < 0 && Math.abs(cc) - imageRect.left > 0) { cc = 0; } if (cc > 0 && Math.abs(cc) + borderBoxRect.width > pageRects.windowWidth) { cc = pageRects.windowWidth - borderBoxRect.width; } borderBoxStyle.transform = "translate(".concat(cc, "px, ").concat(dd, "px)"); borderBoxStyle.nextBase = dd; borderBoxStyle.nextBaseX = cc; setborderBoxStyle(_objectSpread({}, borderBoxStyle)); }; var onTouchEnd = function onTouchEnd(e) { e.stopPropagation(); getBorderRects(); rects.current.y = 0; rects.current.x = 0; borderBoxStyle.base = borderBoxStyle.nextBase; borderBoxStyle.baseX = borderBoxStyle.nextBaseX; rects.current.deltaY = borderBoxStyle.base - imageRect.top; rects.current.deltaX = borderBoxStyle.baseX - imageRect.left; setborderBoxStyle(_objectSpread({}, borderBoxStyle)); }; var touchScaleStart = function touchScaleStart(e) { e.stopPropagation(); scaleRect.x = e.touches[0].clientX; scaleRect.y = e.touches[0].clientY; }; var touchScaleMove = function touchScaleMove(e) { e.stopPropagation(); var yy = e.touches[0].clientY; var xx = e.touches[0].clientX; var aa = xx - scaleRect.x; var bb = yy - scaleRect.y; var currentW = borderBoxStyle.widthBase; var currentH = borderBoxStyle.heightBase; var newW = currentW + aa; var newH = currentH + bb; if (newW < 100) { newW = 100; } if (newW > pageRects.windowWidth - 2) { newW = pageRects.windowWidth; } if (newH < 100) { newH = 100; } if (fixScale) { newH = newW / scale; } borderBoxStyle.width = newW + 'px'; borderBoxStyle.height = newH + 'px'; setborderBoxStyle(_objectSpread({}, borderBoxStyle)); }; var touchScaleEnd = function touchScaleEnd(e) { getBorderRects(); e.stopPropagation(); borderBoxStyle.widthBase = Number(borderBoxStyle.width.replace('px', '')); borderBoxStyle.heightBase = Number(borderBoxStyle.height.replace('px', '')); setborderBoxStyle(_objectSpread({}, borderBoxStyle)); }; var currentScale = (0, _react.useMemo)(function () { return (borderBoxStyle.widthBase / borderBoxStyle.heightBase).toFixed(1); }, [borderBoxStyle.heightBase, borderBoxStyle.widthBase]); var imageInfos = (0, _react.useMemo)(function () { var style = { width: '100vw' }; if (imageRotate % 180 !== 0) { style.transform = "rotate(".concat(imageRotate, "deg)") + " scale(".concat((imageRectY === null || imageRectY === void 0 ? void 0 : imageRectY.dl) || 1, ")"); } else { style.transform = "rotate(".concat(imageRotate, "deg)"); } return { style: style }; }, [imageRectY.dl, imageRotate]); var handleRotate = /*#__PURE__*/function () { var _ref3 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(num) { var newRotate; return _regenerator.default.wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: newRotate = imageRotate + num; if (newRotate === -90) { newRotate = 270; } if (newRotate > 270) { newRotate = 0; } if (newRotate < -270) { newRotate = 0; } setimageRotate(newRotate); if (newRotate % 180 !== 0 && !(imageRectY !== null && imageRectY !== void 0 && imageRectY.dl)) { setTimeout(function () { (0, _utils.getRect)(null, '#van-cropper >>> #cropper-image').then(function (res) { setimageRectY(_objectSpread(_objectSpread({}, res), {}, { dl: pageRects.windowWidth / res.width })); }); }, 500); } case 6: case "end": return _context3.stop(); } }, _callee3); })); return function handleRotate(_x2) { return _ref3.apply(this, arguments); }; }(); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, { children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.View, { id: "van-cropper", className: "van-cropper", onClick: function onClick(e) { e.stopPropagation(); }, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Image, { style: imageInfos.style, id: "cropper-image", className: "image", src: props.image, mode: "widthFix" }, "imageR".concat(imageRotate)), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.View // @ts-ignore , { catchMove: true, id: "cropper-border-box", onTouchStart: onTouchStart, onTouchMove: onTouchMove, onTouchEnd: onTouchEnd, style: { transition: 'All 0s', height: borderBoxStyle.height, width: borderBoxStyle.width, transform: borderBoxStyle.transform, opacity: imageRect.width ? 1 : 0.1 }, className: "border-box", children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.View, { style: allowScale ? {} : { display: 'none' }, onTouchStart: touchScaleStart, onTouchMove: touchScaleMove, onTouchEnd: touchScaleEnd, className: "scale-btn diy-food-icon diy-food-icon-suofang-zuoxiang", children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icon.Icon, { name: "shrink", size: "30px" }) }) }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.View, { className: "rotate-btns", children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_icon.Icon, { onClick: function onClick() { return handleRotate(-90); }, name: "revoke", size: "32px" }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_icon.Icon, { onClick: function onClick() { return handleRotate(90); }, name: "revoke", size: "32px" })] }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.View, { className: "cropper-btns", children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, { onClick: function onClick() { var _props$onCropper3; return (_props$onCropper3 = props.onCropper) === null || _props$onCropper3 === void 0 ? void 0 : _props$onCropper3.call(props, image); }, children: "\u539F\u56FE" }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.View, { className: "current-scale", children: ["\u5BBD\u9AD8\u6BD4\u7EA6\uFF1A", currentScale] }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, { type: "primary", onClick: draw, children: "\u622A\u56FE" })] })] }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Canvas, { id: "cropper-canvas", "canvas-id": "cropper-canvas", style: { width: borderBoxStyle.width, height: borderBoxStyle.height, transform: 'none', position: 'fixed', left: '-900px', top: '0px', zIndex: 0 } }), imageRect.width && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Canvas, { id: "cropper-canvas-rotate", "canvas-id": "cropper-canvas-rotate", style: { height: imageRotate % 180 === 0 ? imageRect.$height + 'px' : imageRect.$width + 'px', width: imageRotate % 180 === 0 ? imageRect.$width + 'px' : imageRect.$height + 'px', transform: 'none', position: 'fixed', right: '-9000px', top: '0px', zIndex: 0 } })] }); }