如何剪辑/使用 globalCompositeOperation = "desination-out" 从我的 Canvas 中排除 2 个圆圈?
How do I clip / use globalCompositeOperation = "desination-out" to exclude 2 circles from my Canvas?
我正在尝试找出 CanvasRenderingContext2D.globalCompositeOperation = "destination-out
以创建 "Fog of War" 效果。
给出这个例子
https://jsfiddle.net/wobzpjLL/
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// a green background box
ctx.fillStyle = "green";
ctx.fillRect(0,0,300,150);
// a line
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(300, 150);
ctx.stroke();
// Fog of war
ctx.fillStyle = "black";
ctx.fillRect(0,0,300,150);
// Here I want two circles that shows the background (green & line)
// text
ctx.fillStyle = "red";
ctx.font = "30px Arial";
ctx.fillText("Hello World",10,50);
如何创建两个排除黑色覆盖层的圆圈,以便用户可以看到绿色背景和线条,在这两个圆圈内,其他地方都是黑色(因此产生 war 效果的雾)?
使用面具
使用合成war 的雾
实现遮罩的最简单方法是创建离屏 canvas 并将遮罩渲染到其上。然后在制作动画时渲染世界,然后使用 "destination-in"
应用蒙版。您可以使用 canvas CSS 背景作为雾(如演示中所做的那样),或者您可以使用文本在演示中使用 "destination-over"
渲染顶部的雾。
分层渲染
个人和为了性能(如果代码需要它可以得到的每一个中断)我会避免 globalCompositeOperation
并通过在演示中创建掩码的反转来渲染世界上的雾。这仅添加了一个额外的渲染调用,无需更改复合操作
使用组合的示例
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function createCanvas(){
var c = document.createElement("canvas");
c.width = 300;
c.height = 150;
c.ctx = c.getContext("2d");
return c;
}
// draw game world on offscreen canvas
function drawBackground(ctx){
ctx.fillStyle = "green";
ctx.fillRect(0,0,300,150);
// a line
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = "#08A";
ctx.lineTo(0, 0);
ctx.lineTo(300, 150);
ctx.stroke();
}
// create and render world
var bGround = createCanvas();
drawBackground(bGround.ctx)
// create mask
var grad = ctx.createRadialGradient(0,0,60,0,0,0);
grad.addColorStop(0,"rgba(0,0,0,0.0)");
grad.addColorStop(0.2,"rgba(0,0,0,1)");
grad.addColorStop(1,"rgba(0,0,0,1)");
var mask = createCanvas();
mask.ctx.setTransform(1,0,0,1,75,75);
mask.ctx.fillStyle = grad;
mask.ctx.beginPath();
mask.ctx.arc(0,0,60,0,Math.PI*2);
mask.ctx.fill();
mask.ctx.setTransform(1,0,0,1,225,75);
mask.ctx.beginPath();
mask.ctx.arc(0,0,60,0,Math.PI*2);
mask.ctx.fill();
document.body.appendChild(mask);
// draws the fog
function drawFog(ctx,x){
ctx.globalCompositeOperation = "destination-in";
ctx.drawImage(mask, x, 0);
ctx.globalCompositeOperation = "source-over";
}
ctx.fillStyle = "red";
ctx.font = "30px Arial";
function loop(time){
ctx.drawImage(bGround,0,0);
drawFog(ctx,Math.sin(time / 1000) *20);
ctx.globalCompositeOperation = "destination-over";
ctx.fillText("Hello World",10,50);
ctx.globalCompositeOperation = "source-over";
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
canvas {
border:1px solid #d3d3d3;
}
<canvas id="myCanvas" width="300" height="150" style="background : black;" ></canvas>
<div>Pre rendered offscreen mask shown below for display only.</div>
我正在尝试找出 CanvasRenderingContext2D.globalCompositeOperation = "destination-out
以创建 "Fog of War" 效果。
给出这个例子
https://jsfiddle.net/wobzpjLL/
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// a green background box
ctx.fillStyle = "green";
ctx.fillRect(0,0,300,150);
// a line
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(300, 150);
ctx.stroke();
// Fog of war
ctx.fillStyle = "black";
ctx.fillRect(0,0,300,150);
// Here I want two circles that shows the background (green & line)
// text
ctx.fillStyle = "red";
ctx.font = "30px Arial";
ctx.fillText("Hello World",10,50);
如何创建两个排除黑色覆盖层的圆圈,以便用户可以看到绿色背景和线条,在这两个圆圈内,其他地方都是黑色(因此产生 war 效果的雾)?
使用面具
使用合成war 的雾
实现遮罩的最简单方法是创建离屏 canvas 并将遮罩渲染到其上。然后在制作动画时渲染世界,然后使用 "destination-in"
应用蒙版。您可以使用 canvas CSS 背景作为雾(如演示中所做的那样),或者您可以使用文本在演示中使用 "destination-over"
渲染顶部的雾。
分层渲染
个人和为了性能(如果代码需要它可以得到的每一个中断)我会避免 globalCompositeOperation
并通过在演示中创建掩码的反转来渲染世界上的雾。这仅添加了一个额外的渲染调用,无需更改复合操作
使用组合的示例
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function createCanvas(){
var c = document.createElement("canvas");
c.width = 300;
c.height = 150;
c.ctx = c.getContext("2d");
return c;
}
// draw game world on offscreen canvas
function drawBackground(ctx){
ctx.fillStyle = "green";
ctx.fillRect(0,0,300,150);
// a line
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = "#08A";
ctx.lineTo(0, 0);
ctx.lineTo(300, 150);
ctx.stroke();
}
// create and render world
var bGround = createCanvas();
drawBackground(bGround.ctx)
// create mask
var grad = ctx.createRadialGradient(0,0,60,0,0,0);
grad.addColorStop(0,"rgba(0,0,0,0.0)");
grad.addColorStop(0.2,"rgba(0,0,0,1)");
grad.addColorStop(1,"rgba(0,0,0,1)");
var mask = createCanvas();
mask.ctx.setTransform(1,0,0,1,75,75);
mask.ctx.fillStyle = grad;
mask.ctx.beginPath();
mask.ctx.arc(0,0,60,0,Math.PI*2);
mask.ctx.fill();
mask.ctx.setTransform(1,0,0,1,225,75);
mask.ctx.beginPath();
mask.ctx.arc(0,0,60,0,Math.PI*2);
mask.ctx.fill();
document.body.appendChild(mask);
// draws the fog
function drawFog(ctx,x){
ctx.globalCompositeOperation = "destination-in";
ctx.drawImage(mask, x, 0);
ctx.globalCompositeOperation = "source-over";
}
ctx.fillStyle = "red";
ctx.font = "30px Arial";
function loop(time){
ctx.drawImage(bGround,0,0);
drawFog(ctx,Math.sin(time / 1000) *20);
ctx.globalCompositeOperation = "destination-over";
ctx.fillText("Hello World",10,50);
ctx.globalCompositeOperation = "source-over";
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
canvas {
border:1px solid #d3d3d3;
}
<canvas id="myCanvas" width="300" height="150" style="background : black;" ></canvas>
<div>Pre rendered offscreen mask shown below for display only.</div>