画布印花合成
This commit is contained in:
@@ -959,3 +959,32 @@ export function getTransformScaleAngle(Transform) {
|
||||
const angle = Math.round(Math.atan2(b, a) * 180 / Math.PI);
|
||||
return { scale, angle };
|
||||
}
|
||||
|
||||
/**
|
||||
* 图片转换为canvas
|
||||
* @param {String} base64 - 图片base64编码
|
||||
* @param {Number} scale - 缩放比例
|
||||
* @param {Boolean} sr - 缩放反转,默认false
|
||||
* @returns {Promise<HTMLCanvasElement>} canvas元素
|
||||
*/
|
||||
export async function base64ToCanvas(base64, scale = 1, sr = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const image = new Image();
|
||||
image.src = base64;
|
||||
image.crossOrigin = 'anonymous';
|
||||
image.onload = () => {
|
||||
image.width = image.width;
|
||||
image.height = image.height;
|
||||
const canvas = document.createElement('canvas');
|
||||
const width = (sr ? image.width / scale : image.width * scale);
|
||||
const height = sr ? image.height / scale : image.height * scale;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.clearRect(0, 0, width, height);
|
||||
ctx.drawImage(image, 0, 0, width, height);
|
||||
resolve(canvas);
|
||||
};
|
||||
image.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -61,11 +61,14 @@ export async function restoreFabricObject(serializedObject, canvas) {
|
||||
|
||||
/**
|
||||
* 获取对象黑白通道画布
|
||||
* @param {fabric.Object} object - 要处理的 fabric 对象
|
||||
* @param {ImageData} revData - 相反的ImageData,白通道的相同位置是否为透明,revData为白色为透明,黑色为不透明
|
||||
* @returns {HTMLCanvasElement|null} 包含黑白通道的画布,或 null 如果失败
|
||||
*/
|
||||
export function getObjectAlphaToCanvas(object) {
|
||||
export function getObjectAlphaToCanvas(object, revData) {
|
||||
const image = object.getElement();
|
||||
const { width, height } = image;
|
||||
if(!width || !height){
|
||||
if (!width || !height) {
|
||||
console.warn("对象没有元素");
|
||||
return null;
|
||||
}
|
||||
@@ -80,12 +83,23 @@ export function getObjectAlphaToCanvas(object) {
|
||||
const g = data.data[i + 1];
|
||||
const b = data.data[i + 2];
|
||||
const a = data.data[i + 3];
|
||||
const revR = revData?.data[i + 0] || 0;
|
||||
const revG = revData?.data[i + 1] || 0;
|
||||
const revB = revData?.data[i + 2] || 0;
|
||||
const revA = revData?.data[i + 3] || 0;
|
||||
if (r || g || b || a) {
|
||||
data.data[i + 0] = 255;
|
||||
data.data[i + 1] = 255;
|
||||
data.data[i + 2] = 255;
|
||||
data.data[i + 3] = 255;
|
||||
}else{
|
||||
if (revR || revG || revB || revA) {
|
||||
data.data[i + 0] = 0;
|
||||
data.data[i + 1] = 0;
|
||||
data.data[i + 2] = 0;
|
||||
data.data[i + 3] = 0;
|
||||
} else {
|
||||
data.data[i + 0] = 255;
|
||||
data.data[i + 1] = 255;
|
||||
data.data[i + 2] = 255;
|
||||
data.data[i + 3] = 255;
|
||||
}
|
||||
} else {
|
||||
data.data[i + 0] = 0;
|
||||
data.data[i + 1] = 0;
|
||||
data.data[i + 2] = 0;
|
||||
|
||||
@@ -184,10 +184,16 @@ const createClippedDataURLByCanvas = async ({
|
||||
console.log("🖼️ 使用图像遮罩裁剪方法生成DataURL");
|
||||
|
||||
// 使用优化后的边界计算,确保包含描边区域
|
||||
const optimizedBounds = calculateOptimizedBounds(
|
||||
clippingObject,
|
||||
fabricObjects
|
||||
);
|
||||
// const optimizedBounds = calculateOptimizedBounds(
|
||||
// clippingObject,
|
||||
// fabricObjects
|
||||
// );
|
||||
const optimizedBounds = {
|
||||
left: clippingObject.left - clippingObject.width / 2,
|
||||
top: clippingObject.top - clippingObject.height / 2,
|
||||
width: clippingObject.width,
|
||||
height: clippingObject.height,
|
||||
}
|
||||
|
||||
// 使用高分辨率以保证质量
|
||||
const pixelRatio = window.devicePixelRatio || 1;
|
||||
|
||||
Reference in New Issue
Block a user