Поиск…
Эффект наклейки с использованием теней
Этот код добавляет внешне увеличивающиеся тени к изображению для создания «стикерной» версии изображения.
Заметки:
- В дополнение к объекту 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
которая заставляет существующий контент оставаться только там, где существующий контент перекрывается новым контентом. Существующий контент, который не перекрывается новым контентом, удаляется.
- Обведите форму с тенью. Тень будет расширяться как наружу, так и внутрь от удара. Мы должны избавиться от внешней тени - оставив только желаемую внутреннюю тень.
- Установите композицию в
destination-in
котором сохраняется существующая поглаженная тень только там, где она перекрывается любыми новыми чертежами. - Заполните форму. Это приводит к тому, что инсульт и внутренняя тень остаются во время стирания внешней тени. Ну, не совсем! Так как ход выполнен в полуинтерфейсе, а половина - вне заполненной формы, внешняя половина хода также будет удалена. Исправление состоит в том, чтобы удвоить значение
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
которая заставляет новый контент рисоваться в существующем контенте .
- Установите композицию в
destination-over
чего заливка будет нарисована под существующей внутренней теневой. - Отключите затенение , установив
context.shadowColor
в прозрачный цвет. - Заполните форму желаемым цветом. Форма будет заполнена под существующей внутренней тенью.
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();
}