Disclaimer: The graphic and model materials involved in this article are only for personal study, research and appreciation. Please do not re-modify, illegally spread, reprint, publish, commercialize, or conduct other profit-making activities.
background
If you have played 🎮
《王者荣耀》
, 《阴阳师》
and other mobile games, you must have noticed its startup animation, skin vertical drawing cards and other scenes, often using static A simple animation of the base image and local liquid flow effect. These flow animations may appear in the slow-flowing water flow 🌊
, the flag fluttering in the wind 🎏
, the game character sleeve 🧜♀️
, Cloud, rain, fog weather effects that slow down with time ⛅
etc. This transition effect not only saves the cost of developing full-scale animations, but also makes the game screen more enthusiastic, adventurous, 💰
, and advanced, and it is also easier to attract players.
This paper uses front-end development technology, combined with SVG
and CSS
to achieve a similar liquefaction flow effect.本文包含的知识点主要包括: mask-image
、 feTurbulence
feDisplacementMap
、 filter
、 canvas
--Drawing method, canvas
TimelineMax
animation and input[type=file]
local image resource loading, etc.
Effect
Let's take a look at the implementation effect first. The following examples and the 👆
article Banner
figure are all applied with the liquid flow animation effect generated by the content of this article. Since GIF
the image compression is serious, the animation effect does not look very smooth 🙃
, you may wish to experience the effect yourself through the following demo page link and generate your own 传说
, 典藏
Skin vertical painting 😅
.
-
👁🗨
Online experience: https://dragonir.github.io/paint-heat-map/ -
👁🗨
Online experience: https://codepen.io/dragonir/full/qBoxQKW
🌀
Mist Diffusion 塞尔达传说:旷野之息
💃
fluttering 貂蝉:猫影幻舞
🌅
Huguang Wave
🔠
Text Liquefaction
📌
ps: the experience page is deployed inGitpage
the uploading image function is not really uploaded to the server, but will only be loaded into the browser locally, the page will not get any information, you can experience it with confidence , don't worry about privacy leaks.
accomplish
The page is mainly composed of 2
part, the top is used to load the picture, and you can draw the hotspot path by pressing the 🖱
mouse swipe to add a flow effect to the picture; the bottom is the control area , click the button 🔘
to clear the canvas , you can clear the drawn flowing animation effect, click the button 🔘
switch the picture to load the local picture.
📌
Note, there is also an invisible function, when you finish drawing, you can click🖱
Right mouse button , and then choose to save the picture, the saved picture is the path we draw fluid animation Using this heat map and using the knowledge ofCSS
in this article, you can convert static pictures into dynamic pictures!
HTML page structure
#sketch
element is mainly used to draw and load the drawing board of the flow effect heat map; #button_container
is the button control area at the bottom of the page; filter
svg
element filter
Filters to achieve liquid flow animation effects, including feTurbulence
and feDisplacementMap
filters.
<main id="sketch">
<canvas id="canvas" data-img=""></canvas>
<div class="mask">
<div id="maskInner" class="mask-inner"></div>
</div>
</main>
<section class="button_container">
<button class="button">清除画布</button>
<button class="button"><input class="input" type="file" id="upload">上传图片</button>
</section>
<svg>
<filter id="heat" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
<feTurbulence id="heatturb" type="fractalNoise" numOctaves="1" seed="2" />
<feDisplacementMap xChannelSelector="G" yChannelSelector="B" scale="22" in="SourceGraphic" />
</filter>
</svg>
💡
feTurbulence and feDisplacementMap
-
feTurbulence
: The filter uses thePerlin
noise function to create an image, which can be used to simulate artificial textures such as moiré and marble. -
feDisplacementMap
: Map displacement filter that replaces the image with pixel values fromin
in2
space from ---120fe9c77f8634cf80bf2ede581f17db--- to space. That is, it can change the pixel position of elements and graphics, by traversing all the pixels of the original graphics,feDisplacementMap
remap and replace a new position to form a new graphics. The mainstream application of this filter in the industry is to deform, distort, and liquefy graphics.
CSS styles
Then look at the implementation of the style, main
element as the main container and the main pattern as the background image; canvas
as the canvas to occupy the space of 100%
; .mask
and .mask-inner
are used to generate the effect of the hotspot path and the background image as shown below, which is achieved with the help of mask-image
. Finally, in order to generate a dynamic flow effect, .mask-inner
pass the filter: url(#heat)
the previously generated svg
as the source of the filter, and the follow-up will be in JavaScript
By continuously modifying the properties of the svg
filter, a liquid flow animation is generated.
main {
position: relative;
background-image: url('bg.jpg');
background-size: cover;
background-position: 100% 50%;
}
canvas {
opacity: 0;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.mask {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
mask-mode: luminance;
mask-size: 100% 100%;
backdrop-filter: hard-light;
mask-image: url('mask.png');
}
.mask-inner {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url('bg.jpg') 0% 0% repeat;
background-size: cover;
background-position: 100% 50%;
filter: url(#heat);
mask-image: url('mask.png')
}
💡
mask-image
mask-image
CSS
attribute is used to set the image of the mask layer on the element.
Syntax :
// 默认值,透明的黑色图像层,也就是没有遮罩层。
mask-image: none;
// <mask-source><mask>或CSS图像的url的值
mask-image: url(masks.svg#mask1);
// <image> 图片作为遮罩层
mask-image: linear-gradient(rgba(0, 0, 0, 1.0), transparent);
mask-image: image(url(mask.png), skyblue);
// 多个值
mask-image: image(url(mask.png), skyblue), linear-gradient(rgba(0, 0, 0, 1.0), transparent);
// 全局值
mask-image: inherit;
mask-image: initial;
mask-image: unset;
Compatibility :
⚡
This function is still under development for some browsers, and a browser prefix is required to be compatible with different browsers.
JavaScript method
① Draw a heat map
Listen for mouse movement and click events, and draw wave path hotspots on canvas
.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var sketch = document.getElementById('sketch');
var sketchStyle = window.getComputedStyle(sketch);
var mouse = { x: 0, y: 0 };
canvas.width = parseInt(sketchStyle.getPropertyValue('width'));
canvas.height = parseInt(sketchStyle.getPropertyValue('height'));
canvas.addEventListener('mousemove', e => {
mouse.x = e.pageX - canvas.getBoundingClientRect().left;
mouse.y = e.pageY - canvas.getBoundingClientRect().top;
}, false);
ctx.lineWidth = 40;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('mousedown', () => {
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
canvas.addEventListener('mousemove', onPaint, false);
}, false);
canvas.addEventListener('mouseup', () => {
canvas.removeEventListener('mousemove', onPaint, false);
}, false);
var onPaint = () => {
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
var url = canvas.toDataURL();
document.querySelectorAll('div').forEach(item => {
item.style.cssText += `
display: initial;
-webkit-mask-image: url(${url});
mask-image: url(${url});
`;
});
};
After the drawing is completed, you can right-click on the page to save the generated heat map of the wave path, and directly put the heat map that you are satisfied with drawing into CSS
, you can add local wave effect to the picture you like, the following one The image is the fluctuating heat path map used on this example page.
② Generate animation
In order to generate the real-time updated wave effect, this article uses TweenMax
to achieve by changing the feTurbulence
baseFrequency
property value of ---f07eb54d06a3a8ecdaeda768bc27bcd8---, using other animation libraries or using requestAnimationFrame
also can achieve the same function.
feTurb = document.querySelector('#heatturb');
var timeline = new TimelineMax({
repeat: -1,
yoyo: true
}),
timeline.add(
new TweenMax.to(feTurb, 8, {
onUpdate: () => {
var bfX = this.progress() * 0.01 + 0.025,
bfY = this.progress() * 0.003 + 0.01,
bfStr = bfX.toString() + ' ' + bfY.toString();
feTurb.setAttribute('baseFrequency', bfStr);
}
}),
0);
③ Clear the canvas
Click the Clear Canvas button to clear the drawn wave path, mainly by clearing the attribute value of the page element mask-image
and clearing the canvas
canvas.
function clear() {
document.querySelectorAll('div').forEach(item => {
item.style.cssText += `
display: none;
-webkit-mask-image: none;
mask-image: none;
`;
});
}
document.querySelectorAll('.button').forEach(item => {
item.addEventListener('click', () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
clear();
})
});
④ Switch pictures
Click to switch the picture, you can load a local picture as the drawing base map, this function is to obtain the picture resource through input[type=file]
, and then set it to a new one by modifying CSS
Canvas background.
document.getElementById('upload').onchange = function () {
var imageFile = this.files[0];
var newImg = window.URL.createObjectURL(imageFile);
clear();
document.getElementById('sketch').style.cssText += `
background: url(${newImg});
background-size: cover;
background-position: center;
`;
document.getElementById('maskInner').style.cssText += `
background: url(${newImg});
background-size: cover;
background-position: center;
`;
};
At this point, all the functions have been realized. Let's make a startup page of your favorite 史诗皮肤
or 奥德赛小游戏
🤣
.
📥
Source address: https://github.com/dragonir/paint-heat-map
Summarize
The new knowledge points included in this article mainly include:
-
mask-image
Mask element -
feTurbulence
andfeDisplacementMap
svg
filters -
filter
Attribute -
Canvas
Drawing method -
TimelineMax
animation -
input[type=file]
Local image resource loading
If you want to know other front-end knowledge or other knowledge that is not described in detail in this article Web 3D
development technology related knowledge, you can read my previous articles. Please indicate the original address and author when reprinting . If you think the article is helpful to you, don't forget to click three links 👍 .
appendix
- My 3D column can be accessed by clicking this link 👈
- [1]. 🌐 Use Three.js to achieve a cool cyberpunk style 3D digital earth screen
- [2]. 🦊 Three.js implements a 3D open world game: Ali's multiverse
- [3]. 🔥 Three.js flame effect to realize the dynamic logo of Aerden's Ring
- [4]. 🐼 Three.js Realize the 2022 Winter Olympics theme 3D fun page, including Bing Dun Dun
-
...
- [1]. 📷 The front-end implements a very impressive browser-side scanning function
- [2]. 🌏 The Legend of Zelda: Breath of the Wild
- [3]. 😱 Realize cyberpunk 2077 style visual effects with CSS only a few steps
-
...
refer to
- [1]. https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/feTurbulence
- [2]. https://developer.mozilla.org/zh-CN/docs/Web/SVG/Element/feDisplacementMap
- [3]. https://developer.mozilla.org/zh-CN/docs/Web/CSS/mask-image
- [4]. https://developer.mozilla.org/zh-CN/docs/Web/CSS/filter
Author: dragonir The address of this article: https://www.cnblogs.com/dragonir/p/16545805.html
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。