|
|
|
|
|
在很多扁平網(wǎng)站上,尤其是那些單頁的HTML5扁平網(wǎng)站,常常見到有飄動的線條色帶(樂普線條畫布),覺得很好看,視覺效果特別好。以前我不知道如何實現(xiàn)的,今天剛好看到這個效果的源碼,就收藏起來了,現(xiàn)在分享給大家,可以現(xiàn)拿現(xiàn)用,不復雜。
樂普線條畫布
這個實現(xiàn)方法比較有意思,使用純JS實現(xiàn)的線條飄動效果。
完整HTML代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>樂普線條畫布</title>
<style>
body {
margin: 0;
height: 100vh;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
}
canvas {
box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.15);
background: #fff;
}
</style>
</head>
<body translate="no" >
<canvas id="canvas"></canvas>
<script src='simplex-noise.min.js'></script>
<script id="rendered-js" >
/*--------------------
Utility
--------------------*/
const lerp = (a, b, n) => (1 - n) * a + n * b;
/*--------------------
Setup
--------------------*/
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let time = 0;
const devicePixelRatio = window.devicePixelRatio || 1;
const w = 400;
const h = 400;
const simplex = new SimplexNoise();
const steps = 100;
const amplitude = 30;
const lines = 30;
/*--------------------
DrawLine
--------------------*/
const drawLine = (startY, t, seed) => {
const step = w / steps;
let x = -step;
let y = 0;
const arr = [];
for (let i = 0; i <= steps; i++) {
const n = simplex.noise2D((time * 0.001 + seed + i) * 0.02, (startY + time * t) * 0.0003);
x += step;
let amp = Math.min(i, 40);
if (i > steps - 40) amp = steps - i;
y = startY + n * amp;
arr.push({ x, y });
}
return arr;
};
/*--------------------
Clear
--------------------*/
const clear = () => {
ctx.clearRect(0, 0, w, h);
};
/*--------------------
Draw
--------------------*/
const draw = () => {
const p1 = drawLine(200, 1.1, 100);
const p2 = drawLine(200, 1.3, 200);
const p3 = drawLine(200, 1, 300);
const p4 = drawLine(200, 1.2, 150);
for (let r = 0; r <= lines; r++) {
const h = Math.floor(130 + r + time * 0.01);
ctx.strokeStyle = `hsla(${h}, 50%, 50%, .5)`;
document.body.style.backgroundColor = `hsl(${h}, 40%, 90%)`;
const s = 1 / lines;
ctx.beginPath();
for (let i = 0; i <= steps; i++) {
const type = i === 0 ? 'moveTo' : 'lineTo';
const x = lerp(p1[i].x, p2[i].x, r * s);
const y = lerp(p1[i].y, p2[i].y, r * s);
ctx[type](x, y);
}
ctx.stroke();
}
for (let r = 1; r <= lines; r++) {
const h = Math.floor(130 + lines + r + time * 0.01);
ctx.strokeStyle = `hsla(${h}, 50%, 50%, .5)`;
document.body.style.backgroundColor = `hsl(${h}, 40%, 90%)`;
const s = 1 / lines;
ctx.beginPath();
for (let i = 0; i <= steps; i++) {
const type = i === 0 ? 'moveTo' : 'lineTo';
const x = lerp(p2[i].x, p3[i].x, r * s);
const y = lerp(p2[i].y, p3[i].y, r * s);
ctx[type](x, y);
}
ctx.stroke();
}
};
/*--------------------
Animate
--------------------*/
const animate = () => {
time = window.performance.now();
clear();
requestAnimationFrame(animate);
draw();
};
animate();
/*--------------------
Resize
--------------------*/
const onResize = () => {
canvas.width = w * devicePixelRatio;
canvas.height = h * devicePixelRatio;
canvas.style.width = `${w}px`;
canvas.style.height = `${h}px`;
ctx.scale(devicePixelRatio, devicePixelRatio);
ctx.strokeWidth = 1;
animate();
};
onResize();
/*--------------------
Listeners
--------------------*/
window.addEventListener('resize', onResize);
//# sourceURL=pen.js
</script>
</body>
</html>
代碼分析
可以看到,HTML代碼僅包含一個canvas
標簽,和引用一個JS文件。
<canvas id="canvas"></canvas>
<script src='simplex-noise.min.js'></script>
這個JS文件是一個庫文件,直接引用。實現(xiàn)效果的JS代碼是這里面的代碼:
<script id="rendered-js" >
... ...
</script>
我們可以通過修改JS代碼的參數(shù)來改變線條的長度、高度、數(shù)量等:
/*--------------------
Setup
--------------------*/
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let time = 0;
const devicePixelRatio = window.devicePixelRatio || 1;
const w = 400;
const h = 400;
const simplex = new SimplexNoise();
const steps = 100;
const amplitude = 30;
const lines = 30;
此外,我們可以通過修改CSS屬性來設置畫布的屬性,如陰影、背景:
canvas {
box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.15);
background: #fff;
}