白癜风治疗 http://m.39.net/pf/bdfyy/
经过这些实验,最终我和老朋友查尔斯·普理查德(CharlesPritchard)开始着手创建Mugtug。我们通过HTML5canvas创建了
Darkroom
。Darkroom是一款无损照片分享应用,将基于像素的过滤器的强大功能与基于矢量的排版和绘图结合在一起。
简介
canvas可让JavaScript编程人员完全地控制屏幕上的颜色、矢量和像素,也就是显示器的视觉效果。
以下示例涉及的是canvas经常被忽视的一个方面,也就是创建文字效果。
这些演示仅仅是一部分,能在canvas中创建多少文字效果,完全取决于您的想象力。虽然我们在本文中讨论的是“文字”,但是您可以将这些方法应用于任何矢量对象,从而在游戏和其他应用中创建炫目的视觉效果:
canvas中的文字阴影。 canvas中类似CSS的文字效果可用于创建剪辑蒙板、查找canvas中的度量以及使用阴影属性。 彩虹式霓虹灯、斑马线反射连锁效果。 canvas中类似于Photoshop的文字效果示例,使用了globalCompositeOperation、createLinearGradient、createPattern。 canvas中的内部和外部阴影 透露一个鲜为人知的功能:使用顺时针而不是逆时针方向绕圈,即可创建反转的投射阴影(即内部阴影)。 航天时代:生成效果 canvas中基于生成的文字效果,使用hsl()color-cycling和window.requestAnimationFrame产生运动的感觉。
画布中的文字阴影
CSS规范中我最喜欢的新增功能之一(其他还包括边框圆角、网络梯度等)就是创建阴影的功能。CSS阴影与canvas阴影是有差别的,很有必要区分开来,具体而言:CSS对框元素(例如div、span等)使用框阴影,而对文字内容使用文字阴影。
而canvas对ctx.moveTo、ctx.lineTo、ctx.bezierCurveTo、ctx.quadradicCurveTo、ctx.arc、ctx.rect、ctx.fillText、ctx.strokeText等所有矢量对象均使用同一类型的阴影。要在canvas中创建阴影,可利用以下四个属性:
ctx.shadowColor=“red”//string 阴影的颜色,有效输入包括RGB、RGBA、HSL、HEX等。 ctx.shadowOffsetX=0;//integer 阴影相对于文字的水平距离。 ctx.shadowOffsetY=0;//integer 阴影相对于文字的垂直距离。 ctx.shadowBlur=10;//integer 阴影的模糊效果,值越大越模糊。
我们先来了解下,canvas是如何模拟CSS效果的。在Google图片中搜索“css文字阴影”可以找到一些很好的演示供我们进行模拟,例如
Line5
、
立体效果
和
阴影D
。
以立体D效果(有关详情,请参见
立体图片
)为例,就是通过一行简单的代码实现了很棒的应用。通过下面的一行CSS代码,我们可以创建一种视觉效果,只要透过D红/蓝眼镜(看D电影时用的那种)就能看出景深。
text-shadow:-0.06em00red,0.06em00cyan;
在将该字符串转换为canvas时,需要注意两点:(1)不存在阴影模糊(第三个值),因此没有必要实际使用阴影,fillText将会得到同样的结果:
vartext=“Helloworld!”ctx.fillStyle=“#”ctx.fillText(text,-7,0);ctx.fillStyle=“red”ctx.fillText(text,0,0);ctx.fillStyle=“cyan”ctx.fillText(text,7,0);
()canvas不支持EM,因此必须将其转换为PX。通过在DOM中使用相同字体属性创建元素,并将宽度设置为待衡量的格式,我们可以得出PT、PC、EM、EX、PX等之间的转换率;例如,要捕获EM-PX转换,我们可以通过“height:1em”来衡量DOM元素,所得的offsetHeight就是相对于各EM的PX值。
varfont=“0pxsans-serif”vard=document.createElement(”span”);d.style.cssText=“font:“+font+“height:1em;display:block”//thevaluetomultiplyPX’sbytoconverttoEM’svarEMPX=1/d.offsetHeight;
禁止alpha倍增
在更为复杂的示例中(例如Line5中的霓虹灯效果),必须使用shadowBlur属性来正确地模拟效果。由于霓虹灯效果依赖于多个阴影,而在canvas中,每个矢量对象只能有一个阴影,这就带来了问题。因此,为了绘制多个阴影,您必须在文字的上层绘制多个版本的文字。这就导致了alpha倍增,并最终导致边缘锯齿化。
我曾试过运行
ctx.fillStyle=“rgba(0,0,0,0)”
或
“transparent”
,以便在显示阴影的同时隐藏文字,但是这样的尝试失败了;由于阴影是fillStylealpha倍增,因此阴影永远不可能比fillStyle更加不透明。幸运的是,我们可以通过以下方法解决这一问题:绘制文本的阴影偏移,使文本分离(这样就不会重叠在一起),从而将文本隐藏在屏幕之外:
vartext=“Helloworld!”varblur=10;varwidth=ctx.measureText(text).width+blur*;ctx.textBaseline=“top”ctx.shadowColor=“#”ctx.shadowOffsetX=width;ctx.shadowOffsetY=0;ctx.shadowBlur=blur;ctx.fillText(text,-width,0);
围绕文本块剪切
要清理干净一些,我们可以在一开始就添加剪辑路径,以禁止绘制fillText(同时允许绘制阴影)。要创建围绕文本的剪辑路径,我们需要知道文本的高度(以前称为“em-高度”,指印刷机上的字母“M”高度)和宽度。我们可以使用
ctx.measureText().width
获取宽度,但是不存在
ctx.measureText().height
。幸运的是,利用CSShack-ardry(请参见
排版度量
,了解使用CSS测量修正旧canvas实施的更多方法),我们可以通过测量带有相同字体属性的span的
offsetHeight
,得出文本的高度:
vard=document.createElement(”span”);d.font=“0pxarial”d.textContent=“Helloworld!”varemHeight=d.offsetHeight;
由此,我们可以创建一个用作剪辑路径的矩形,在删除虚拟形状的同时封闭“阴影”。
ctx.rect(0,0,width,emHeight);ctx.clip();
尝试所有这些方法并不断优化,如果阴影没有模糊效果,可使用fillText达到同样的效果,而无需设置剪辑蒙板:
varwidth=ctx.measureText(text).width;varstyle=shadowStyles[text];//addabackgroundtothecurrenteffectctx.fillStyle=style.background;ctx.fillRect(0,offsetY,ctx.canvas.width,textHeight-1)//parsetext-shadowsfromcssvarshadows=parseShadow(style.shadow);//loopthroughtheshadowcollectionvarn=shadows.length;while(n--){varshadow=shadows[n];vartotalWidth=width+shadow.blur*;ctx.save();ctx.beginPath();ctx.rect(offsetX-shadow.blur,offsetY,offsetX+totalWidth,textHeight);ctx.clip();if(shadow.blur){//justrunshadow(cliptext)ctx.shadowColor=shadow.color;ctx.shadowOffsetX=shadow.x+totalWidth;ctx.shadowOffsetY=shadow.y;ctx.shadowBlur=shadow.blur;ctx.fillText(text,-totalWidth+offsetX,offsetY+metrics.top);}else{//justrunpseudo-shadowctx.fillStyle=shadow.color;ctx.fillText(text,offsetX+(shadow.x
0),offsetY-(shadow.y
0)+metrics.top);}ctx.restore();}//drawingthetextintheforegroundif(style.color){ctx.fillStyle=style.color;ctx.fillText(text,offsetX,offsetY+metrics.top);}//jumptonextem-linectx.translate(0,textHeight);
您想必也不愿意手动输入这么多canvas命令,因此我在演示来源中加入了一个简单的文字阴影解析器;这样您可以直接向该解析器馈入CSS命令,让其生成canvas命令。现在,我们的canvas元素拥有了所有能够拥有的样式。这些相同的阴影效果可用于任何矢量对象,包括WebFonts、从SVG导入的复杂形状、生成矢量形状等等!
查看canvas中的文字阴影效果
。
暂停(像素推送上的切线)
我在写到本文的这一部分时,对立体效果示例感到非常好奇。要使用canvas和两张从略微不同角度所拍摄的图片做出D电影屏幕般的效果,会很难吗?显然,没有那么难。下面的核心部分将第一张图片(data)的红色通道与第二张图片(data)的蓝色通道组合在一起:
data[i]=data[i]*55/0xFF;data[i+1]=55*data[i+1]/0xFF;data[i+]=55*data[i+]/0xFF;
请访问
立体效果演示
,了解如何创建可通过D眼镜(红/蓝)增强观看效果的图片。现在,只要用胶带把两台iPhone粘在脑门上,然后同时点击“录制视频”,就能利用HTML5制作自己的D电影啦!有人自愿试试吗?
彩虹式霓虹灯、斑马线反射连锁效果
在canvas中连锁多种效果是很简单的,但是必须掌握globalCompositeOperation(GCO)的基本知识。这些操作与GIMP(或Photoshop)的对比:canvas中有1种GCO,其中包括darker和lighter(可视为图层混合模式);另外10种操作应用于作为alpha蒙板(一个图层删除另一个图层的像素)的图层。
globalCompositeOperation将“图层”(在本例中为代码字符串)联系在一起,以新颖有趣的方式将它们组合起来:
globalCompositeOperation图表
显示了实际使用中的GCO模式;此图表中使用了很大一部分的多色谱和多层阿尔法透明处理,以便展示出预期的细节。我建议您查看Mozilla的globalCompositeOperation参考,以获取文字说明。要做进一步的研究,您可以了解如何在波特·达夫(PorterDuff)的
复合数字图片
中运用此操作。
我最喜欢的模式是globalCompositeOperation=”lighter”。Lighter以类似于光线混合的方式来混合附加像素;当红光、绿光和白光都处于最高亮度时,我们看到的是白光。这是一项很令人兴奋的功能,尤其是在将canvas设为低globalAlpha的情况下;可以实现更精细的控制,并获得更平滑的边缘。lighter有很多用途,我最近喜欢用的是