Ricerca…


Effetto adesivo usando le ombre

Questo codice aggiunge esternamente ombre a un'immagine per creare una versione "adesiva" dell'immagine.

Gli appunti:

  • Oltre ad essere un oggetto ImageObject, l'argomento "img" può anche essere un elemento Canvas. Ciò ti consente di auto-adesivizzare i tuoi disegni personalizzati. Se si disegna un testo sull'argomento Canvas, è anche possibile applicare un adesivo a tale testo.
  • Le immagini completamente opache non avranno effetto adesivo perché l'effetto è disegnato attorno a gruppi di pixel opachi che sono bordati da pixel trasparenti.

inserisci la descrizione dell'immagine qui

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);
}

Come smettere di ombreggiare ulteriormente

Una volta attivato lo shadowing, ogni nuovo disegno sulla tela verrà ombreggiato.

Disattiva ulteriormente l'ombreggiatura impostando context.shadowColor su un colore trasparente.

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

... render some shadowed drawings ...

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

Shadowing è computazionalmente costoso - Cache that shadow!

Avvertimento! Applica le ombre con parsimonia!

Applicare lo shadowing è costoso ed è molto costoso se si applica lo shadowing all'interno di un ciclo di animazione.

Invece, memorizza nella cache una versione ombreggiata della tua immagine (o di un altro disegno):

  • All'inizio della tua app, crea una versione ombreggiata della tua immagine in un secondo Canvas in memoria: var memoryCanvas = document.createElement('canvas') ...

  • Ogni volta che hai bisogno della versione in ombra, disegna l'immagine pre-ombreggiata dalla tela in memoria alla tela visibile: context.drawImage(memoryCanvas,x,y)

inserisci la descrizione dell'immagine qui

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);
}

Aggiungi profondità visiva con le ombre

L'uso tradizionale di shadowing è di dare ai disegni bidimensionali l'illusione della profondità 3D.

Questo esempio mostra lo stesso "pulsante" con e senza ombra

inserisci la descrizione dell'immagine qui

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)';

Ombre interne

Canvas non ha l' inner-shadow del CSS.

  • La tela ombreggia l'esterno di una forma piena.
  • La tela ombreggia sia all'interno che all'esterno di una forma accarezzata.

Ma è facile creare ombre interne usando il compositing.

Colpi con un'ombra interiore

inserisci la descrizione dell'immagine qui

Per creare tratti con un'ombra interiore, utilizzare la composizione di destination-in cui il contenuto esistente rimane solo dove il contenuto esistente viene sovrapposto al nuovo contenuto. I contenuti esistenti che non sono sovrapposti da nuovi contenuti vengono cancellati.

  1. Traccia una forma con un'ombra. L'ombra si estenderà sia verso l'esterno che verso l'interno dal tratto. Dobbiamo sbarazzarci dell'ombra esterna, lasciando solo l'ombra interiore desiderata.
  2. Imposta il compositing alla destination-in cui mantiene l'ombra tratteggiata esistente solo dove è sovrapposta a eventuali nuovi disegni.
  3. Riempi la forma. Questo fa sì che il tratto e l'ombra interiore rimangano mentre l'ombra esterna viene cancellata. Bene, non esattamente! Poiché un tratto è metà dentro e metà all'esterno della forma piena, anche la metà esterna del tratto verrà cancellata. La correzione è raddoppiare il context.lineWidth modo che metà del tratto a doppia dimensione sia ancora all'interno della forma riempita.
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();
}

Riempie riempito con un'ombra interiore

inserisci la descrizione dell'immagine qui

Per creare riempimenti con un'ombra interiore, seguire i passaggi da 1 a 3 sopra, ma utilizzare ulteriormente destination-over compositing di destination-over che consente di disegnare nuovi contenuti sotto il contenuto esistente .

  1. Imposta il compositing su destination-over che fa disegnare il riempimento sotto l'ombra interna esistente.
  2. Disattiva lo shadowing impostando context.shadowColor su un colore trasparente.
  3. Riempi la forma con il colore desiderato. La forma sarà riempita sotto l'ombra interiore esistente.
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();
}

Riempimenti non a tratti con un'ombra interiore

inserisci la descrizione dell'immagine qui

Per disegnare una forma piena con un'ombra interiore, ma senza tratto, puoi disegnare il tratto fuori campo e usare shadowOffsetX per shadowOffsetX l'ombra shadowOffsetX di shadowOffsetX .

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow