nicecode-v2/packages/meta/es/ImageEditor/viewer/render.js

335 lines
21 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
//@ts-nocheck
import { set, getOuterWidth, getOuterHeight } from 'rc-util/lib/Dom/css';
import { isNil, isString, isFunction, cloneDeep } from '@zhst/func';
import { dispatchEvent } from "../utils";
import { EVENT_VIEWER_TRANSFORM_CHANGE } from "./constants";
export default {
// store
image: null,
canvas: null,
containerData: {
width: 0,
height: 0
},
animationFrame: null,
backgroundColor: '#fff',
targetTransform: {
translateX: 0,
translateY: 0,
scale: 0,
rotate: 0
// rotate: 90,
},
//method
render: function render() {
var _this = this;
return _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
return _regeneratorRuntime().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return _this.initImg();
case 2:
_this.initCanvas();
_this.startRaf();
case 4:
case "end":
return _context.stop();
}
}, _callee);
}))();
},
initImg: function initImg() {
var _this2 = this;
return new Promise(function (resolve, reject) {
var propImage = _this2.options.image;
if (isString(propImage)) {
var image = new Image();
image.crossOrigin = 'anonymous';
image.src = propImage;
image.onload = function () {
_this2.image = image;
resolve(image);
};
image.onerror = function (err) {
reject(err);
};
} else {
_this2.image = propImage;
resolve(propImage);
}
});
},
initCanvas: function initCanvas() {
//通过样式设置 不依赖父元素的prosition
var element = this.element,
canvas = this.canvas,
_this$limit = this.limit,
limit = _this$limit === void 0 ? {} : _this$limit,
options = this.options;
var containerData = {
width: getOuterWidth(element),
height: getOuterHeight(element)
};
this.containerData = containerData;
set(canvas, containerData);
canvas.width = containerData.width;
canvas.height = containerData.height;
var fitTransform = this.calcFitScreen();
this.targetTransform = Object.assign({}, this.targetTransform, fitTransform);
dispatchEvent(this.element, EVENT_VIEWER_TRANSFORM_CHANGE, cloneDeep(this.targetTransform));
//产品需求fitscale 是 minscale
var _options$fitScaleAsMi = options.fitScaleAsMinScale,
fitScaleAsMinScale = _options$fitScaleAsMi === void 0 ? false : _options$fitScaleAsMi;
if (fitScaleAsMinScale) {
this.limit = Object.assign({
minScale: this.targetTransform.scale
}, this.limit);
}
},
startRaf: function startRaf() {
var _this3 = this;
//清理动画
window.cancelAnimationFrame(this.animationFrame);
//渲染
var loop = function loop() {
// this.update(); //先update
_this3.renderCanvas();
window.cancelAnimationFrame(_this3.animationFrame);
_this3.animationFrame = window.requestAnimationFrame(loop);
};
loop();
},
// 绘制画布
renderCanvas: function renderCanvas(_ctx) {
if (!this.canvas) return;
var containerData = this.containerData,
canvas = this.canvas,
targetTransform = this.targetTransform,
options = this.options;
var translateX = targetTransform.translateX,
translateY = targetTransform.translateY,
scale = targetTransform.scale,
rotate = targetTransform.rotate;
var ctx = _ctx ? _ctx : canvas.getContext('2d');
//画背景
ctx.clearRect(0, 0, containerData.width, containerData.height);
ctx.fillStyle = options.backgroundColor; //todo@wdy OD框背景颜色
ctx.fillRect(0, 0, canvas.width, canvas.height);
//画图
ctx.save();
//缩放移动
ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
// ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
//旋转
var centerX = this.image ? this.image.width / 2 : canvas.width;
var centerY = this.image ? this.image.height / 2 : canvas.height;
ctx.translate(centerX, centerY);
ctx.rotate(rotate / 180 * Math.PI);
ctx.translate(-centerX, -centerY);
//图片
this.image && ctx.drawImage(this.image, 0, 0);
ctx.restore();
//画图形
ctx.save();
this.renderShape(ctx);
ctx.restore();
},
scaleTo: function scaleTo(offsetScale) {
//获取图片中心点
var containerData = this.containerData;
this.calcTransform({
scaleCenter: {
x: containerData.width / 2,
y: containerData.height / 2,
step: offsetScale
}
});
},
//暂时只支持90deg旋转 否则limit 不能做
rotateTo: function rotateTo(T) {
if (!this.image) return;
var targetTransform = this.targetTransform;
var rotate = targetTransform.rotate;
var newDeg = isFunction(T) ? T(rotate) : T;
this.calcTransform({
rotate: newDeg
});
},
reset: function reset() {
this.targetTransform.rotate = 0;
var fitTransform = this.calcFitScreen();
this.targetTransform = Object.assign({}, this.targetTransform, fitTransform);
dispatchEvent(this.element, EVENT_VIEWER_TRANSFORM_CHANGE, cloneDeep(this.targetTransform));
},
getImgSize: function getImgSize() {
if (!this.image) return;
return {
w: this.image.width,
h: this.image.height
};
},
getImage: function getImage() {
return this;
},
calcFitScreen: function calcFitScreen() {
if (!this.image) return;
var w = this.containerData.width;
var h = this.containerData.height;
var iw = this.image.width;
var ih = this.image.height;
//算图片显示长款 todo旋转算旋转后
var _this$targetTransform = this.targetTransform.rotate,
rotate = _this$targetTransform === void 0 ? 0 : _this$targetTransform;
var wToh = w / h;
var imgwToh = iw / ih;
if (rotate % 180 !== 0) {
imgwToh = ih / iw;
}
//计算后的位置
var scale;
var translateX = 0;
var translateY = 0;
if (imgwToh > wToh) {
scale = w / iw;
translateX = 0;
translateY = (h - ih * scale) / 2;
if (rotate % 180 !== 0) {
scale = w / ih;
translateX = (ih - iw) / 2 * scale;
translateY = (h - iw * scale) / 2 + (iw - ih) / 2 * scale;
}
} else {
scale = h / ih;
translateX = (w - iw * scale) / 2;
translateY = 0;
if (rotate % 180 !== 0) {
scale = h / iw;
translateX = (w - ih * scale) / 2 + (ih - iw) / 2 * scale;
translateY = (iw - ih) / 2 * scale;
}
}
var fitTransform = {
translateX: translateX,
translateY: translateY,
scale: scale
};
return fitTransform;
},
calcTransform: function calcTransform(newTransform, cropBox) {
if (!this.image) return;
var translateX = newTransform.translateX,
translateY = newTransform.translateY,
scaleCenter = newTransform.scaleCenter,
rotate = newTransform.rotate;
if (!isNil(scaleCenter)) {
var _targetTransform = this.targetTransform,
_this$limit2 = this.limit,
limit = _this$limit2 === void 0 ? {} : _this$limit2;
var _limit$minScale = limit.minScale,
minScale = _limit$minScale === void 0 ? 0.1 : _limit$minScale,
_limit$maxScale = limit.maxScale,
maxScale = _limit$maxScale === void 0 ? Number.MAX_VALUE : _limit$maxScale;
if (cropBox) {
//如果有cropbox 最小缩放值需要重新计算
var _this$image = this.image,
iw = _this$image.width,
ih = _this$image.height;
if (_targetTransform.rotate % 180 !== 0) {
var _ref = [ih, iw];
iw = _ref[0];
ih = _ref[1];
}
var cw = cropBox.width,
ch = cropBox.height;
var corpMinScale = Math.max(cw / iw, ch / ih);
minScale = Math.max(corpMinScale, minScale);
}
var x = scaleCenter.x,
y = scaleCenter.y,
step = scaleCenter.step;
var preScale = _targetTransform.scale;
var newScale = _targetTransform.scale + step;
newScale = Math.min(maxScale, Math.max(newScale, minScale));
var newStep = newScale - preScale;
if (newScale != preScale) {
var offsetX = (x - _targetTransform.translateX) / _targetTransform.scale * newStep;
var offsetY = (y - _targetTransform.translateY) / _targetTransform.scale * newStep;
this.targetTransform.translateX = this.targetTransform.translateX - offsetX;
this.targetTransform.translateY = this.targetTransform.translateY - offsetY;
}
this.targetTransform.scale = newScale;
}
if (!isNil(translateX)) {
this.targetTransform.translateX += translateX;
}
if (!isNil(translateY)) {
this.targetTransform.translateY += translateY;
}
if (!isNil(rotate)) {
this.targetTransform.rotate = rotate;
}
//阻止拖出边界
var targetTransform = this.targetTransform,
containerData = this.containerData;
var minMargin = 50;
var imgWidth = this.image.width;
var imgHeight = this.image.height;
if (this.targetTransform.rotate % 180 !== 0) {
imgWidth = this.image.height;
imgHeight = this.image.width;
}
var minX = minMargin - imgWidth * targetTransform.scale;
var maxX = containerData.width - minMargin;
var minY = minMargin - imgHeight * targetTransform.scale;
var maxY = containerData.height - minMargin;
this.targetTransform.translateX = Math.min(maxX, Math.max(this.targetTransform.translateX, minX));
this.targetTransform.translateY = Math.min(maxY, Math.max(this.targetTransform.translateY, minY));
//限制截图框不能超出拖动范围
if (cropBox) {
var _cw = cropBox.width,
_ch = cropBox.height,
top = cropBox.top,
left = cropBox.left;
var _this$image2 = this.image,
_iw = _this$image2.width,
_ih = _this$image2.height;
var imgLeftTop = {
x: 0,
y: 0
};
var imgRightBottom = {
x: _iw,
y: _ih
};
if (this.targetTransform.rotate % 180 !== 0) {
imgLeftTop = {
x: (_iw - _ih) / 2,
y: (_ih - _iw) / 2
};
imgRightBottom = {
x: (_iw + _ih) / 2,
y: (_iw + _ih) / 2
};
}
//图片左上角不能大于crop左上角
var _maxX = left - imgLeftTop.x * this.targetTransform.scale;
var _maxY = top - imgLeftTop.y * this.targetTransform.scale;
//图片右下角不能小于crop 右下角
var _minX = left + _cw - imgRightBottom.x * this.targetTransform.scale;
var _minY = top + _ch - imgRightBottom.y * this.targetTransform.scale;
this.targetTransform.translateX = Math.min(_maxX, Math.max(this.targetTransform.translateX, _minX));
this.targetTransform.translateY = Math.min(_maxY, Math.max(this.targetTransform.translateY, _minY));
}
dispatchEvent(this.element, EVENT_VIEWER_TRANSFORM_CHANGE, cloneDeep(this.targetTransform));
}
};