CSS Houdini 号称 CSS 领域最令人振奋的革新。CSS 本身长期欠缺语法特性,可拓展性几乎为零,并且新特性的支持效率太低,兼容性差。而 Houdini 直接将 CSS 的 API 暴露给开发者,以往完全黑盒的浏览器解析流开始对外开放,开发者可以自定义属于自己的 CSS 属性。

背景

我们知道,浏览器在渲染页面时,首先会解析页面的 HTML 和 CSS,生成渲染树(rendering tree),再经由布局(layout)和绘制(painting),呈现出整个页面内容。在 Houdini 出现之前,这个流程上我们能操作的空间少之甚少,尤其是 layout 和 painting 环节,可以说是完全封闭,极大地限制了 CSS 的灵活性。社区中 sass、less、stylus 等 CSS 预处理技术的出现大多都源于这个原因,它们都希望通过预编译,突破 CSS 的局限性,让 CSS 拥有更强大的组织和编写能力。所以慢慢地,我们都不再手写 CSS,更方便、更灵活的 CSS 扩展语言成了 web 开发的主角。看到这样的情况,CSS Houdini 终于坐不住了。

什么是 CSS Houdini?

CSS Houdini 对外开放了浏览器解析流程的一系列 API,这些 API 允许开发者介入浏览器的 CSS engine 运作,带来了更多的 CSS 解决方案。

CSS Houdini 主要提供了以下几个 API:

CSS Properties and Values API

允许在 CSS 中定义变量和使用变量,是目前兼容性最好的一个 API;

Layout API

允许开发者编写自己的 Layout Module,自定义诸如 display 这类的布局属性;

Painting API

允许开发者编写自己的 Paint Module,自定义诸如 background-image 这类的绘制属性。

基础:三步用上 Painting API

1、HTML 中通过 Worklets 载入样式的自定义代码:

if ("paintWorklet" in CSS) {

CSS.paintWorklet.addModule("paintworklet.js");

}

Worklets 也是 Houdini 提供的 API 之一,负责加载和执行样式的自定义 JS 代码。它类似于 Web Worker,是一个运行于主代码之外的独立工作进程,但比 Worker 更为轻量,负责 CSS 渲染任务最为合适。

2、新建一个 paintworklet.js,利用 registerPaint 方法注册一个 paint 类 rect,定义 paint 属性的绘制逻辑:

registerPaint(

"rect",

class {

static get inputProperties() {

return ["--rect-color"];

}

paint(ctx, geom, properties) {

const color = properties.get("--rect-color")[0];

ctx.fillStyle = color;

ctx.fillRect(0, 0, geom.width, geom.height);

}

}

);

上边定义了一个名为 rect 的 paint 属性类,当 rect 被使用时,会实例化 rect 并自动触发 paint 方法执行渲染。paint 方法中,我们获取节点 CSS 定义的 --rect-color 变量,并将元素的背景填充为指定颜色。ctx 参数是一个 Canvas 的 Context 对象,因此 paint 的逻辑跟 Canvas 的绘制方式一样。

3、CSS 中使用的时候,只需要调用 paint 方法:

.rect {

width: 100vw;

height: 100vh;

background-image: paint(rect);

--rect-color: rgb(255, 64, 129);

}

这是一个自定义 CSS 背景色属性的简单实现,看得出利用 CSS Houdini,我们可以像操作 canvas 一样灵活自如地实现我们想要的样式功能。

进阶:实现动态波纹

根据上述步骤,我们演示一下如何用 CSS Painting API 实现一个动态波浪的效果:

#wave {

width: 20%;

height: 70vh;

margin: 10vh auto;

background-color: #ff3e81;

background-image: paint(wave);

}

if ("paintWorklet" in CSS) {

CSS.paintWorklet.addModule("paintworklet.js");

const wave = document.querySelector("#wave");

let tick = 0;

requestAnimationFrame(function raf(now) {

tick += 1;

wave.style.cssText = `--animation-tick: ${tick};`;

requestAnimationFrame(raf);

});

}

// paintworklet.js

registerPaint('wave', class {

static get inputProperties() {

return ['--animation-tick'];

}

paint(ctx, geom, properties) {

let tick = Number(properties.get('--animation-tick'));

const {

width,

height

} = geom;

const initY = height * 0.4;

tick = tick * 2;

ctx.beginPath();

ctx.moveTo(0, initY + Math.sin(tick / 20) * 10);

for (let i = 1; i <= width; i++) {

ctx.lineTo(i, initY + Math.sin((i + tick) / 20) * 10);

}

ctx.lineTo(width, height);

ctx.lineTo(0, height);

ctx.lineTo(0, initY + Math.sin(tick / 20) * 10);

ctx.closePath();

ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';

ctx.fill();

}

})

paintworklet 中,利用 sin 函数绘制波浪线,由于 AnimationWorklets 尚处于实验阶段,开放较少,这里我们在 worklet 外部用 requestAnimationFrame API 来做动画驱动,让波浪纹动起来。完成后能看到下边这样的效果。

然而事实上这个效果略显僵硬,sin 函数太过于规则了,现实中的波浪应该是不规则波动的,这种不规则主要体现在两个方面:

1)波纹高度(Y)随位置(X)变化而不规则变化

把图按照 x-y 正交分解之后,我们希望的不规则,可以认为是固定某一时刻,随着 x 轴变化,波纹高度 y 呈现不规则变化;

2)固定某点(X 固定),波纹高度(Y)随时间推进而不规则变化

动态过程需要考虑时间维度,我们希望的不规则,还需要体现在时间的影响中,比如风吹过的前一秒和后一秒,同一个位置的波浪高度肯定是不规则变化的。

提到不规则,有朋友可能想到了用 Math.random 方法,然而这里的不规则并不适合用随机数来实现,因为前后两次取的随机数是不连续的,而前后两个点的波浪是连续的。这个不难理解,你见过长成锯齿状的波浪吗?又或者你见过上一刻 10 米高、下一刻就掉到 2 米的波浪吗?

为了实现这种连续不规则的特征,我们弃用 sin 函数,引入了一个包 simplex-noise。由于影响波高的有两个维度,位置 X 和时间 T,这里需要用到 noise2D 方法,它提前在一个三维的空间中,构建了一个连续的不规则曲面:

// paintworklet.js

import SimplexNoise from 'simplex-noise';

const sim = new SimplexNoise(() => 1);

registerPaint('wave', class {

static get inputProperties() {

return ['--animation-tick'];

}

paint(ctx, geom, properties) {

const tick = Number(properties.get('--animation-tick'));

this.drawWave(ctx, geom, 'rgba(255, 255, 255, 0.4)', 0.004, tick, 15, 0.4);

this.drawWave(ctx, geom, 'rgba(255, 255, 255, 0.5)', 0.006, tick, 12, 0.4);

}

/**

* 绘制波纹

*/

drawWave(ctx, geom, fillColor, ratio, tick, amp, ih) {

const {

width,

height

} = geom;

const initY = height * ih;

const speedT = tick * ratio;

ctx.beginPath();

for (let x = 0, speedX = 0; x <= width; x++) {

speedX += ratio * 1;

var y = initY + sim.noise2D(speedX, speedT) * amp;

ctx[x === 0 ? 'moveTo' : 'lineTo'](x, y);

}

ctx.lineTo(width, height);

ctx.lineTo(0, height);

ctx.lineTo(0, initY + sim.noise2D(0, speedT) * amp);

ctx.closePath();

ctx.fillStyle = fillColor;

ctx.fill();

}

})

修改峰值和偏置项等参数,可以再画多一个不一样的波浪纹,效果如下,完工!

总结

以上所述是小编给大家介绍的CSS Houdini实现动态波浪纹效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

css3波浪纹路_CSS Houdini实现动态波浪纹效果相关推荐

  1. CSS Houdini实现动态波浪纹

    我们知道,浏览器在渲染页面时,首先会解析页面的 HTML 和 CSS,生成渲染树(rendering tree),再经由布局(layout)和绘制(painting),呈现出整个页面内容.在 Houd ...

  2. SwiftUI 动画图形之绘制正弦波实现个性化波浪纹效果 (教程含源码)

    实战需求 SwiftUI 动画图形之绘制正弦波实现个性化波浪纹效果 (教程含源码) 本文价值与收获 看完本文后,您将能够作出下面的界面 一个可动画显示的SwiftUI形状,用于沿着底部绘制带有弯曲正弦 ...

  3. css3波浪纹路_css3实现波纹特效、H5实现动态波浪效果

    css3实现动态波纹特效,由于css3里面有过渡和动画效果,现在利用css3实现动态波浪效果就很简单了,直接使用transform来实现就ok, 使得translateX 产生偏移就可以不断实现循环动 ...

  4. css3波浪纹路_css3线条波浪动画效果

    这是一款使用CSS3 animation动画和png图片制作的css3线条波浪动画效果.该特效中,使用了3张波浪线条的png图片,以及少量的CSS代码,制作出逼真的线条波浪动画效果. 使用方法 HTM ...

  5. css3波浪纹路_纯 CSS 实现波浪效果!

    一直以来,使用纯 CSS 实现波浪效果都是十分困难的. 因为实现波浪的曲线需要借助贝塞尔曲线. 而使用纯 CSS 的方式,实现贝塞尔曲线,额,暂时是没有很好的方法. 当然,借助其他力量(SVG.CAN ...

  6. css3波浪纹路_使用CSS3实现的波浪分隔线

    CSS 语言: CSSSCSS 确定 html { height: 100vh; } body { height: inherit; background: #2e576b; display: -ms ...

  7. css3波浪纹路_css3动画水波纹、波浪

    Document *{padding:0px;margin:0px;font-family:"微软雅黑";font-size:100%;font-style:normal}dd, ...

  8. css3波浪动画特效

    css3波浪动画特效 可根据需求添加修改波浪线和背景颜色 全部代码如下 <!doctype html> <html> <head> <meta charset ...

  9. 前端必学的CSS3波浪效果演示

    目录 文章目录 前言 CSS3波浪效果 1.Html构建 2.CSS编写 3.完整代码 index.html文件 style.css文件 总结 前言 随着前端技术的不断发展与进步,界面交互的样式要求和 ...

最新文章

  1. javascript函数、对象及变量、正则表达式(7.19)
  2. 命令行 笔记本键盘禁用_宏碁发布Enduro系列三防笔记本电脑和平板电脑
  3. 使用Java EE 8中的反应式API加速服务
  4. 计算机应用基础进制转换说课稿,计算机应用基础信息技术基础《进制转换》教案.doc...
  5. 入门命令13-字符串查找增强:findstr
  6. 管理例程——数据库管理员
  7. FISCO BCOS 日志分析 关键词 格式
  8. 深度学习caffe--手写字体识别例程(一)——运行手写字体识别例程
  9. 光耦隔离的作用是什么?
  10. 【AAAI 2021】自监督目标检测知识蒸馏:Distilling Localization for Self-Supervised Representation Learning
  11. 125KHz 100cm ID 读卡电路_二维码门禁读卡器动态二维码扫描器二维码刷卡读头介绍...
  12. 编程列入高考-青少儿编程学习-Python那些事
  13. 《嵌入式 – GD32开发实战指南》第3章 GPIO流水灯的前世今生
  14. oracle批次处理数据_如何加速Oracle大批量数据处理
  15. 解决pytorch官网下载慢ubuntu16.04+anaconda3(python3.6)+pytorch0.4.1+cuda9.0+cudnn7.1安装指南
  16. Warning: .config does not exists一生一芯
  17. 人工神经网络算法的应用,神经网络算法应用案例
  18. Linux常用环境软件安装(提供对应安装包)
  19. GLES2.0中文API-glFramebufferTexture2D
  20. 我们的征途是星辰大海(演讲稿)(作者:黄哲威)

热门文章

  1. vivo 微服务 API 网关架构实践
  2. Hadoop历险记(七 Hive配置和启动hiveservice2服务)
  3. oracle shmfs,linux tmpfs和swap介绍
  4. Android调用手机新浪微博客户端分享
  5. 证明函数有界的步骤_怎样判断函数的有界性,求具体判断步骤方法。
  6. 极客学院安卓视频零散笔记总结
  7. 爬取数据是违法的吗_网络爬虫违法吗?
  8. ShaderJoy —— “雪花飞舞 ”的实现 【GLSL】
  9. CSP试题—— 风险人群筛查
  10. 探索 PlanetIX:解读区块链游戏运营的奥秘