Recherche…


Effet d'autocollant en utilisant des ombres

Ce code ajoute des ombres croissantes à une image pour créer une version "autocollant" de l'image.

Remarques:

  • En plus d'être un objet ImageObject, l'argument "img" peut également être un élément Canvas. Cela vous permet de personnaliser vos propres dessins. Si vous dessinez du texte sur l'argument Canvas, vous pouvez également coller ce texte.
  • Les images entièrement opaques n'auront aucun effet d'autocollant car l'effet est dessiné autour de groupes de pixels opaques bordés de pixels transparents.

entrer la description de l'image ici

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

Comment arrêter d'autres ombres

Une fois que l'observation est activée, chaque nouveau dessin sur la toile sera ombré.

Désactivez d'autres masques en définissant context.shadowColor sur une couleur transparente.

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

... render some shadowed drawings ...

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

L'observation est coûteuse en calculs - Cachez cette ombre!

Attention! Appliquez les ombres avec parcimonie!

Appliquer l'observation est coûteux et multiplicativement coûteux si vous appliquez l'observation dans une boucle d'animation.

Au lieu de cela, mettez en cache une version ombrée de votre image (ou un autre dessin):

  • Au début de votre application, créez une version ombrée de votre image dans un deuxième canevas en mémoire uniquement: var memoryCanvas = document.createElement('canvas') ...

  • Chaque fois que vous avez besoin de la version ombrée, dessinez cette image pré-ombrée du canevas en mémoire dans le canevas visible: context.drawImage(memoryCanvas,x,y)

entrer la description de l'image ici

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

Ajouter de la profondeur visuelle avec des ombres

L'utilisation traditionnelle de l'ombrage consiste à donner des dessins bidimensionnels à l'illusion de la profondeur 3D.

Cet exemple montre le même "bouton" avec et sans ombrage

entrer la description de l'image ici

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

Ombres intérieures

Canvas n'a pas d' inner-shadow CSS.

  • La toile va masquer l'extérieur d'une forme remplie.
  • La toile ira à la fois à l'intérieur et à l'extérieur d'une forme caressée.

Mais il est facile de créer des ombres intérieures en utilisant le compositing.

Coups avec une ombre intérieure

entrer la description de l'image ici

Pour créer des traits avec une ombre intérieure, utilisez destination-in compositing qui provoque le contenu existant reste que si le contenu existant est chevauché par un nouveau contenu. Le contenu existant qui n'est pas recouvert par un nouveau contenu est effacé.

  1. Traitez une forme avec une ombre. L'ombre s'étendra à la fois vers l'extérieur et l'intérieur du trait. Nous devons nous débarrasser de l'ombre extérieure en ne laissant que l'ombre intérieure désirée.
  2. Définissez la composition à l’ destination-in de la destination-in conserver l’ombre que si elle est recouverte par de nouveaux dessins.
  3. Remplissez la forme. Cela fait que le trait et l'ombre intérieure restent pendant que l'ombre extérieure est effacée. Eh bien, pas exactement! Comme un trait est à mi-distance et à moitié en dehors de la forme remplie, la moitié extérieure de la course sera également effacée. La solution consiste à doubler le context.lineWidth afin que la moitié du trait double soit toujours dans la forme remplie.
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();
}

Filled Filled avec une ombre intérieure

entrer la description de l'image ici

Pour créer des remplissages avec une ombre interne, suivez les étapes 1 à 3 ci-dessus, mais utilisez davantage destination-over composition par destination-over ce qui entraîne la création de nouveaux contenus sous du contenu existant .

  1. Définissez la composition sur la destination-over ce qui entraîne le remplissage sous le masque interne existant.
  2. Désactivez l'observation en définissant context.shadowColor sur une couleur transparente.
  3. Remplissez la forme avec la couleur souhaitée. La forme sera remplie sous l'ombre interne existante.
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();
}

Remplissage sans traits avec une ombre intérieure

entrer la description de l'image ici

Pour dessiner une forme remplie avec une ombre interne, mais sans le moindre trait, vous pouvez dessiner le trait hors-toile et utiliser shadowOffsetX pour repousser l'ombre sur le canevas.

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow