2015-05-22 55 views
0

我与画布新,所以感谢您的耐心。显示底部画布与阴影效果 - 修剪区域内的阴影

我写了一个引擎,在2个画布元素中创建了2个不同的图层,这两个图层元素相互重叠。它们包含一些生成的图片,这在这里并不重要。
They are on over another

我试图创建一个效果,当我将鼠标移到顶层并单击时,它将显示底层。

事情是这样的:
enter image description here

这是我到目前为止已经试过:

  1. 要canvas元素上使用的透明度和显示底帆布(快,但不能使用)
  2. 重新创建一个剪辑区域。
    每当我按下鼠标我保存当前坐标,如果我使用斜线形成阴影+我真的不知道重新渲染更新的裁剪区域画布


更新裁剪区域是缓慢的如何从中删除线条(见图片)。
Lines show up

如果我删除阴影效果,它的工作原理非常快,但我需要它。

唯一让我想起如何加快速度的方法是保存每次点击的坐标,然后重新计算成一个形状并在其上放置阴影 - 我仍然有线条,但是它会更快,因为没有一千个圈画...

任何帮助将不胜感激!

回答

3

您可以通过画吧黑,把它当做一个伪低通滤波器,利用内置插值浏览器的,但首先:

  • 复制顶层到底层
  • 设置源输入压缩。模式
  • 全部绘制黑色
  • 设置源输入补偿。模式
  • 比例缩小图像至25%
  • 量表25%的区域回升到原始(或双的电流)
  • 量表的50%现在50%区域回升到原始的100%。它会模糊。

根据您想要的模糊程度,您可以添加其他步骤。这就是说:无论阴影是如何扭曲和变形的,模糊阴影都是一种密集的运作。例如,我们可以做出妥协来仅渲染鼠标上的阴影(如下面的演示)。

实施例使用两个层

实施例。顶层让你画任何东西,底部将在绘制后在底部显示影子版本。

var ctx = document.getElementById("top").getContext("2d"), 
 
    bctx = document.getElementById("bottom").getContext("2d"), 
 
    bg = new Image(), 
 
    isDown = false; 
 

 
bg.src = "http://i.imgur.com/R2naCpK.png"; 
 

 
ctx.fillStyle = "#27f"; 
 
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); 
 
ctx.globalCompositeOperation = "destination-out"; // "eraser" 
 

 
ctx.canvas.onmousedown = function(e) {isDown = true}; 
 

 
window.onmousemove = function(e) { 
 
    if (!isDown) return; 
 
    var pos = getPos(ctx.canvas, e); 
 
    ctx.beginPath(); 
 
    ctx.moveTo(pos.x + 10, pos.y); 
 
    ctx.arc(pos.x, pos.y, 10, 0, 2*Math.PI);   // erase while drawing 
 
    ctx.fill(); 
 
}; 
 

 
window.onmouseup = function(e) { 
 
    if (isDown) { 
 
    isDown = false; 
 
    makeShadow(); 
 
    } 
 
}; 
 

 
function makeShadow(){ 
 
    var w = bctx.canvas.width, 
 
     h = bctx.canvas.height, 
 
     offset = 7, 
 
     alpha = 0.75; 
 
    
 
    // reset alpha 
 
    bctx.globalAlpha = 1; 
 

 
    // normal comp mode to clear as it is faster than using "copy" 
 
    bctx.globalCompositeOperation = "source-over"; 
 
    bctx.clearRect(0, 0, w, h); 
 

 
    // copy top-layer to bottom-layer 
 
    bctx.drawImage(ctx.canvas, 0, 0); 
 
    
 
    // comp. mode will only draw in to non-alpha pixels next 
 
    bctx.globalCompositeOperation = "source-in"; 
 
    
 
    // black overlay 
 
    bctx.fillRect(0, 0, w, h); 
 
    
 
    // copy mode so we don't need an extra canvas 
 
    bctx.globalCompositeOperation = "copy"; 
 
    
 
    // step 1: reduce to 50% (quality related - create more steps to increase blur/quality) 
 
    bctx.drawImage(bctx.canvas, 0, 0, w, h, 0, 0, w * 0.5, h * 0.5); 
 
    
 
    bctx.drawImage(bctx.canvas, 0, 0, w * 0.5, h * 0.5, 0, 0, w * 0.25, h * 0.25); 
 
    bctx.drawImage(bctx.canvas, 0, 0, w * 0.25, h * 0.25, 0, 0, w * 0.5, h * 0.5); 
 
    
 
    // shadow transparency 
 
    bctx.globalAlpha = alpha; 
 
    
 
    // step 2: draw back up to 100%, draw offset 
 
    bctx.drawImage(bctx.canvas, 0, 0, w * 0.5, h * 0.5, offset, offset, w, h); 
 

 
    // comp in background image 
 
    bctx.globalCompositeOperation = "destination-over"; 
 
    bctx.drawImage(bg, 0, 0, w, h); 
 
} 
 

 
function getPos(canvas, e) { 
 
    var r = canvas.getBoundingClientRect(); 
 
    return {x: e.clientX - r.left, y: e.clientY - r.top}; 
 
}
div {position:relative;border:1px solid #000;width:500px;height:500px} 
 
canvas {position:absolute;left:0;top:0} 
 
#bottom {background:#eee}
<div> 
 
    <canvas id="bottom" width=500 height=500></canvas> 
 
    <canvas id="top" width=500 height=500></canvas> 
 
</div>

+0

妈呀,这看起来令人惊讶!我需要稍后再检查一下,不过谢谢! –

+0

Upvote效果酷,合成效果好。顺便说一句,如果你做了这样的事情,你的演示会更酷:'#bottom {background-image:url('someCoolBackground.png');}'而不是#eee。 :-) – markE

+1

只是想让你知道,这有很大的帮助。我在两层都有照片,所以我必须为影子制作第三张照片。我将底层图层复制到新图层上,并在其上运行效果。你认为只有2个可以完成吗? –