Suche…
Sticker-Effekt mit Schatten
Dieser Code fügt einem Bild nach außen zunehmende Schatten hinzu, um eine "Sticker" -Version des Bildes zu erstellen.
Anmerkungen:
- Das Argument "img" kann nicht nur ein ImageObject sein, sondern auch ein Canvas-Element. Auf diese Weise können Sie Ihre eigenen benutzerdefinierten Zeichnungen ankleben. Wenn Sie Text in das Canvas-Argument zeichnen, können Sie diesen Text auch ankleben.
- Für vollständig undurchsichtige Bilder wird kein Aufklebereffekt angezeigt, da der Effekt um Cluster von undurchsichtigen Pixeln gezeichnet wird, die von transparenten Pixeln umgeben sind.
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);
}
So stoppen Sie das weitere Shadowing
Sobald die Spiegelung aktiviert ist, wird jede neue Zeichnung der Leinwand gespiegelt.
Deaktivieren Sie weitere context.shadowColor
, indem Sie context.shadowColor
auf eine transparente Farbe setzen.
// start shadowing
context.shadowColor='black';
... render some shadowed drawings ...
// turn off shadowing.
context.shadowColor='rgba(0,0,0,0)';
Shadowing ist rechenintensiv - Cache zwischenspeichern!
Warnung! Schatten sparsam anwenden!
Das Anwenden von Schatten ist teuer und multipliziert, wenn Sie Schatten innerhalb einer Animationsschleife anwenden.
Zwischenspeichern Sie stattdessen eine gespiegelte Version Ihres Bildes (oder einer anderen Zeichnung):
Erstellen Sie zu Beginn Ihrer App eine gespiegelte Version Ihres Bildes in einem zweiten Canvas im Nur-Canvas-Bereich:
var memoryCanvas = document.createElement('canvas') ...
Wann immer Sie die schattierte Version benötigen, zeichnen Sie das vorabschattierte Bild von der In-Memory-
context.drawImage(memoryCanvas,x,y)
zur sichtbarencontext.drawImage(memoryCanvas,x,y)
:context.drawImage(memoryCanvas,x,y)
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);
}
Fügen Sie visuelle Tiefe mit Schatten hinzu
Die traditionelle Verwendung von Schattierungen besteht darin, zweidimensionalen Zeichnungen die Illusion von 3D-Tiefe zu geben.
Dieses Beispiel zeigt den gleichen "Button" mit und ohne Spiegelung
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)';
Innere Schatten
Canvas hat keinen inner-shadow
CSS.
- Canvas beschattet die Außenseite einer ausgefüllten Form.
- Canvas beschattet sowohl innerhalb als auch außerhalb einer gestrichenen Form.
Mit Compositing lassen sich jedoch leicht Innenschatten erstellen.
Striche mit einem inneren Schatten
Um Striche mit einem inneren Schatten zu erstellen, verwenden Sie das Composite- destination-in
, wodurch vorhandene Inhalte nur dort verbleiben, wo vorhandene Inhalte von neuem Inhalt überlappt werden. Bestehender Inhalt, der sich nicht mit neuem Inhalt überschneidet, wird gelöscht.
- Streichen Sie eine Form mit einem Schatten. Der Schatten erstreckt sich sowohl nach außen als auch nach innen vom Strich. Wir müssen den äußeren Schatten loswerden - nur den gewünschten inneren Schatten lassen.
- Setzen Sie Compositing auf
destination-in
wodurch der vorhandene Schatten nur dort verbleibt, wo neue Zeichnungen ihn überlappen. - Fülle die Form aus. Dadurch bleiben der Strich und der innere Schatten erhalten, während der äußere Schatten gelöscht wird. Nun, nicht genau! Da sich ein Strich zur Hälfte innerhalb und zur Hälfte außerhalb der gefüllten Form befindet, wird auch die äußere Hälfte des Strichs gelöscht. Das
context.lineWidth
besteht darin,context.lineWidth
zu verdoppeln, sodass sich die Hälfte des doppelten Strichs immer noch in der gefüllten Form befindet.
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();
}
Schlaganfall füllt sich mit einem inneren Schatten
Um Füllungen mit einem inneren Schatten zu erstellen, folgen Sie die Schritte # 1-3 oben , aber die weitere Verwendung destination-over
- Compositing , die neuen Inhalte verursacht im Rahmen der bestehenden Inhalte gezogen werden.
- Setzen Sie Compositing auf
destination-over
, wodurch die Füllung unter dem vorhandenen inneren Schatten gezeichnet wird. - Deaktivieren Sie die
context.shadowColor
, indem Siecontext.shadowColor
auf eine transparente Farbe setzen. - Füllen Sie die Form mit der gewünschten Farbe. Die Form wird unter dem vorhandenen inneren Schatten gefüllt.
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();
}
Non-stroked Fills mit einem inneren Schatten
Um eine gefüllte Form mit einem inneren Schatten, aber ohne Strich zu zeichnen, können Sie den Strich außerhalb der Leinwand zeichnen und mit shadowOffsetX
den Schatten wieder auf die Leinwand drücken.
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();
}