수색…


그림자를 사용한 스티커 효과

이 코드는 이미지에 외곽으로 그림자를 추가하여 이미지의 "스티커"버전을 만듭니다.

노트:

  • ImageObject가되는 것 외에도 "img"인수는 Canvas 요소가 될 수도 있습니다. 이렇게하면 사용자 정의 도면을 스티커로 표시 할 수 있습니다. 캔버스 인수에 텍스트를 그릴 경우 해당 텍스트에 스티커를 지정할 수도 있습니다.
  • 완전 불투명 이미지는 투명 픽셀로 경계가있는 불투명 픽셀 클러스터 주위에 효과가 나타나기 때문에 스티커 효과가 없습니다.

여기에 이미지 설명을 입력하십시오.

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

추가 섀도 잉을 중지하는 방법

섀도 잉이 켜지면 캔버스에 대한 모든 새 드로잉이 음영 처리됩니다.

context.shadowColor 를 투명한 색으로 설정하여 추가 섀도 잉을 비활성화하십시오.

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

... render some shadowed drawings ...

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

음영 처리는 계산 상 비쌉니다. - 그 음영을 캐시하십시오!

경고! 그림자를 살짝 적용하십시오!

섀도 잉을 적용하는 것은 비용이 많이 들고 애니메이션 루프 내부에서 섀도 잉을 적용 할 경우 배가된다.

대신 이미지 (또는 다른 그림)의 그림자 버전을 캐시하십시오.

  • 앱을 시작할 때 두 번째 메모리 내 캔버스에서 이미지의 섀도우 버전을 만듭니다. var memoryCanvas = document.createElement('canvas') ...

  • 그림자 버전이 필요할 때마다 메모리 내 캔버스의 미리 음영 처리 된 이미지를 보이는 캔버스로 그 context.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);
}

그림자가있는 시각적 깊이 추가

전통적인 그림자 사용은 2 차원 도면에 3 차원 깊이의 환상을 부여하는 것입니다.

이 예제는 그림자가있는 것과없는 동일한 "버튼"을 보여줍니다.

여기에 이미지 설명을 입력하십시오.

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

내부 그림자

캔버스에는 CSS의 inner-shadow 가 없습니다.

  • 캔버스는 채워진 모양의 바깥 쪽을 가리 킵니다.
  • 캔버스는 안쪽과 바깥 쪽 모두에 그림자가 생깁니다.

그러나 합성을 사용하여 내부 그림자를 만드는 것은 쉽습니다.

안쪽 그림자가있는 스트로크

여기에 이미지 설명을 입력하십시오.

내부 그림자가있는 스트로크를 만들려면 기존 콘텐츠가 새 콘텐츠로 기존 콘텐츠가 겹쳐진 부분 만 유지하도록하는 destination-in 합성을 사용하십시오. 새로운 콘텐츠와 중복되지 않는 기존 콘텐츠는 지워집니다.

  1. 그림자가있는 도형을 칠하십시오. 그림자는 스트로크에서 바깥 쪽과 안쪽으로 확장됩니다. 우리는 바깥 쪽 그림자를 제거해야합니다. 원하는 안쪽 그림자 만 남겨 두어야합니다.
  2. 새로운 획에 의해 겹쳐지는 곳에서만 기존의 선이 그어진 그림자를 유지하는 합성을 destination-in 설정 합니다.
  3. 모양을 채 웁니다. 이로 인해 외부 그림자가 지워지는 동안 스트로크와 내부 그림자가 남아있게됩니다. 음, 정확히는 아닙니다! 스트로크는 채워진 모양의 반쪽과 바깥 쪽이므로 스트로크의 바깥 쪽 절반도 지워집니다. double 크기의 획의 절반이 여전히 채워진 모양 안에 있도록 context.lineWidth 를 두 배로 수정해야합니다.
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();
}

내부 그림자로 채워진 채우기

여기에 이미지 설명을 입력하십시오.

내부 그림자로 채우기를 만들려면 위의 1-3 단계를 따르고 기존 콘텐츠에서 새 콘텐츠를 가져 오는 destination-over 합성을 사용 destination-over .

  1. 채우기가 기존의 내부 그림자 아래 에 그려지는 destination-over 합성을 설정 합니다.
  2. context.shadowColor 를 투명한 색으로 설정 하여 섀도 잉해제하십시오 .
  3. 원하는 색상으로 도형 을 채 웁니다. 모양은 기존의 내부 그림자 아래에 채워질 것입니다.
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();
}

안쪽 그림자가있는 비 스트로크 채우기

여기에 이미지 설명을 입력하십시오.

채워진 모양을 내부 그림자로 그리지 만 획이없는 경우 그리기 취소 선을 그릴 수 있으며 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
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow