Buscar..


Efecto adhesivo utilizando sombras.

Este código agrega sombras que aumentan hacia el exterior a una imagen para crear una versión "adhesiva" de la imagen.

Notas:

  • Además de ser un ImageObject, el argumento "img" también puede ser un elemento Canvas. Esto te permite pegar tus propios dibujos personalizados. Si dibuja texto en el argumento del lienzo, también puede pegar ese texto.
  • Las imágenes totalmente opacas no tendrán efecto de etiqueta porque el efecto se dibuja alrededor de grupos de píxeles opacos que están bordeados por píxeles transparentes.

introduzca la descripción de la imagen aquí

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

¿Cómo parar más sombras?

Una vez que se activa el sombreado, cada nuevo dibujo del lienzo se sombreará.

Desactive las sombras adicionales configurando context.shadowColor a un color transparente.

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

... render some shadowed drawings ...

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

El sombreado es computacionalmente costoso: ¡caché esa sombra!

¡Advertencia! Aplicar sombras con moderación!

Aplicar el sombreado es costoso y es muy costoso si aplica el sombreado dentro de un ciclo de animación.

En su lugar, almacene en caché una versión sombreada de su imagen (u otro dibujo):

  • Al inicio de su aplicación, cree una versión sombreada de su imagen en un segundo lienzo solo en memoria: var memoryCanvas = document.createElement('canvas') ...

  • Siempre que necesite la versión sombreada, dibuje esa imagen previamente sombreada desde el lienzo en memoria al lienzo visible: context.drawImage(memoryCanvas,x,y)

introduzca la descripción de la imagen aquí

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

Añade profundidad visual con sombras

El uso tradicional de la sombra es dar a los dibujos bidimensionales la ilusión de la profundidad 3D.

Este ejemplo muestra el mismo "botón" con y sin sombra

introduzca la descripción de la imagen aquí

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

Sombras interiores

Canvas no tiene la inner-shadow de CSS.

  • El lienzo sombreará el exterior de una forma rellena.
  • El lienzo sombreará tanto dentro como fuera de una forma trazada.

Pero es fácil crear sombras internas utilizando la composición.

Trazos con una sombra interior.

introduzca la descripción de la imagen aquí

Para crear trazos con una sombra interior, use la composición de destination-in , lo que hace que el contenido existente permanezca solo donde el contenido existente se superpone al contenido nuevo. El contenido existente que no se superpone con el contenido nuevo se borra.

  1. Trazar una forma con una sombra. La sombra se extenderá tanto hacia afuera como hacia adentro desde el trazo. Debemos deshacernos de la sombra exterior, dejando solo la sombra interior deseada.
  2. Establezca la composición en destination-in que mantiene la sombra trazada existente solo donde se superponga con cualquier dibujo nuevo.
  3. Rellena la forma. Esto hace que el trazo y la sombra interior permanezcan mientras se borra la sombra exterior. ¡Bueno no exactamente! Dado que un trazo es medio dentro y medio fuera de la forma rellena, la mitad exterior del trazo también se borrará. La solución es duplicar el context.lineWidth por lo que la mitad del trazo de doble tamaño aún está dentro de la forma rellena.
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();
}

Trazos rellenos con una sombra interior

introduzca la descripción de la imagen aquí

Para crear rellenos con una sombra interior, siga los pasos 1 a 3 anteriores, pero utilice aún destination-over composición de destination-over , lo que hace que se dibuje nuevo contenido bajo el contenido existente .

  1. Establezca la composición en destination-over que hace que el relleno se dibuje bajo la sombra interna existente.
  2. Desactive el sombreado configurando context.shadowColor a un color transparente.
  3. Rellena la forma con el color deseado. La forma se rellenará debajo de la sombra interior existente.
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();
}

Rellenos sin trazos con una sombra interior

introduzca la descripción de la imagen aquí

Para dibujar una forma rellena con una sombra interior, pero sin trazo, puede dibujar el trazo fuera del lienzo y usar shadowOffsetX para empujar la sombra hacia atrás en el lienzo.

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
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow