


Let's talk about how to use CSS to achieve the wavy progress bar effect
This article will share with you advanced CSS skills and introduce how to use CSS to achieve the wavy progress bar effect. I hope it will be helpful to everyone!
This article is the third article in the CSS Painting API series of CSS Houdini.
- Modern CSS Advanced Image Fade and Disappear Technique
- Modern CSS Advanced Skills, free drawing and building styles like Canvas!
In the last two articles, we introduced in detail how the CSS Painting API can implement custom patterns and even animation effects step by step!
In this article, we will continue to explore and try to use the CSS Painting API to achieve some effects that were not possible with pure CSS in the past. [Recommended learning: css video tutorial]
CSS Painting API
Let’s take a quick look at what is CSS Painting API.
The CSS Painting API is part of CSS Houdini. Houdini, on the other hand, is a set of low-level APIs that expose parts of the CSS engine, allowing developers to extend CSS by joining the styling and layout process of the browser rendering engine. Houdini is a set of APIs that give developers direct access to the CSS Object Model (CSSOM), allowing developers to write code that browsers can parse into CSS, thereby creating new CSS functionality without having to wait. They are implemented natively in the browser.
The current version of CSS Paint API is CSS Painting API Level 1. It is also known as CSS Custom Paint or Houdini's Paint Worklet.
We can understand it as JS In CSS, using the powerful capabilities of JavaScript Canvas to achieve functions that were not possible with CSS in the past.
Use CSS Painting API to achieve wave effect
CSS Implementing wave effect has always been one of the difficulties in CSS. In the past, although we have many ways to use Hack to create some wave effects, I have repeatedly mentioned it in many previous articles:
- Pure CSS to achieve wave effects!
- A clever way to use CSS to create wave effects
- Rounded corner killer, use filters to create rounded corners and wave effects!
Yes, most of the time, we use some tricks to achieve the wave effect, like this:
Now, with the CSS Painting API, we can already draw real wave effects. Take a look at the code:
<div></div> <script> if (CSS.paintWorklet) { CSS.paintWorklet.addModule('/CSSHoudini.js'); } </script>
div { position: relative; width: 300px; height: 300px; background: paint(waveDraw); border-radius: 50%; border: 2px solid rgba(255, 0, 0, 0.5); }
We have defined a waveDraw
method. Next, just use registerPaint to implement this method.
// 文件名为 CSSHoudini.js registerPaint( "waveDraw", class { static get inputProperties() { return []; } paint(ctx, size, properties) { const { width, height } = size; const initY = height * 0.5; ctx.beginPath(); for (let i = 0; i <= width; i++) { ctx.lineTo(i, initY + Math.sin((i) / 20) * 10); } ctx.lineTo(width, height); ctx.lineTo(0, height); ctx.lineTo(0, initY); ctx.closePath(); ctx.fillStyle = 'rgba(255, 0, 0, 0.9)'; ctx.fill(); } } );
In this way, we get such a wave effect:
The above code is actually easy to understand. Let’s explain briefly. Our core is to use paths. Drawing, based on the Math.sin()
trigonometric function, draws a graph of the sin(x) trigonometric function.
The entire graph starts from
ctx.beginPath()
, the first point isctx.lineTo(0, initY Math.sin((i) / 20) * 10)
, butMath.sin(0) = 0
, so it is equal toctx.lineTo(0, initY)
initY
The function here is to control the height from which to start drawing the wave graphics. Our value here isinitY = height * 0.5
, which is defined as a graphic. centre position利用
for (let i = 0; i <= width; i++)
循环,配合ctx.lineTo(i, initY + Math.sin((i) / 20) * 10)
,也就是在每一个 x 轴上的点,都绘制一个点随后三个在循环体外的
ctx.lineTo
的作用是让整个图形形成一个闭环最后
ctx.closePath()
完成整个路径,ctx.fill()
进行上色
如果不 ctx.fill()
上色,利用 ctx.stroke()
绘制边框,也是可以的,其实我们得到是这样一个图形:
上图是同时去掉了 CSS 代码里面的 border-radius: 50%
,方便大家理解。
当然,上面的图形,有个很大的问题,没法动起来,所以,我们需要借助一个 CSS @Property 自定义变量,让它拥有一些动画效果。
我们需要改造一下代码,首先,添加一个 CSS @Property 自定义变量:
@property --animation-tick { syntax: '<number>'; inherits: false; initial-value: 1000; } div { // ... 代码与上述保持一致 animation: move 20s infinite linear; --animation-tick: 1000; } @keyframes move { 100% { --animation-tick: 0; } }
我们添加了一个 --animation-tick
变量,并且利用 CSS 动画,让它从 1000 减至 0。
下一步,利用这个不断在变化的 CSS 自定义变量,我们在 waveDraw
方法中,把它利用上:
// 文件名为 CSSHoudini.js registerPaint( "waveDraw", class { static get inputProperties() { return ["--animation-tick"]; } paint(ctx, size, properties) { let tick = Number(properties.get("--animation-tick")); const { width, height } = size; const initY = height * 0.5; ctx.beginPath(); for (let i = 0; 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); ctx.closePath(); ctx.fillStyle = 'rgba(255, 0, 0, 0.9)'; ctx.fill(); } } );
仔细看,和上述的代码变化不大,核心在于,利用三角函数绘制图形的时候,我们把这个变量加入进去。
从原来的 ctx.lineTo(i, initY + Math.sin((i) / 20) * 10)
,变成了 ctx.lineTo(i, initY + Math.sin((i + tick) / 20) * 10)
。
这样,在这个不断变化的变量的作用下,我们的波浪图形就能运动起来了:
CodePen Demo -- CSS Houdini Wave
虽然能动了,但是总是感觉还少了些什么。如果我们把这个波浪效果应用与进度条之类的效果上,我们可以需要可以快速定义波浪的振幅、每个波峰之间的间距、效果的颜色、百分比等等。
因此,我们需要再通过一个 CSS 变量,让它成为一个实际可用的封装良好的波浪进度条。我们再简单改造一下:
@property --animation-tick { syntax: '<number>'; inherits: false; initial-value: 1000; } @property --height { syntax: '<number>'; inherits: false; initial-value: .7; } div { position: relative; width: 300px; height: 300px; background: paint(waveDraw); animation: move 20s infinite linear; border-radius: 50%; border: 2px solid var(--color1); --amplitude: 15; --gap: 28; --animation-tick: 700; --height: 0.7; --color1: rgba(255, 0, 0, 0.5); --color2: rgba(255, 0, 0, 0.4); --color3: rgba(255, 0, 0, 0.3); transition: --height 8s; }
可以看到,我们定义了非常多个 CSS 变量,每次,它们都是有意义的:
--animation-tick
表示波浪运动的速率--amplitude
波浪的振幅--gap
波峰间距--initHeight
初始高度--color1
、--color2
、--color3
我们会叠加 3 层波浪效果,显得更真实一点,这里 3 个颜色表示 3 层波浪的颜色
定义好这些 CSS 变量后,我们就可以把它们运用在实际的waveDraw
方法中。看看代码:
registerPaint( "waveDraw", class { static get inputProperties() { return [ "--animation-tick", "--height", "--gap", "--amplitude", "--color1", "--color2", "--color3" ]; } paint(ctx, size, properties) { let tick = Number(properties.get("--animation-tick")); let initHeight = Number(properties.get("--height")); let gap = Number(properties.get("--gap")); let amplitude = Number(properties.get("--amplitude")); let color1 = properties.get("--color1"); let color2 = properties.get("--color2"); let color3 = properties.get("--color3"); this.drawWave(ctx, size, tick, amplitude, gap, initHeight, color1); this.drawWave(ctx, size, tick * 1.21, amplitude / 0.82, gap + 2, initHeight + 0.02, color2); this.drawWave(ctx, size, tick * 0.79, amplitude / 1.19, gap - 2, initHeight - 0.02, color3); } /** * ctx * size * tick 速率 * amplitude 振幅 * gap 波峰间距 * initHeight 初始高度 * color 颜色 */ drawWave(ctx, size, tick, amplitude, gap, initHeight, color) { const { width, height } = size; const initY = height * initHeight; tick = tick * 2; ctx.beginPath(); for (let i = 0; i <= width; i++) { ctx.lineTo(i, initY + Math.sin((i + tick) / gap) * amplitude); } ctx.lineTo(width, height); ctx.lineTo(0, height); ctx.lineTo(0, initY); ctx.closePath(); ctx.fillStyle = color; ctx.fill(); } } );
可以看到,我们在 paint()
方法中,调用了 this.drawWave()
。每次调用 this.drawWave()
都会生成一个波浪图形,通过 3 层的叠加效果,生成 3 层波浪。并且,把我们在 CSS 中定义的变量全部的应用了起来,分别控制波浪效果的不同参数。
这样,我们就得到了这样一个波浪效果:
通过控制 CSS 中的 --height
变量,还可以实现高度的变化,从而完成真实的百分比,实现一种进度条效果。
div:hover { --height: 0; }
效果如下:
很好,非常不错的效果。有了上述一些 CSS 自定义变量的帮助,我们就可以通过封装好的 waveDraw
方法,实现不同颜色,不同大小,不同速率的波浪进度条效果了。
我们只需要简单的改变一下传入的 CSS 变量参数即可:
<div></div> <div></div> <div></div>
div { position: relative; width: 300px; height: 300px; background: paint(waveDraw); animation: move 20s infinite linear; border-radius: 50%; border: 2px solid var(--color1); --amplitude: 15; --gap: 28; --animation-tick: 700; --height: 0.7; --color1: rgba(255, 0, 0, 0.5); --color2: rgba(255, 0, 0, 0.4); --color3: rgba(255, 0, 0, 0.3); transition: --height 8s; } div:nth-child(2) { --amplitude: 6; --gap: 25; --animation-tick: 300; --height: 0.5; --color1: rgba(28, 90, 199, 0.5); --color2: rgba(28, 90, 199, 0.4); --color3: rgba(28, 90, 199, 0.3); } div:nth-child(3) { --amplitude: 3; --gap: 30; --animation-tick: 1200; --height: 0.3; --color1: rgba(178, 120, 33, 0.5); --color2: rgba(178, 120, 33, 0.4); --color3: rgba(178, 120, 33, 0.3); }
看看效果如何:
CodePen Demo -- CSS Hudini Custom Wave Effects !
In this way, with the help of CSS Painting API, we have perfectly realized the wave graphics, and with the help of it, we have realized the wave progress bar effect. By passing in different CSS variables, we have the ability to quickly batch generate different effects. It makes up for the shortcomings of previous CSS in wave effects!
Of course, based on the above code, there is still some room for optimization:
In the above CSS code, you can see that we are passing in There are 3 CSS variables about color,
--color1
,--color2
,--color3
. Normally, 1 color is passed in here, that is Yes, by converting to HSL color representation, replacing the L color value, and obtaining the other two approximate color values. Of course, doing this will add a lot of JavaScript code. Therefore, in order to facilitate everyone's understanding, this article lazily directly passes in 3 CSS color variable values;-
The entire wave effect is a single round I set the animation duration to 20s, but in this article, I did not adapt the hand-to-tail connection of the animation, which means that every 20s, the wave effect may have an obvious beating feeling. To solve this problem, there are two ideas
- Through accurate calculation, let the last frame of the animation and the first frame of the animation be connected
- Put
--animation- Set the value of tick
to a very large value, and then set the corresponding single-round animation time to be very long. In this way, you will basically not feel the frame skipping of the animation
The third problem may be compatibility
compatibility?
Well, in fact, the previous article also talked about the compatibility issue, because there may be many students who saw this article and did not read the first two articles. So, how compatible is the CSS Painting API?
CanIUse - registerPaint The data is as follows (as of 2022-11-23):
Chrome and Edge are based on Chromium Kernel browsers have supported it for a long time, but among mainstream browsers, Firefox and Safari do not yet support it.
Although CSS Houdini is powerful, it currently seems that it will still take some time to be put into production environments on a large scale. Let's give it some time!
Original address: https://juejin.cn/post/7170868201645932551
Author: ChokCoco
(Learning video sharing: web front end)
The above is the detailed content of Let's talk about how to use CSS to achieve the wavy progress bar effect. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Using Bootstrap in Vue.js is divided into five steps: Install Bootstrap. Import Bootstrap in main.js. Use the Bootstrap component directly in the template. Optional: Custom style. Optional: Use plug-ins.

HTML defines the web structure, CSS is responsible for style and layout, and JavaScript gives dynamic interaction. The three perform their duties in web development and jointly build a colorful website.

There are two ways to create a Bootstrap split line: using the tag, which creates a horizontal split line. Use the CSS border property to create custom style split lines.

WebdevelopmentreliesonHTML,CSS,andJavaScript:1)HTMLstructurescontent,2)CSSstylesit,and3)JavaScriptaddsinteractivity,formingthebasisofmodernwebexperiences.

To adjust the size of elements in Bootstrap, you can use the dimension class, which includes: adjusting width: .col-, .w-, .mw-adjust height: .h-, .min-h-, .max-h-

To set up the Bootstrap framework, you need to follow these steps: 1. Reference the Bootstrap file via CDN; 2. Download and host the file on your own server; 3. Include the Bootstrap file in HTML; 4. Compile Sass/Less as needed; 5. Import a custom file (optional). Once setup is complete, you can use Bootstrap's grid systems, components, and styles to create responsive websites and applications.

There are several ways to insert images in Bootstrap: insert images directly, using the HTML img tag. With the Bootstrap image component, you can provide responsive images and more styles. Set the image size, use the img-fluid class to make the image adaptable. Set the border, using the img-bordered class. Set the rounded corners and use the img-rounded class. Set the shadow, use the shadow class. Resize and position the image, using CSS style. Using the background image, use the background-image CSS property.

How to use the Bootstrap button? Introduce Bootstrap CSS to create button elements and add Bootstrap button class to add button text
