这篇文章发布于 2018年02月27日,星期二,23:22,归类于 Canvas相关, CSS相关, SVG相关。 阅读 36348 次, 今日 7 次 20 条评论
by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=7395
本文可全文转载,但需得到原作者书面许可,同时保留原作者和出处,摘要引流则随意。
本文这里所说的叠加,就是混合模式中的叠加,也就是说,本文要实现的效果是,文字本身的颜色和纹理进行叠加,而非直接填充纹理。
CSS, SVG和canvas都能实现类似的效果,我们一个一个来看一下。
一、CSS/CSS3实现文本纹理叠加
HTML和CSS代码如下:
<h2 class="pattern-overlay"> <span data-text="CSS纹理叠加"></span> CSS纹理叠加 </h2>
.pattern-overlay { font-size: 60px; font-family: 'microsoft yahei'; background-image: url(./pattern01.jpg); -webkit-text-fill-color: transparent; -webkit-background-clip: text; } .pattern-overlay > span { position: absolute; background-image: linear-gradient(to bottom, #f00, #f00); mix-blend-mode: overlay; -webkit-text-fill-color: transparent; -webkit-background-clip: text; } .pattern-overlay > span::before { content: attr(data-text); }
就可以实现类似下图的效果(红色渐变和灰色石质纹理叠加效果):
您可以狠狠的点击这里:CSS实现文本的纹理叠加效果demo
在demo页面中,我们可以调整渐变图片的起止颜色,或者更换我们的纹理图片,都有实时的渲染效果:
实现原理
而在webkit浏览器下,可以通过下面CSS组合实现文本以背景显示效果:
.fill-bg { -webkit-text-fill-color: transparent; -webkit-background-clip: text; }
于是,我们使用两层标签,分明填充渐变背景和纹理背景,然后再使用CSS3混合模式mix-blend-mode:overly
对两层标签进行叠加,效果即达成!
兼容性
webkit内核浏览器,Chrome,Safari等都支持。
关于为何不使用background-blend-mode说明
理论上,使用background-blend-mode
最多背景图片进行模式混合是最简单的,因为只需要一层表现,理论支持代码如下:
<h2 class="pattern-overlay">CSS纹理叠加</h2>
.pattern-overlay { font-size: 60px; font-family: 'microsoft yahei'; background-image: linear-gradient(to bottom, #f00, #f00), url(./pattern01.jpg); background-blend-mode: overlay; -webkit-text-fill-color: transparent; -webkit-background-clip: text; }
背景渐变和纹理叠加本身是没有任何问题的,效果如下截图:
但是当应用background-clip:text
声明的时候,混合模式被忽略,于是最终的文本并没有叠加效果。因此才采用两层独立的标签应用mix-blend-mode
来叠加的方法。
//zxx: CSS3对混合模式天然支持,可以参见这篇文章:“CSS3混合模式mix-blend-mode/background-blend-mode简介”,其中mix-blend-mode
是元素间的混合,background-blend-mode
是背景图片之间的混合。
二、使用SVG实现更加兼容的文本纹理叠加效果
CSS3的方法最容易理解上手最快,但是Firefox和IE浏览器都不支持,所以只能在移动端使用,如果我们想兼容PC浏览器,可以试试使用SVG来实现,代码如下:
<svg width="360" height="120"> <defs> <filter id="blend"> <feImage xlink:href="./pattern01.jpg" result="patternSource" x="0" y="0" width="360" height="120" /> <feBlend mode="overlay" in="SourceGraphic" in2="patternSource" /> </filter> <linearGradient id="gradient" x1="0" y1="0" x2="0" y2="1"> <stop offset="0%" stop-color="green" /> <stop offset="100%" stop-color="red" /> </linearGradient> <pattern id="pattern" width="360" height="120" patternUnits="userSpaceOnUse"> <rect x="0" y="0" width="100%" height="100%" fill="url(#gradient)" filter="url(#blend)"></rect> </pattern> </defs> <text x="0" y="60" font-family="Microsoft Yahei" font-size="60" font-weight="900" fill="url(#pattern)"> SVG纹理叠加 </text> </svg>
红绿渐变叠加石头质感纹理,最终实现的效果如下截图:
您可以狠狠地点击这里:SVG实现文本的纹理叠加效果demo
实现原理
SVG中有个和混合模式相关的滤镜元素名为<feBlend>
,所以我们可以定义一个<filter>
,让引用该<filter>
的图形(in="SourceGraphic"
)和<feImage>
这个图片(in2="patternSource"
)进行overlay
混合(mode="overlay"
)。
SVG中文本除了可以填充颜色外,还可以填充纹理,元素是<pattern>
,所以,我们需要一个渐变和纹理素材混合的<pattern>
元素,很简单,一个和SVG尺寸一样的矩形<rect>
元素,使用渐变填充,应用叠加滤镜,作为<pattern>
纹理。
于是,效果达成!
兼容性
Chrome, Safari, Firefox浏览器都支持。
如果在IE浏览器下访问我们的demo页面,会看到纹理并没有叠加,那是因为,IE浏览器下的<feBlend>
只支持规范中提到的几种混合模式,包括:normal
,multiply
,screen
,darken
,lighten
。并没有叠加overlay
。
因此,如果你希望SVG纹理叠加效果IE9+全兼容,可以试试使用正片叠加混合模式-multiply
,对于大部分用户而言,是看不出什么差异的。
三、使用canvas实现纹理叠加效果
canvas并没有现成的混合模式api,因此,如果要想实现叠加效果,需要通过算法重新计算方法。关于混合模式的各种算法,实际上都是公开的,搜一搜就能找到。
在本文中,canvas的混合模式效果使用了一个开源的JS方法,项目地址是:https://github.com/Phrogz/context-blender
JS未压缩状态也就9K不到,各种曾经的混合模式都支持。
于是,要使用canvas实现纹理叠加效果那就容易多了。
下面是实现的效果截图:
您可以狠狠地点击这里:canvas实现文本的纹理叠加效果demo
同样的,我们可以修改渐变颜色,修改纹理图片看到其他渲染效果,例如,我们选择本地一张纸张图片作为纹理:
实现原理
绘制JS代码如下:
// 先引入context_blender.js,然后…… // canvas绘制脚本 var canvas = document.querySelector('canvas'); var context = canvas.getContext('2d'); var width = canvas.width, height = canvas.height; context.textBaseline = 'middle'; context.font = 'bold 60px "Microsoft Yahei"'; // 绘制方法 var draw = function () { context.clearRect(0, 0, width, height); // 渐变和纹理 var gradient, pattern; // 创建材质canvas var canvasPattern = document.createElement('canvas'); var contextUnder = canvasPattern.getContext('2d'); canvasPattern.width = width; canvasPattern.height = height; // 创建渐变canvas var canvasGradient = document.createElement('canvas'); var contextOver = canvasGradient.getContext('2d'); canvasGradient.width = width; canvasGradient.height = height; // 绘制渐变对象 gradient = contextOver.createLinearGradient(0, 0, 0, height); gradient.addColorStop(0, red); gradient.addColorStop(1, red); // 纹理对象,img指纹理图片对象 pattern = contextUnder.createPattern(img, 'no-repeat'); contextUnder.fillStyle = pattern; contextUnder.fillRect(0, 0, width, height); // 应用渐变 contextOver.fillStyle = gradient; contextOver.fillRect(0, 0, width, height); // 叠加canvas contextOver.blendOnto(contextUnder, 'overlay'); // 给当前context创建pattern pattern = context.createPattern(canvasPattern, 'no-repeat'); // 绘制文本 context.fillStyle = pattern; context.fillText('画布纹理叠加', 0, 60); };
原理描述:
临时创建一个canvas绘制一个渐变,临时创建一个canvas使用纹理图片填充,两个canvas叠加混合得到新的canvas,然后页面上那个canvas上的文字就把这个叠加混合后canvas作为纹理进行填充,效果即达成。
兼容性
IE9+,Chrome, Safari, Firefox浏览器都支持。
四、结束语
本文所有案例,无论是CSS3,SVG还是canvas实现都是以叠加混合模式overlay
示意的。其他各种混合模式也都可以轻松支持,只要修改overlay
为其他关键字即可,就不一一举例了。
一点抛砖引玉,以上就是自己根据一些经验摸索出来的方法,实际上应该有更好的方法实现纹理叠加效果,欢迎不吝赐教。
感谢您花宝贵的时间阅读到这里!
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:http://www.zhangxinxu.com/wordpress/?p=7395
(本篇完)
- SVG滤镜系列之搞懂<feBlend>元素 (0.429)
- -webkit-box-reflect属性简介及元素镜像倒影实现 (0.213)
- 深入理解SVG feDisplacementMap滤镜及实际应用 (0.158)
- CSS混合模式mix-blend-mode/background-blend-mode简介 (0.149)
- 小tip:CSS3下的渐变文字效果实现 (0.142)
- 小tip: CSS3与文字渐变光影流动动画效果实现 (0.142)
- “蝉原则”与CSS3随机多背景随机圆角等效果 (0.142)
- HTML中无标签文本的CSS变色技巧 (0.103)
- 第五届CSS大会主题分享之CSS创意与视觉表现 (0.100)
- FDCon2019大会分享之滤镜与混合模式实录 (0.100)
- 纯CSS实现任意格式图标变色的研究 (RANDOM - 0.012)
现在 background-clip:text 不会忽略background-blend-mode: overlay; 的效果了
学习了 ,膜拜大神
学习
多谢,正有需要
大佬博客干货很多,学习了
都是干货,但是一般人难以坚持
太厉害
可以的,慢慢的来搞还是没问题的
你好,我想问您一个问题,怎么用js获得一个元素默认的样式值。比如说input这个元素我没有显式设置他的display,我怎么通过js去获得这个元素默认的display值。我看chrome的用户代理默认是inline-block,而firefox的是inline,我不论是用jq还是JavaScript得到的都是“”
刚才一直用jq的attr(),,试了下css()可以啦,哈哈
终于可以实现五彩斑斓的黑了
调皮
膜拜大神已久,之前模仿你的网站框架做了一个个人网站http://2tro.com/index01.aspx,你会不会打我~~~~_~~##@@#@
厉害厉害
首页视频播放器可以更新H5了,嘻~~~~
你可以的
数个大拇指!
厉害了小哥哥
遇到这种问题 我一般都是:ui这里切一张图
哈哈