- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在努力思考 globalCompositeOperation通过尝试组合这两个示例来获得属性:JSFiddle和 Codepen .
前者使用destination-out
,后者使用source-over
。是否可以在 Codepen 中使用火热光标,但也可以像在 Fiddle 中一样,让它删除用户点击的覆盖填充部分?
如有任何帮助,我们将不胜感激。如有必要,我可以结合 Codepen 上的演示使用相同的方法。
相关Fiddle代码:
function drawDot(mouseX,mouseY){
bridgeCanvas.beginPath();
bridgeCanvas.arc(mouseX, mouseY, brushRadius, 0, 2*Math.PI, true);
bridgeCanvas.fillStyle = '#000';
bridgeCanvas.globalCompositeOperation = "destination-out";
bridgeCanvas.fill();
}
相关Codepen代码:
Fire.prototype.clearCanvas = function(){
this.ctx.globalCompositeOperation = "source-over";
this.ctx.fillStyle = "rgba( 15, 5, 2, 1 )";
this.ctx.fillRect( 0, 0, window.innerWidth, window.innerHeight );
this.ctx.globalCompositeOperation = "lighter";
this.ctx.rect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.fillStyle = this.pattern;
this.ctx.fill();/**/
}
最佳答案
正如我在评论中所说,您必须至少将代码分为两部分。
cropper 函数使用 "destination-out"
合成操作来移除 Canvas 上应该绘制新像素的已经绘制的像素。在您的版本中,它使用背景图像,一旦删除了前景像素,您就可以看到这个背景,因为在 Canvas 的现在透明区域中。
另一方面,火焰使用'"lighter"'、"color-dodge"
和"soft-light"
混合操作。这将添加现有像素和新绘制像素的颜色。
至少第一个,如果用于透明区域,将与默认的 "source-over"
复合操作相同。因此,您需要将背景图像绘制到 Canvas 上才能在混合中使用它。
为此,您必须使用第二个屏幕外 Canvas ,您将只应用橡皮擦 “destination-out”
操作。然后,在可见的 Canvas 上,在每个新的橡皮擦帧上,您必须在可见的 Canvas 上绘制背景图像,然后是带有孔的橡皮擦,最后是混合,它会将所有的东西混合在一起。
这是一个快速代码转储,我在其中重写了一点橡皮擦,并修改了 Fire 一个,以使我们的主要功能处理事件和动画循环。
function MainDrawing(){
this.canvas = document.getElementById('main');
this.ctx = this.canvas.getContext('2d');
this.background = new Image();
this.background.src = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/calgary-bridge-1943.jpg"
this.eraser = new Eraser(this.canvas);
this.fire = new Fire(this.canvas);
this.attachEvents();
}
MainDrawing.prototype = {
anim: function(){
if(this.stopped)
return;
this.ctx.globalCompositeOperation = 'source-over';
this.ctx.drawImage(this.background, 0,0);
this.ctx.drawImage(this.eraser.canvas, 0,0);
this.fire.run();
requestAnimationFrame(this.anim.bind(this));
},
stop: function(){
this.stopped = true;
},
attachEvents: function(){
var mouseDown = false;
this.canvas.onmousedown = function(){
mouseDown = true;
};
this.canvas.onmouseup = function(){
mouseDown = false;
};
this.canvas.onmousemove = function(e){
if(mouseDown){
this.eraser.handleClick(e);
}
this.fire.updateMouse(e);
}.bind(this);
}
};
function Eraser(canvas){
this.main = canvas;
this.canvas = canvas.cloneNode();
var ctx = this.ctx = this.canvas.getContext('2d');
this.img = new Image();
this.img.onload = function(){
ctx.drawImage(this, 0, 0);
ctx.globalCompositeOperation = 'destination-out';
};
this.img.src = "https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/calgary-bridge-2013.jpg";
this.getRect();
}
Eraser.prototype = {
getRect: function(){
this.rect = this.main.getBoundingClientRect();
},
handleClick: function(evt){
var x = evt.clientX - this.rect.left;
var y = evt.clientY - this.rect.top;
this.draw(x,y);
},
draw: function(x, y){
this.ctx.beginPath();
this.ctx.arc(x, y, 30, 0, Math.PI*2);
this.ctx.fill();
}
};
var Fire = function(canvas){
this.canvas = canvas;
this.ctx = this.canvas.getContext('2d');
this.aFires = [];
this.aSpark = [];
this.aSpark2 = [];
this.mouse = {
x : this.canvas.width * .5,
y : this.canvas.height * .75,
}
}
Fire.prototype.run = function(){
this.update();
this.draw();
}
Fire.prototype.start = function(){
this.bRuning = true;
this.run();
}
Fire.prototype.stop = function(){
this.bRuning = false;
}
Fire.prototype.update = function(){
this.aFires.push( new Flame( this.mouse ) );
this.aSpark.push( new Spark( this.mouse ) );
this.aSpark2.push( new Spark( this.mouse ) );
for (var i = this.aFires.length - 1; i >= 0; i--) {
if( this.aFires[i].alive )
this.aFires[i].update();
else
this.aFires.splice( i, 1 );
}
for (var i = this.aSpark.length - 1; i >= 0; i--) {
if( this.aSpark[i].alive )
this.aSpark[i].update();
else
this.aSpark.splice( i, 1 );
}
for (var i = this.aSpark2.length - 1; i >= 0; i--) {
if( this.aSpark2[i].alive )
this.aSpark2[i].update();
else
this.aSpark2.splice( i, 1 );
}
}
Fire.prototype.draw = function(){
this.drawHalo();
this.ctx.globalCompositeOperation = "overlay";//or lighter or soft-light
for (var i = this.aFires.length - 1; i >= 0; i--) {
this.aFires[i].draw( this.ctx );
}
this.ctx.globalCompositeOperation = "soft-light";//"soft-light";//"color-dodge";
for (var i = this.aSpark.length - 1; i >= 0; i--) {
if( ( i % 2 ) === 0 )
this.aSpark[i].draw( this.ctx );
}
this.ctx.globalCompositeOperation = "color-dodge";//"soft-light";//"color-dodge";
for (var i = this.aSpark2.length - 1; i >= 0; i--) {
this.aSpark2[i].draw( this.ctx );
}
}
Fire.prototype.updateMouse = function( e ){
this.mouse.x = e.clientX;
this.mouse.y = e.clientY;
}
Fire.prototype.drawHalo = function(){
var r = rand( 300, 350 );
this.ctx.globalCompositeOperation = "lighter";
this.grd = this.ctx.createRadialGradient( this.mouse.x, this.mouse.y,r,this.mouse.x, this.mouse.y, 0 );
this.grd.addColorStop(0,"transparent");
this.grd.addColorStop(1,"rgb( 50, 2, 0 )");
this.ctx.beginPath();
this.ctx.arc( this.mouse.x, this.mouse.y - 100, r, 0, 2*Math.PI );
this.ctx.fillStyle= this.grd;
this.ctx.fill();
}
var Flame = function( mouse ){
this.cx = mouse.x;
this.cy = mouse.y;
this.x = rand( this.cx - 25, this.cx + 25);
this.y = rand( this.cy - 5, this.cy + 5);
this.lx = this.x;
this.ly = this.y;
this.vy = rand( 1, 3 );
this.vx = rand( -1, 1 );
this.r = rand( 30, 40 );
this.life = rand( 2, 7 );
this.alive = true;
this.c = {
h : Math.floor( rand( 2, 40) ),
s : 100,
l : rand( 80, 100 ),
a : 0,
ta : rand( 0.8, 0.9 )
}
}
Flame.prototype.update = function()
{
this.lx = this.x;
this.ly = this.y;
this.y -= this.vy;
this.vy += 0.08;
this.x += this.vx;
if( this.x < this.cx )
this.vx += 0.2;
else
this.vx -= 0.2;
if( this.r > 0 )
this.r -= 0.3;
if( this.r <= 0 )
this.r = 0;
this.life -= 0.12;
if( this.life <= 0 ){
this.c.a -= 0.05;
if( this.c.a <= 0 )
this.alive = false;
}else if( this.life > 0 && this.c.a < this.c.ta ){
this.c.a += .08;
}
}
Flame.prototype.draw = function( ctx ){
this.grd1 = ctx.createRadialGradient( this.x, this.y, this.r*3, this.x, this.y, 0 );
this.grd1.addColorStop( 0.5, "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a/20) + ")" );
this.grd1.addColorStop( 0, "transparent" );
this.grd2 = ctx.createRadialGradient( this.x, this.y, this.r, this.x, this.y, 0 );
this.grd2.addColorStop( 0.5, "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")" );
this.grd2.addColorStop( 0, "transparent" );
ctx.beginPath();
ctx.arc( this.x, this.y, this.r * 3, 0, 2*Math.PI );
ctx.fillStyle = this.grd1;
//ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a/20) + ")";
ctx.fill();
ctx.globalCompositeOperation = "overlay";
ctx.beginPath();
ctx.arc( this.x, this.y, this.r, 0, 2*Math.PI );
ctx.fillStyle = this.grd2;
ctx.fill();
ctx.beginPath();
ctx.moveTo( this.lx , this.ly);
ctx.lineTo( this.x, this.y);
ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, 1)";
ctx.lineWidth = rand( 1, 2 );
ctx.stroke();
ctx.closePath();
}
var Spark = function( mouse ){
this.cx = mouse.x;
this.cy = mouse.y;
this.x = rand( this.cx -40, this.cx + 40);
this.y = rand( this.cy, this.cy + 5);
this.lx = this.x;
this.ly = this.y;
this.vy = rand( 1, 3 );
this.vx = rand( -4, 4 );
this.r = rand( 0, 1 );
this.life = rand( 4, 8 );
this.alive = true;
this.c = {
h : Math.floor( rand( 2, 40) ),
s : 100,
l : rand( 40, 100 ),
a : rand( 0.8, 0.9 )
}
}
Spark.prototype.update = function()
{
this.lx = this.x;
this.ly = this.y;
this.y -= this.vy;
this.x += this.vx;
if( this.x < this.cx )
this.vx += 0.2;
else
this.vx -= 0.2;
this.vy += 0.08;
this.life -= 0.1;
if( this.life <= 0 ){
this.c.a -= 0.05;
if( this.c.a <= 0 )
this.alive = false;
}
}
Spark.prototype.draw = function( ctx ){
ctx.beginPath();
ctx.moveTo( this.lx , this.ly);
ctx.lineTo( this.x, this.y);
ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a / 2) + ")";
ctx.lineWidth = this.r * 2;
ctx.lineCap = 'round';
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.moveTo( this.lx , this.ly);
ctx.lineTo( this.x, this.y);
ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")";
ctx.lineWidth = this.r;
ctx.stroke();
ctx.closePath();
}
rand = function( min, max ){ return Math.random() * ( max - min) + min; };
var app = new MainDrawing();
app.anim();
<canvas id="main" width="750" height="465"></canvas>
关于javascript - Canvas:了解 globalCompositeOperation 以删除部分图像覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40078206/
在使用 ng-lottie 时用于动画。它突然出现构建问题。 Know more . 因此,为了寻找替代品,我正在尝试 ng-particles . 我已经安装了它并按照文档添加了配置。 但是,现在我
我有一个简单的代码,我想为播放器创建蒙版。 ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(level1, 0, 0);
我在 html5 Canvas 的 javascript 中使用 globalCompositeOperation 时遇到问题。 https://jsfiddle.net/6j51kxeh/ 我使用“
我有一个大的源图像,我想在一个圆圈内显示它的一小部分,并使圆圈外的 Canvas 部分保持透明。 Mozilla guide to Compositing with HTML5涵盖两个主题:globa
如何使用此函数在红色和绿色框之间放置一个蓝色框? 我需要实现这个效果。 这是一个 Codepen . HTML JS var canvas = document.getElementById("c
我有一个 Canvas ,其中包含透明背景上的艺术。我像这样降低饱和度: boardCtx.fillStyle = "rgba(0, 0, 0, 1.0)"; boardCtx.globalCompo
我正在尝试创建径向进度 View 。 Canvas 中的第二条弧应该只清除 Canvas 的一小部分,但它却将其全部清除。 我用过: this.ctx.globalCompositeOperation
我如何将 globalCompositeOperation(或任何其他可以给我“multiply”颜色操作的插件)集成到 jCanvas 中jQuery 插件? // How do I get thi
我正在尝试编写 Sierpinski 地毯前几次迭代的简单演示,如下所示: 我想要继续的方法是通过单击以在每一步上以较小的比例应用基本图案蒙版。在我看来,通过从一个黑色方 block 开始,然后使用“
我有这 4 个层。 我想做的是将 red 和 blue 层放入一个 mask 中。但我不希望 purple 或 orange 层受到此掩码的影响(只有 red 和 blue).我设法让它适用于 ora
我正在努力思考 globalCompositeOperation通过尝试组合这两个示例来获得属性:JSFiddle和 Codepen . 前者使用destination-out,后者使用source-
我对 globalCompositeOperation 有疑问。 我的目标是让蓝色元素仅显示在红色元素内部,并且根本不应该在红色矩形外部可见(有点溢出隐藏效果)。另外,红色和蓝色都必须具有转换能力(都
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我正在尝试使用globalCompositeOperation在 内的对象上元素,但我的目标是与 Canvas 外部的对象混合 - 一个简单的 html 标记元素,如段落。 我的最终目标是使用 di
如何使用 globalCompositeOperation 删除某些内容? http://canvaspaint.org/有一个橡皮擦,但那只是一条白线 - 只有当你的背景是白色的时候才行......
我正在尝试使用 Canvas 的 globalCompositeOperation='destination-in' 设置来绘制一系列被径向渐变掩盖的点。我想要的结果显示在下面的屏幕截图中: 相反,我
每年年底我都会制作一个烟花表演 Canvas 效果(Javascript),最后一个是: http://js1k.com/2011-dysentery/demo/955 这个效果很简单:用create
我在这里查看所有不同类型的全局复合操作: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globa
我知道 ctx.globalcompositeoperation=source-over 在使用 drawimage 时有效,但它可以与 putimagedata 一起使用吗? 最佳答案 简短的回答是
有没有一种方法可以“更轻量”地使用 globalCompositeOperation,同时使用 source-atop? (又名打火机,但仅限于已经绘制了一些东西的地方。) 最佳答案 一次只能设置一项
我是一名优秀的程序员,十分优秀!