@antmjs/vantui
Version:
一套适用于Taro3及React的vantui组件库
515 lines (514 loc) • 20.1 kB
JavaScript
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
}
})]
});
}
;