2015-01-11 108 views
2

在我的畫布中,我有一個隨光標移動的圓形。 我想給這個小小的內在影子,但它不起作用。如何爲畫布形狀設置圓形內部陰影?

這裏是代碼和演示:JSFIDDLE

function writeMessage(canvas, message, x, y) { 
    var context = canvas.getContext('2d'); 
    context.clearRect(0, 0, canvas.width, canvas.height); 

    var pattern = context.createPattern(imageResized, 'no-repeat'); //Use imageResized, not imageObj. 
    context.fillStyle = pattern; 
    context.fill(); 

    context.font = '28pt Calibri'; 
    context.fillStyle = 'white'; 
    //context.fillText(message, x, y); 
    context.beginPath(); 
    context.arc(x, y, 50, 0, 2 * Math.PI); 
    context.stroke(); 


    context.beginPath(); 
    context.lineWidth = 5; 
    context.shadowColor = 'black'; 
    context.strokeStyle = "rgba(0,0,0,1)"; 
    context.shadowBlur = 15; 
    context.shadowOffsetX = 0; 
    context.shadowOffsetY = 0; 
    context.arc(x, y, 50, 0, 2 * Math.PI, false); 
    context.stroke(); 
    context.restore(); 

} 

我發現如果我添加context.clip();但隨後它會使整個畫布墜毀的設置是可行的。

任何想法爲這個圈子有一個內在的影子?

回答

2

嘗試在提供框架的弧線之前繪製要提供陰影的弧線。在beginPath之前保存上下文狀態,並在陰影弧線中風之後將其恢復。您需要使陰影弧線半徑小於框架弧線,以便陰影的外邊緣由框架弧線的線條覆蓋。陰影弧外部的外部陰影仍然被繪製,但被構圖弧覆蓋。

例子:

context.save(); 
context.beginPath(); 
context.lineWidth = 6; 
context.shadowColor = 'black'; 
context.strokeStyle = "rgba(0,0,0,1)"; 
context.shadowBlur = 15; 
context.shadowOffsetX = 0; 
context.shadowOffsetY = 0; 
context.arc(x, y, 47, 0, 2 * Math.PI, false); 
context.stroke(); 
context.restore(); 

context.save(); 
context.beginPath(); 
context.lineWidth = 6; 
context.arc(x, y, 50, 0, 2 * Math.PI); 
context.stroke(); 
context.restore(); 

您需要調整大小,顏色,以及圓弧的線條寬度來獲得你想要的效果。

2

enter image description here

如果一個繁忙的處理像鼠標移動中做.clip崩潰您的瀏覽器,你可以預先建立與內部影子你的圈子,一旦在你的應用程序的開始,然後再利用與預建圈對性能影響不大。

以下是如何創建包含內部陰影的圓的內存畫布。是的,它使用.clip,但它只在應用程序開始時使用一次。

var PI2=Math.PI*2; 
var cut=document.createElement('canvas'); 
var cutCtx=cut.getContext('2d'); 
cut.width=100; 
cut.height=100; 
cutCtx.arc(50,50,50,0,Math.PI*2); 
cutCtx.closePath(); 
cutCtx.clip(); 
cutCtx.shadowColor='black' 
cutCtx.shadowBlur=15; 
for(var i=0;i<15;i++){ 
    cutCtx.stroke(); 
} 

然後在mousemove事件中繪製預構建的圓並不是很昂貴。

這裏的示例代碼和演示:

var canvas=document.getElementById("canvas"); 
 
var ctx=canvas.getContext("2d"); 
 
var cw=canvas.width; 
 
var ch=canvas.height; 
 
var $canvas=$("#canvas"); 
 
var canvasOffset=$canvas.offset(); 
 
var offsetX=canvasOffset.left; 
 
var offsetY=canvasOffset.top; 
 
var scrollX=$canvas.scrollLeft(); 
 
var scrollY=$canvas.scrollTop(); 
 

 
var PI2=Math.PI*2; 
 
var cut=document.createElement('canvas'); 
 
var cutCtx=cut.getContext('2d'); 
 
cut.width=100; 
 
cut.height=100; 
 
cutCtx.arc(50,50,50,0,Math.PI*2); 
 
cutCtx.closePath(); 
 
cutCtx.clip(); 
 
cutCtx.shadowColor='black' 
 
cutCtx.shadowBlur=15; 
 
for(var i=0;i<15;i++){ 
 
    cutCtx.stroke(); 
 
} 
 

 
ctx.fillStyle='white'; 
 
ctx.fillRect(0,0,cw,ch); 
 

 
$("#canvas").mousemove(function(e){handleMouseMove(e);}); 
 

 

 
function applyCut(mx,my){ 
 
    // hide the background image by whiteing-out the canvas 
 
    ctx.fillRect(0,0,cw,ch); 
 

 
    // use compositing to "erase" a circle under the mouse 
 
    ctx.globalCompositeOperation='destination-out'; 
 
    ctx.beginPath(); 
 
    ctx.arc(mx,my,50,0,PI2); 
 
    ctx.closePath(); 
 
    ctx.fill(); 
 

 
    // draw the pre-built circle shadow under the mouse 
 
    ctx.globalCompositeOperation='source-over'; 
 
    // Hint: the in-memory canvas can be an image source for 
 
    // your on-screen canvas 
 
    ctx.drawImage(cut,mx-50,my-50); 
 
} 
 

 

 
function handleMouseMove(e){ 
 
    // tell the browser we're handling this event 
 
    e.preventDefault(); 
 
    e.stopPropagation(); 
 

 
    mouseX=parseInt(e.clientX-offsetX); 
 
    mouseY=parseInt(e.clientY-offsetY); 
 

 
    applyCut(mouseX,mouseY); 
 

 
}
body{ background-color: ivory; } 
 
#wrapper{position:relative;} 
 
#bk,#canvas{position:absolute;} 
 
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
 
<h4>Move the mouse to reveal the image underneath</h4> 
 
<div id=wrapper> 
 
    <img id=bk src=https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tiger.png /> 
 
    <canvas id="canvas" width=512 height=512></canvas> 
 
</div>

0

我剛剛創建Inset.js這個確切的情況!

Inset.js

只需要設置ctx.shadowInset = true;

例如:http://codepen.io/patlillis/pen/RpEoKE

var ctx = canvas.getContext("2d"); 
var w = canvas.width = window.innerWidth; 
var h = canvas.height = window.innerHeight; 

// Set up circle styles. 
ctx.shadowInset = true; 
ctx.shadowBlur = 15; 
ctx.shadowColor = 'black'; 
ctx.shadowOffsetX = 5; 
ctx.shadowOffsetY = 5; 
ctx.fillStyle = 'red'; 

// Set up mouse listener. 
document.addEventListener('mousemove', function(e) { 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    ctx.beginPath(); 
    ctx.arc(e.clientX, e.clientY, 30, 0, 2 * Math.PI); 
    ctx.fill(); 
}); 

Inset circle demo