Sök…


Klistermärkeeffekt med skuggor

Den här koden lägger ut ökande skuggor till en bild för att skapa en "klistermärke" -version av bilden.

Anmärkningar:

  • Förutom att vara ett ImageObject, kan "img" -argumentet också vara ett Canvas-element. Detta gör att du kan klistra in dina egna egna ritningar. Om du ritar text på Canvas-argumentet kan du också klistra in den texten.
  • Helt ogenomskinliga bilder har ingen klistermärkningseffekt eftersom effekten dras runt kluster av ogenomskinliga pixlar som gränsar till transparenta pixlar.

ange bildbeskrivning här

var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
document.body.appendChild(canvas);
canvas.style.background='navy';
canvas.style.border='1px solid red;';

// Always(!) wait for your images to fully load before trying to drawImage them!
var img=new Image();
img.onload=start;
// put your img.src here...
img.src='http://i.stack.imgur.com/bXaB6.png';
function start(){
    ctx.drawImage(img,20,20);
    var sticker=stickerEffect(img,5);
    ctx.drawImage(sticker, 150,20);
}

function stickerEffect(img,grow){
    var canvas1=document.createElement("canvas");
    var ctx1=canvas1.getContext("2d");
    var canvas2=document.createElement("canvas");
    var ctx2=canvas2.getContext("2d");
    canvas1.width=canvas2.width=img.width+grow*2;
    canvas1.height=canvas2.height=img.height+grow*2;
    ctx1.drawImage(img,grow,grow);
    ctx2.shadowColor='white';
    ctx2.shadowBlur=2;
    for(var i=0;i<grow;i++){
        ctx2.drawImage(canvas1,0,0);
        ctx1.drawImage(canvas2,0,0);
    }
    ctx2.shadowColor='rgba(0,0,0,0)';   
    ctx2.drawImage(img,grow,grow);
    return(canvas2);
}

Hur man stoppar ytterligare skuggning

När skuggan är påslagen skuggas varje ny teckning på duken.

Stäng av ytterligare skuggning genom att ställa context.shadowColor till en transparent färg.

// start shadowing
context.shadowColor='black';

... render some shadowed drawings ...

// turn off shadowing.
context.shadowColor='rgba(0,0,0,0)';

Skuggning är beräkningsvärt dyr - Cache den skuggan!

Varning! Applicera skuggor sparsamt!

Att applicera skugga är dyrt och multiplikativt dyrt om du applicerar skuggning i en animeringsslinga.

Cache i stället en skuggad version av din bild (eller annan ritning):

  • I början av din app, skapa en skuggad version av din bild i en andra in-minne-Canvas: var memoryCanvas = document.createElement('canvas') ...

  • När du behöver den skuggade versionen, rita den förskuggade bilden från minnesduken till den synliga duken: context.drawImage(memoryCanvas,x,y)

ange bildbeskrivning här

var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
canvas.style.border='1px solid red;';
document.body.appendChild(canvas);

// Always(!) use "img.onload" to give your image time to 
//     fully load before you try drawing it to the Canvas!
var img=new Image();
img.onload=start;
// Put your own img.src here
img.src="http://i.stack.imgur.com/hYFNe.png";
function start(){
    ctx.drawImage(img,0,20);
    var cached=cacheShadowedImage(img,'black',5,3,3);
    for(var i=0;i<5;i++){ 
        ctx.drawImage(cached,i*(img.width+10),80);
    }
}

function cacheShadowedImage(img,shadowcolor,blur){
    var c=document.createElement('canvas');
    var cctx=c.getContext('2d');
    c.width=img.width+blur*2+2;
    c.height=img.height+blur*2+2;
    cctx.shadowColor=shadowcolor;
    cctx.shadowBlur=blur;
    cctx.drawImage(img,blur+1,blur+1);
    return(c);
}

Lägg till visuellt djup med skuggor

Den traditionella användningen av skuggning är att ge tvådimensionella ritningar en illusion av 3D-djup.

Detta exempel visar samma "knapp" med och utan skuggning

ange bildbeskrivning här

var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
document.body.appendChild(canvas);

ctx.fillStyle='skyblue';
ctx.strokeStyle='lightgray';
ctx.lineWidth=5;

// without shadow
ctx.beginPath();
ctx.arc(60,60,30,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.stroke();

// with shadow
ctx.shadowColor='black';
ctx.shadowBlur=4;
ctx.shadowOffsetY=3;
ctx.beginPath();
ctx.arc(175,60,30,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.stroke();
// stop the shadowing
ctx.shadowColor='rgba(0,0,0,0)';

Inre skuggor

Canvas har inte CSS inner-shadow .

  • Canvas skuggar utsidan av en fylld form.
  • Canvas skuggar både inuti och utanför en streckad form.

Men det är lätt att skapa inre skuggor med kompositionering.

Slag med en inre skugga

ange bildbeskrivning här

För att skapa strofer med en inre skugga, använd destination-in komposition som gör att befintligt innehåll bara förblir där befintligt innehåll överlappas av nytt innehåll. Befintligt innehåll som inte överlappas av nytt innehåll raderas.

  1. Stryk en form med en skugga. Skuggan kommer att sträcka sig både utåt och inåt från stroke. Vi måste bli av med den yttre skuggan - och bara lämna den önskade inre skuggan.
  2. Ställ kompositionen till destination-in som håller den befintliga streckade skuggan endast där den överlappas av nya ritningar.
  3. Fyll formen. Detta gör att stroke och inner-skugga kvarstår medan den yttre skuggan raderas. Tja, inte exakt! Eftersom ett slag är halvt inuti och halvt utanför den fyllda formen, kommer den yttre halvan av stroke att raderas. Fixet är att fördubbla context.lineWidth så att hälften av den dubbla storleken fortfarande finns i den fyllda formen.
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
document.body.appendChild(canvas);

// draw an opaque shape -- here we use a rounded rectangle
defineRoundedRect(30,30,100,75,10);

// set shadowing
ctx.shadowColor='black';
ctx.shadowBlur=10;

// stroke the shadowed rounded rectangle
ctx.lineWidth=4;
ctx.stroke();

// set compositing to erase everything outside the stroke
ctx.globalCompositeOperation='destination-in';
ctx.fill();

// always clean up -- set compsiting back to default
ctx.globalCompositeOperation='source-over';   


function defineRoundedRect(x,y,width,height,radius) {
    ctx.beginPath();
    ctx.moveTo(x + radius, y);
    ctx.lineTo(x + width - radius, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
    ctx.lineTo(x + width, y + height - radius);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    ctx.lineTo(x + radius, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
    ctx.lineTo(x, y + radius);
    ctx.quadraticCurveTo(x, y, x + radius, y);
    ctx.closePath();
}

Stroked Fills med en inre skugga

ange bildbeskrivning här

För att skapa fyllningar med en inre skugga, följ steg 1-3 ovan, men använd vidare destination-over kompositionering som gör att nytt innehåll dras under befintligt innehåll .

  1. Ställ kompositionen till destination-over som gör att fyllningen dras under den befintliga inre skuggan.
  2. Stäng av skuggning genom att ställa context.shadowColor till en transparent färg.
  3. Fyll formen med önskad färg. Formen kommer att fyllas under den befintliga inre skuggan.
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
document.body.appendChild(canvas);

// draw an opaque shape -- here we use a rounded rectangle
defineRoundedRect(30,30,100,75,10);

// set shadowing
ctx.shadowColor='black';
ctx.shadowBlur=10;

// stroke the shadowed rounded rectangle
ctx.lineWidth=4;
ctx.stroke();

// stop shadowing
ctx.shadowColor='rgba(0,0,0,0)';

// set compositing to erase everything outside the stroke
ctx.globalCompositeOperation='destination-in';
ctx.fill();

// set compositing to erase everything outside the stroke
ctx.globalCompositeOperation='destination-over';
ctx.fillStyle='gold';
ctx.fill();

// always clean up -- set compsiting back to default
ctx.globalCompositeOperation='source-over';   

function defineRoundedRect(x,y,width,height,radius) {
    ctx.beginPath();
    ctx.moveTo(x + radius, y);
    ctx.lineTo(x + width - radius, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
    ctx.lineTo(x + width, y + height - radius);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    ctx.lineTo(x + radius, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
    ctx.lineTo(x, y + radius);
    ctx.quadraticCurveTo(x, y, x + radius, y);
    ctx.closePath();
}

Icke-strökad fyllning med en inre skugga

ange bildbeskrivning här

För att rita en fylld form med en inre skugga, men utan stroke, kan du rita linjen utanför duken och använda shadowOffsetX att skjuta tillbaka skuggan på duken.

var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
document.body.appendChild(canvas);

// define an opaque shape -- here we use a rounded rectangle
defineRoundedRect(30-500,30,100,75,10);

// set shadowing
ctx.shadowColor='black';
ctx.shadowBlur=10;
ctx.shadowOffsetX=500;

// stroke the shadowed rounded rectangle
ctx.lineWidth=4;
ctx.stroke();

// stop shadowing
ctx.shadowColor='rgba(0,0,0,0)';

// redefine an opaque shape -- here we use a rounded rectangle
defineRoundedRect(30,30,100,75,10);

// set compositing to erase everything outside the stroke
ctx.globalCompositeOperation='destination-in';
ctx.fill();

// set compositing to erase everything outside the stroke
ctx.globalCompositeOperation='destination-over';
ctx.fillStyle='gold';
ctx.fill();

// always clean up -- set compsiting back to default
ctx.globalCompositeOperation='source-over';   

function defineRoundedRect(x,y,width,height,radius) {
    ctx.beginPath();
    ctx.moveTo(x + radius, y);
    ctx.lineTo(x + width - radius, y);
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
    ctx.lineTo(x + width, y + height - radius);
    ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
    ctx.lineTo(x + radius, y + height);
    ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
    ctx.lineTo(x, y + radius);
    ctx.quadraticCurveTo(x, y, x + radius, y);
    ctx.closePath();
}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow