我一直在尝试通过首先创建一个圆角矩形并向其添加阴影来在画布中制作阴影效果,如果我在没有循环的情况下执行此操作一次,一切似乎都工作正常。然而,当我尝试在视频帧中循环执行此操作时,我在背景上应用了太多阴影:-
export const titleRender = async () => {
const canvas = createCanvas(1920, 1080);
const ctx = canvas.getContext('2d');
const img = await loadImage('blueBackground.png')
ctx.drawImage(img, 0, 0, 1920, 1920);
return canvas;
};
const drawEffects = async () => {
const effectsCanvas = createCanvas(1920, 1080)
const ctx = effectsCanvas.getContext('2d');
ctx.beginPath();
ctx.roundRect(77 , 234 , 1766 , 846,[20, 20, 0, 0]);
ctx.closePath()
// Apply drop shadow effect
ctx.shadowColor = '#00ff44';
ctx.shadowBlur = 68;
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 20;
// Set the background color and fill the rectangle
ctx.fillStyle = '#ffaadd';
ctx.fill();
ctx.strokeStyle = 'rgba(26, 26, 26, 0.46)';
ctx.lineWidth = 2;
ctx.stroke();
// Reset shadow settings
ctx.shadowColor = 'transparent';
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.clip()
//ctx.drawImage(cropedFrame as any, downscaleX, downscaleY, scaledWidth, scaledHeight);
return effectsCanvas;
}
async function test() {
const img = await loadImage('overlayimage.jpg')
const backgroundCanvas= createCanvas(1920, 1080)
console.log('hii')
const titleComposition = await titleRender();
const effectsCanvas = await drawEffects()
const backgroundCTX = backgroundCanvas.getContext('2d');
const effectsCTX = effectsCanvas.getContext('2d');
backgroundCTX.drawImage(titleComposition, 0, 0, titleComposition.width, titleComposition.height)
effectsCTX.drawImage(img, 77 , 234 , 1766 , 846 )
backgroundCTX.drawImage(effectsCanvas, 0, 0, effectsCanvas.width, effectsCanvas.height)
const out = fs.createWriteStream(`comp/ren${1}.png`);
const stream = backgroundCanvas.createPNGStream();
stream.pipe(out);
out.on('finish', () => console.log('Wows'))
return true;
}
test()
但是,我尝试对循环中的视频帧执行类似的操作:-
async function test() {
const img = await loadImage('green/overlay.jpg')
const backgroundCanvas= createCanvas(1920, 1080)
console.log('hii')
const titleComposition = await titleRender();
const effectsCanvas = await drawEffects()
const backgroundCTX = backgroundCanvas.getContext('2d');
const effectsCTX = effectsCanvas.getContext('2d');
backgroundCTX.drawImage(titleComposition, 0, 0, titleComposition.width, titleComposition.height)
for (let i = 0; i<=20; i++) {
effectsCTX.drawImage(img, 77 , 234 , 1766 , 846 )
backgroundCTX.drawImage(effectsCanvas, 0, 0, effectsCanvas.width, effectsCanvas.height)
const out = fs.createWriteStream(`comp/ren${1}.png`);
const stream = backgroundCanvas.createPNGStream();
stream.pipe(out);
out.on('finish', () => console.log('Wows'))
}
return true;
}
test()
如果您不想在目标画布上累积发光,则需要每帧清除目标画布。
尝试使用下面的代码片段呈现的按钮,看看在每一帧上绘制蓝色“标题”或仅绘制一次之间的区别。我还在覆盖层中添加了一些动画,因此更容易看到轨迹如何累积。
function createCanvas(width, height) {
const c = document.createElement("canvas");
return Object.assign(c, { width, height });
}
const titleRender = async () => {
const canvas = createCanvas(1920, 1080);
const ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, 1920, 1080);
return canvas;
};
const drawEffects = async () => {
const effectsCanvas = createCanvas(1920, 1080);
const ctx = effectsCanvas.getContext("2d");
ctx.beginPath();
ctx.roundRect(77, 234, 1766, 846, [20, 20, 0, 0]);
ctx.closePath();
// Apply drop shadow effect
ctx.shadowColor = "#00ff44";
ctx.shadowBlur = 68;
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 20;
// Set the background color and fill the rectangle
ctx.fillStyle = "#ffaadd";
ctx.fill();
ctx.strokeStyle = "rgba(26, 26, 26, 0.46)";
ctx.lineWidth = 2;
ctx.stroke();
// Reset shadow settings
ctx.shadowColor = "transparent";
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.clip();
return effectsCanvas;
};
async function sleep(number) {
return new Promise((resolve) => setTimeout(() => resolve(), number));
}
async function test(drawBgEveryFrame) {
const backgroundCanvas = createCanvas(1920, 1080);
const titleComposition = await titleRender();
const effectsCanvas = await drawEffects();
const backgroundCTX = backgroundCanvas.getContext("2d");
const effectsCTX = effectsCanvas.getContext("2d");
for (let i = 0; i <= 20; i++) {
if (i === 0 || drawBgEveryFrame) {
backgroundCTX.drawImage(
titleComposition,
0,
0,
titleComposition.width,
titleComposition.height,
);
}
backgroundCTX.drawImage(
effectsCanvas,
0,
Math.cos((i / 20) * 6.283) * 50,
effectsCanvas.width,
effectsCanvas.height,
);
document.getElementById("img").src = backgroundCanvas.toDataURL();
await sleep(100);
}
}
<button onclick="test(false)">Go, without clearing the frames</button> <button onclick="test(true)">Go, but draw background every frame</button>
<img id="img" style="width:100%;border:1px solid black">