mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-28 01:30:23 +01:00
promiseがコールバックを待たないのを修正
This commit is contained in:
parent
1a3e96bf7f
commit
88e0b522ea
1 changed files with 133 additions and 132 deletions
|
@ -113,146 +113,151 @@ export function canPreview(config: Partial<WatermarkConfig | WatermarkUserConfig
|
||||||
* @param el ウォーターマークを適用するキャンバス
|
* @param el ウォーターマークを適用するキャンバス
|
||||||
* @param config ウォーターマークの設定
|
* @param config ウォーターマークの設定
|
||||||
*/
|
*/
|
||||||
export async function applyWatermark(img: string | Blob, el: HTMLCanvasElement, config: WatermarkConfig | null) {
|
export function applyWatermark(img: string | Blob, el: HTMLCanvasElement | OffscreenCanvas, config: WatermarkConfig | null) {
|
||||||
const canvas = el;
|
return new Promise<void>(async (resolve) => {
|
||||||
const ctx = canvas.getContext('2d')!;
|
const canvas = el;
|
||||||
const imgEl = new Image();
|
const ctx = canvas.getContext('2d')!;
|
||||||
imgEl.onload = async () => {
|
const imgEl = new Image();
|
||||||
canvas.width = imgEl.width;
|
imgEl.onload = async () => {
|
||||||
canvas.height = imgEl.height;
|
canvas.width = imgEl.width;
|
||||||
ctx.drawImage(imgEl, 0, 0);
|
canvas.height = imgEl.height;
|
||||||
|
ctx.drawImage(imgEl, 0, 0);
|
||||||
|
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
if (config.fileUrl) {
|
if (config.fileUrl) {
|
||||||
const watermark = new Image();
|
const watermark = new Image();
|
||||||
watermark.onload = () => {
|
watermark.onload = () => {
|
||||||
const canvasAspectRatio = canvas.width / canvas.height; // 横長は1より大きい
|
const canvasAspectRatio = canvas.width / canvas.height; // 横長は1より大きい
|
||||||
const watermarkAspectRatio = watermark.width / watermark.height; // 横長は1より大きい
|
const watermarkAspectRatio = watermark.width / watermark.height; // 横長は1より大きい
|
||||||
const { width, height } = (() => {
|
const { width, height } = (() => {
|
||||||
const desiredWidth = canvas.width * (config.sizeRatio ?? 1);
|
const desiredWidth = canvas.width * (config.sizeRatio ?? 1);
|
||||||
const desiredHeight = canvas.height * (config.sizeRatio ?? 1);
|
const desiredHeight = canvas.height * (config.sizeRatio ?? 1);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(watermarkAspectRatio > 1 && canvasAspectRatio > 1) || // 両方横長
|
(watermarkAspectRatio > 1 && canvasAspectRatio > 1) || // 両方横長
|
||||||
(watermarkAspectRatio < 1 && canvasAspectRatio < 1) // 両方縦長
|
(watermarkAspectRatio < 1 && canvasAspectRatio < 1) // 両方縦長
|
||||||
) {
|
) {
|
||||||
// 横幅を基準にウォーターマークのサイズを決定
|
// 横幅を基準にウォーターマークのサイズを決定
|
||||||
return {
|
return {
|
||||||
width: desiredWidth,
|
width: desiredWidth,
|
||||||
height: desiredWidth / watermarkAspectRatio,
|
height: desiredWidth / watermarkAspectRatio,
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
// 縦幅を基準にウォーターマークのサイズを決定
|
|
||||||
return {
|
|
||||||
width: desiredHeight * watermarkAspectRatio,
|
|
||||||
height: desiredHeight,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
ctx.globalAlpha = config.opacity ?? 1;
|
|
||||||
|
|
||||||
if (config.repeat) {
|
|
||||||
// 余白をもたせた状態のウォーターマークを作成しておく(それをパターン繰り返しする)
|
|
||||||
const resizedWatermark = document.createElement('canvas');
|
|
||||||
resizedWatermark.width = width + (config.padding ? (config.padding.left ?? 0) + (config.padding.right ?? 0) : 0);
|
|
||||||
resizedWatermark.height = height + (config.padding ? (config.padding.top ?? 0) + (config.padding.bottom ?? 0) : 0);
|
|
||||||
const resizedCtx = resizedWatermark.getContext('2d')!;
|
|
||||||
resizedCtx.drawImage(
|
|
||||||
watermark,
|
|
||||||
(config.padding ? config.padding.left ?? 0 : 0),
|
|
||||||
(config.padding ? config.padding.top ?? 0 : 0),
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
);
|
|
||||||
|
|
||||||
const pattern = ctx.createPattern(resizedWatermark, 'repeat');
|
|
||||||
if (pattern) {
|
|
||||||
ctx.fillStyle = pattern;
|
|
||||||
if (config.rotate != null && config.rotate !== 0) {
|
|
||||||
const rotateRad = config.rotate * Math.PI / 180;
|
|
||||||
ctx.translate(canvas.width / 2, canvas.height / 2);
|
|
||||||
ctx.rotate(rotateRad);
|
|
||||||
ctx.translate(-canvas.width / 2, -canvas.height / 2);
|
|
||||||
const rotatedWidth = Math.abs(canvas.width * Math.cos(rotateRad)) + Math.abs(canvas.height * Math.sin(rotateRad));
|
|
||||||
const rotatedHeight = Math.abs(canvas.width * Math.sin(rotateRad)) + Math.abs(canvas.height * Math.cos(rotateRad));
|
|
||||||
const x = Math.abs(rotatedWidth - canvas.width) / -2;
|
|
||||||
const y = Math.abs(rotatedHeight - canvas.height) / -2;
|
|
||||||
ctx.fillRect(x, y, rotatedWidth, rotatedHeight);
|
|
||||||
} else {
|
} else {
|
||||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
// 縦幅を基準にウォーターマークのサイズを決定
|
||||||
}
|
return {
|
||||||
}
|
width: desiredHeight * watermarkAspectRatio,
|
||||||
} else {
|
height: desiredHeight,
|
||||||
const x = (() => {
|
};
|
||||||
switch (config.anchor) {
|
|
||||||
case 'center':
|
|
||||||
case 'top':
|
|
||||||
case 'bottom':
|
|
||||||
return (canvas.width - width) / 2;
|
|
||||||
case 'left':
|
|
||||||
case 'top-left':
|
|
||||||
case 'bottom-left':
|
|
||||||
return 0 + (config.padding ? config.padding.left ?? 0 : 0);
|
|
||||||
case 'right':
|
|
||||||
case 'top-right':
|
|
||||||
case 'bottom-right':
|
|
||||||
return canvas.width - width - (config.padding ? config.padding.right ?? 0 : 0);
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const y = (() => {
|
ctx.globalAlpha = config.opacity ?? 1;
|
||||||
let rotateY = 0; // 回転によるY座標の補正
|
|
||||||
|
|
||||||
if (config.rotate != null && config.rotate !== 0 && !config.noBoundingBoxExpansion) {
|
if (config.repeat) {
|
||||||
|
// 余白をもたせた状態のウォーターマークを作成しておく(それをパターン繰り返しする)
|
||||||
|
const resizedWatermark = document.createElement('canvas');
|
||||||
|
resizedWatermark.width = width + (config.padding ? (config.padding.left ?? 0) + (config.padding.right ?? 0) : 0);
|
||||||
|
resizedWatermark.height = height + (config.padding ? (config.padding.top ?? 0) + (config.padding.bottom ?? 0) : 0);
|
||||||
|
const resizedCtx = resizedWatermark.getContext('2d')!;
|
||||||
|
resizedCtx.drawImage(
|
||||||
|
watermark,
|
||||||
|
(config.padding ? config.padding.left ?? 0 : 0),
|
||||||
|
(config.padding ? config.padding.top ?? 0 : 0),
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
|
||||||
|
const pattern = ctx.createPattern(resizedWatermark, 'repeat');
|
||||||
|
if (pattern) {
|
||||||
|
ctx.fillStyle = pattern;
|
||||||
|
if (config.rotate != null && config.rotate !== 0) {
|
||||||
|
const rotateRad = config.rotate * Math.PI / 180;
|
||||||
|
ctx.translate(canvas.width / 2, canvas.height / 2);
|
||||||
|
ctx.rotate(rotateRad);
|
||||||
|
ctx.translate(-canvas.width / 2, -canvas.height / 2);
|
||||||
|
const rotatedWidth = Math.abs(canvas.width * Math.cos(rotateRad)) + Math.abs(canvas.height * Math.sin(rotateRad));
|
||||||
|
const rotatedHeight = Math.abs(canvas.width * Math.sin(rotateRad)) + Math.abs(canvas.height * Math.cos(rotateRad));
|
||||||
|
const x = Math.abs(rotatedWidth - canvas.width) / -2;
|
||||||
|
const y = Math.abs(rotatedHeight - canvas.height) / -2;
|
||||||
|
ctx.fillRect(x, y, rotatedWidth, rotatedHeight);
|
||||||
|
} else {
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const x = (() => {
|
||||||
|
switch (config.anchor) {
|
||||||
|
case 'center':
|
||||||
|
case 'top':
|
||||||
|
case 'bottom':
|
||||||
|
return (canvas.width - width) / 2;
|
||||||
|
case 'left':
|
||||||
|
case 'top-left':
|
||||||
|
case 'bottom-left':
|
||||||
|
return 0 + (config.padding ? config.padding.left ?? 0 : 0);
|
||||||
|
case 'right':
|
||||||
|
case 'top-right':
|
||||||
|
case 'bottom-right':
|
||||||
|
return canvas.width - width - (config.padding ? config.padding.right ?? 0 : 0);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
const y = (() => {
|
||||||
|
let rotateY = 0; // 回転によるY座標の補正
|
||||||
|
|
||||||
|
if (config.rotate != null && config.rotate !== 0 && !config.noBoundingBoxExpansion) {
|
||||||
|
const rotateRad = config.rotate * Math.PI / 180;
|
||||||
|
rotateY = Math.abs(Math.abs(width * Math.sin(rotateRad)) + Math.abs(height * Math.cos(rotateRad)) - height) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (config.anchor) {
|
||||||
|
case 'center':
|
||||||
|
case 'left':
|
||||||
|
case 'right':
|
||||||
|
return (canvas.height - height) / 2;
|
||||||
|
case 'top':
|
||||||
|
case 'top-left':
|
||||||
|
case 'top-right':
|
||||||
|
return rotateY + (config.padding ? config.padding.top ?? 0 : 0);
|
||||||
|
case 'bottom':
|
||||||
|
case 'bottom-left':
|
||||||
|
case 'bottom-right':
|
||||||
|
return canvas.height - height - (config.padding ? config.padding.bottom ?? 0 : 0) - rotateY;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
if (config.rotate) {
|
||||||
const rotateRad = config.rotate * Math.PI / 180;
|
const rotateRad = config.rotate * Math.PI / 180;
|
||||||
rotateY = Math.abs(Math.abs(width * Math.sin(rotateRad)) + Math.abs(height * Math.cos(rotateRad)) - height) / 2;
|
ctx.translate(x + width / 2, y + height / 2);
|
||||||
|
ctx.rotate(rotateRad);
|
||||||
|
ctx.translate(-x - width / 2, -y - height / 2);
|
||||||
}
|
}
|
||||||
|
ctx.drawImage(watermark, x, y, width, height);
|
||||||
switch (config.anchor) {
|
|
||||||
case 'center':
|
|
||||||
case 'left':
|
|
||||||
case 'right':
|
|
||||||
return (canvas.height - height) / 2;
|
|
||||||
case 'top':
|
|
||||||
case 'top-left':
|
|
||||||
case 'top-right':
|
|
||||||
return rotateY + (config.padding ? config.padding.top ?? 0 : 0);
|
|
||||||
case 'bottom':
|
|
||||||
case 'bottom-left':
|
|
||||||
case 'bottom-right':
|
|
||||||
return canvas.height - height - (config.padding ? config.padding.bottom ?? 0 : 0) - rotateY;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
if (config.rotate) {
|
|
||||||
const rotateRad = config.rotate * Math.PI / 180;
|
|
||||||
ctx.translate(x + width / 2, y + height / 2);
|
|
||||||
ctx.rotate(rotateRad);
|
|
||||||
ctx.translate(-x - width / 2, -y - height / 2);
|
|
||||||
}
|
}
|
||||||
ctx.drawImage(watermark, x, y, width, height);
|
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
let watermarkUrl: string;
|
||||||
|
if (config.fileUrl == null && config.fileId != null) {
|
||||||
|
const res = await misskeyApi('drive/files/show', { fileId: config.fileId });
|
||||||
|
watermarkUrl = res.url;
|
||||||
|
// 抜けてたら保存
|
||||||
|
defaultStore.set('watermarkConfig', { ...config, fileUrl: watermarkUrl });
|
||||||
|
} else {
|
||||||
|
watermarkUrl = config.fileUrl!;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let watermarkUrl: string;
|
watermark.src = config.__bypassMediaProxy ? config.fileUrl : getProxiedImageUrl(watermarkUrl, undefined, true);
|
||||||
if (config.fileUrl == null && config.fileId != null) {
|
|
||||||
const res = await misskeyApi('drive/files/show', { fileId: config.fileId });
|
|
||||||
watermarkUrl = res.url;
|
|
||||||
// 抜けてたら保存
|
|
||||||
defaultStore.set('watermarkConfig', { ...config, fileUrl: watermarkUrl });
|
|
||||||
} else {
|
|
||||||
watermarkUrl = config.fileUrl!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
watermark.src = config.__bypassMediaProxy ? config.fileUrl : getProxiedImageUrl(watermarkUrl, undefined, true);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof img === 'string') {
|
||||||
|
imgEl.src = img;
|
||||||
|
} else {
|
||||||
|
imgEl.src = URL.createObjectURL(img);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
if (typeof img === 'string') {
|
|
||||||
imgEl.src = img;
|
|
||||||
} else {
|
|
||||||
imgEl.src = URL.createObjectURL(img);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -262,12 +267,8 @@ export async function applyWatermark(img: string | Blob, el: HTMLCanvasElement,
|
||||||
* @param config ウォーターマークの設定
|
* @param config ウォーターマークの設定
|
||||||
* @returns ウォーターマークを適用した画像のBlob
|
* @returns ウォーターマークを適用した画像のBlob
|
||||||
*/
|
*/
|
||||||
export function getWatermarkAppliedImage(img: Blob, config: WatermarkConfig): Promise<Blob> {
|
export async function getWatermarkAppliedImage(img: Blob, config: WatermarkConfig): Promise<Blob> {
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
applyWatermark(img, canvas, config);
|
await applyWatermark(img, canvas, config);
|
||||||
return new Promise<Blob>(resolve => {
|
return new Promise(resolve => canvas.toBlob(blob => resolve(blob!)));
|
||||||
canvas.toBlob(blob => {
|
|
||||||
resolve(blob!);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue