Поиск…


Эффект наклейки с использованием теней

Этот код добавляет внешне увеличивающиеся тени к изображению для создания «стикерной» версии изображения.

Заметки:

  • В дополнение к объекту ImageObject аргумент «img» также может быть элементом Canvas. Это позволяет вам наклеить ваши собственные рисунки. Если вы нарисуете текст в аргументе 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') ... в памяти: var memoryCanvas = document.createElement('canvas') ...

  • Всякий раз, когда вам нужна затененная версия, нарисуйте это предварительно затененное изображение из холста в памяти на видимый холст: 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);
}

Добавить визуальную глубину с тенями

Традиционное использование затенения - дать двумерным рисункам иллюзию 3D-глубины.

В этом примере показана одна и та же кнопка с и без теневого копирования

введите описание изображения здесь

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

Внутренние тени

Canvas не имеет inner-shadow CSS.

  • Холст будет затенять внешность заполненной формы.
  • Холст будет теневать как внутри, так и снаружи поглаженной формы.

Но легко создавать внутренние тени с помощью композитинга.

Штрихи с внутренней тенью

введите описание изображения здесь

Чтобы создать штрихи с внутренней тенью, используйте компоновку destination-in которая заставляет существующий контент оставаться только там, где существующий контент перекрывается новым контентом. Существующий контент, который не перекрывается новым контентом, удаляется.

  1. Обведите форму с тенью. Тень будет расширяться как наружу, так и внутрь от удара. Мы должны избавиться от внешней тени - оставив только желаемую внутреннюю тень.
  2. Установите композицию в destination-in котором сохраняется существующая поглаженная тень только там, где она перекрывается любыми новыми чертежами.
  3. Заполните форму. Это приводит к тому, что инсульт и внутренняя тень остаются во время стирания внешней тени. Ну, не совсем! Так как ход выполнен в полуинтерфейсе, а половина - вне заполненной формы, внешняя половина хода также будет удалена. Исправление состоит в том, чтобы удвоить значение 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();
}

Stroked Fills с внутренней тенью

введите описание изображения здесь

Чтобы создать заливки с внутренней тенью, выполните шаги № 1-3 выше, но еще больше используйте компоновку 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