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

333 lines
11 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.

import _regeneratorRuntime from "@babel/runtime/helpers/esm/regeneratorRuntime";
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
//@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));
}
};