
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>千山万水</title>
<style>
body {
margin: 0;
padding: 0;
}
#container {
margin: 0;
padding: 0;
position:absolute;
top:0;
left:0;
width:100%;
height:100vh;
overflow:hidden;
background-color: #fff;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
background-color:#ff3333;
}
canvas {
margin: 0;
padding: 0;
position:absolute;
top:0;
left:-100px;
}
svg{
margin: 0;
padding: 0;
position:absolute;
top:0;
left:0;
}
</style>
</head>
<body>
<!-- 千山万水 -->
<div id="container"></div>
</body>
<script>
// 使用SVG绘制山脉
// 画布高度和页面高度相同
let canvasHeight=window.innerHeight;
console.log(`canvasHeight=${canvasHeight}`);
//----------------------------
function generateMountainsCurvePoints (pointCount=9,mtWidthBase=30,mtWidthVariation=120,mtHeightBase=100,mtHeightVariation=200) {
// 生成随机的山脉曲线点
// 山脉曲线点数组
let mountainCurvePoints=[];
// 起点
let currentX=0;
let currentY=canvasHeight;
// 随机生成山脉曲线点
for (let i = 0; i < pointCount; i++) {
mountainCurvePoints.push([currentX,currentY]);
//生成随机偏移量
//x偏移量限定区间100-200
let xOffset=Math.random()*mtWidthVariation+mtWidthBase;
currentX+=xOffset;
//y值随机变幻区间
currentY=Math.random()*mtHeightVariation+mtHeightBase;
currentY=canvasHeight-currentY;
}
// 终点
mountainCurvePoints.push([currentX+100,canvasHeight]);
// 返回结果数组
return mountainCurvePoints;
}
//----------------------------
// 绘制山脉
function drawMountains (canvasId,mountainCurvePoints,mtLineColor='rgb(255,0,0,1)',mtFillColor='rgb(255,0,0,1)',mtLineWidth=1) {
console.log(canvasId);
// 获取Canvas元素
const canvas = document.getElementById(canvasId);
const ctx = canvas.getContext('2d');
// 设置Canvas布大小mountainCurvePoints最后一个点的x坐标决定
// 画布宽度由mountainCurvePoints最后一个点的x坐标决定
canvas.width = mountainCurvePoints[mountainCurvePoints.length-1][0];
console.log(`canvas.width=${canvas.width}`);
canvas.height = canvasHeight;
// 设置背景颜色
ctx.fillStyle='rgba(255,0,0,0)';
ctx.fillRect(0,0,canvas.width,canvas.height);
// 绘制山脉曲线,使用随机颜色
ctx.strokeStyle=`${mtLineColor}`;
ctx.lineWidth=mtLineWidth;
ctx.lineCap='round';
ctx.lineJoin='round';
ctx.beginPath();
ctx.moveTo(mountainCurvePoints[0][0], mountainCurvePoints[0][1]);
for (let i = 0; i < mountainCurvePoints.length-1; i++) {
// ctx.lineTo(mountainCurvePoints[i][0], mountainCurvePoints[i][1]);
//绘制圆滑曲线
const p0x=mountainCurvePoints[Math.max(i-1,0)][0];
const p0y=mountainCurvePoints[Math.max(i-1,0)][1];
const p1x=mountainCurvePoints[i][0];
const p1y=mountainCurvePoints[i][1];
const p2x=mountainCurvePoints[i+1][0];
const p2y=mountainCurvePoints[i+1][1];
const p3x=mountainCurvePoints[Math.min(i+2,mountainCurvePoints.length-1)][0];
const p3y=mountainCurvePoints[Math.min(i+2,mountainCurvePoints.length-1)][1];
//计算控制点
const tension=0.15;
const cp1x=p1x+(p2x-p0x)*tension;
const cp1y=p1y+(p2y-p0y)*tension;
const cp2x=p1x+(p3x-p1x)*tension;
const cp2y=p1y+(p3y-p1y)*tension;
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, p2x, p2y);
}
//闭合曲线
ctx.closePath();
ctx.stroke();
//填充颜色
ctx.fillStyle=`${mtFillColor}`;
ctx.fill();
}
//----------------------------
function drawMountainsSVG (canvasId,mountainCurvePoints,mtLineColor='rgb(255,0,0,1)',mtFillColor='rgb(255,0,0,1)',mtLineWidth=1) {
// 绘制山脉
//创建SVG元素svg
const svg = document.createElementNS('http://www.w3.org/2000/svg','svg');
// 设置SVG元素的属性
svg.setAttribute('width',mountainCurvePoints[mountainCurvePoints.length-1][0]);
svg.setAttribute('height',canvasHeight);
svg.setAttribute('id',canvasId);
// 设置SVG元素的属性
svg.setAttribute('viewBox',`0 0 ${mountainCurvePoints[mountainCurvePoints.length-1][0]} ${canvasHeight}`);
// 创建path元素
const path = document.createElementNS('http://www.w3.org/2000/svg','path');
// 构造path文本字符串
let pathText=`M ${mountainCurvePoints[0][0]} ${mountainCurvePoints[0][1]} `;
// 按照mountainCurvePoints的坐标点,绘制山脉曲线
for (let i = 0; i < mountainCurvePoints.length; i++) {
//构造path文本字符串
pathText+=`L ${mountainCurvePoints[i][0]} ${mountainCurvePoints[i][1]} `;
}
// 闭合曲线
pathText+='Z';
// 设置path元素的属性
path.setAttribute('d',pathText);
// 绘制山脉曲线,使用随机颜色
path.setAttribute('stroke',`${mtLineColor}`);
path.setAttribute('stroke-width',`${mtLineWidth}`);
path.setAttribute('stroke-linecap','round');
path.setAttribute('stroke-linejoin','round');
//添加linearGradient线性渐变填充
const linearGradient = document.createElementNS('http://www.w3.org/2000/svg','linearGradient');
linearGradient.setAttribute('id',`linearGradientFill${canvasId}`);
linearGradient.setAttribute('x1','0%');
linearGradient.setAttribute('y1','0%');
linearGradient.setAttribute('x2','0%');
linearGradient.setAttribute('y2','100%');
const stop1 = document.createElementNS('http://www.w3.org/2000/svg','stop');
stop1.setAttribute('stop-color',`${mtFillColor}`);
stop1.setAttribute('offset','0%');
linearGradient.appendChild(stop1);
const stop2 = document.createElementNS('http://www.w3.org/2000/svg','stop');
stop2.setAttribute('stop-color',`orange`);
stop2.setAttribute('offset','100%');
linearGradient.appendChild(stop2);
// 添加linearGradient元素到svg元素
svg.appendChild(linearGradient);
path.setAttribute('fill',`url(#linearGradientFill${canvasId})`);
// 填充颜色
// path.setAttribute('fill',`${mtFillColor}`);
// 添加path元素到svg元素
svg.appendChild(path);
// 添加svg元素到container元素
document.getElementById('container').appendChild(svg);
}
//----------------------------
// 动画:canvas水平平移动画循环
function moveMt(canvasId,speed=10,stopGate=1000000) {
// 获取Canvas元素
let mt = document.getElementById(canvasId);
// 通过修改left属性实现水平平移动,left的属性无法直接获取,需要通过getComputedStyle()方法获取当前left值,,
// 所能直接修改left属性,实现水平平移动
let mtLeft=parseInt(getComputedStyle(mt).left);
// console.log("canvas left:"+mtLeft);
mt.style.left=mtLeft-speed+"px";
//动画循环
let animationId=requestAnimationFrame(()=>{
moveMt(canvasId,speed);
});
// 触发结束循环的条件是left绝对值大于等于当前画布的宽度
// console.log(`stopGate=${stopGate}`);
if(mtLeft<=-stopGate){
console.log(`${canvasId} 结束循环`);
cancelAnimationFrame(animationId);
}
}
//----------------------------
// 绘制山脉
let pointCount=10000;
let mtWidthVariation=50;
let mtHeightVariation=145;
mtps0=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=870,mtHeightVariation=mtHeightVariation);
mtps1=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=800,mtHeightVariation=mtHeightVariation);
mtps2=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=720,mtHeightVariation=mtHeightVariation);
mtps3=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=630,mtHeightVariation=mtHeightVariation);
mtps4=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=530,mtHeightVariation=mtHeightVariation);
mtps5=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=420,mtHeightVariation=mtHeightVariation);
mtps6=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=320,mtHeightVariation=mtHeightVariation);
mtps7=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=200,mtHeightVariation=mtHeightVariation);
//----------------------------
//SVG模式绘制山脉
let mtFillColorList=['#ff4444','#ff5555','#ff6666','#ff7777','#ff8888','#ff9999','#ffaaaa','#ffbbbb','#ffcccc','#ffdddd','#ffeeee','#ffffff'];
drawMountainsSVG("canvas0",mtps0,mtLineColor=mtFillColorList[0],mtFillColor=mtFillColorList[0],mtLineWidth=0);
drawMountainsSVG("canvas1",mtps1,mtLineColor=mtFillColorList[1],mtFillColor=mtFillColorList[1],mtLineWidth=0);
drawMountainsSVG("canvas2",mtps2,mtLineColor=mtFillColorList[2],mtFillColor=mtFillColorList[2],mtLineWidth=0);
drawMountainsSVG("canvas3",mtps3,mtLineColor=mtFillColorList[3],mtFillColor=mtFillColorList[3],mtLineWidth=0);
drawMountainsSVG("canvas4",mtps4,mtLineColor=mtFillColorList[4],mtFillColor=mtFillColorList[4],mtLineWidth=0);
drawMountainsSVG("canvas5",mtps5,mtLineColor=mtFillColorList[5],mtFillColor=mtFillColorList[5],mtLineWidth=0);
drawMountainsSVG("canvas6",mtps6,mtLineColor=mtFillColorList[6],mtFillColor=mtFillColorList[6],mtLineWidth=0);
drawMountainsSVG("canvas7",mtps7,mtLineColor=mtFillColorList[7],mtFillColor=mtFillColorList[7],mtLineWidth=0);
/*
//canvas模式绘制山脉
let mtFillColorList=['#ff3333','#ff4444','#ff5555','#ff6666','#ff7777','#ff8888','#ff9999','#ffaaaa','#ffbbbb','#ffcccc'];
drawMountains("canvas0",mtps0,mtLineColor=mtFillColorList[0],mtFillColor=mtFillColorList[0],mtLineWidth=0);
drawMountains("canvas1",mtps1,mtLineColor=mtFillColorList[1],mtFillColor=mtFillColorList[1],mtLineWidth=0);
drawMountains("canvas2",mtps2,mtLineColor=mtFillColorList[2],mtFillColor=mtFillColorList[2],mtLineWidth=0);
drawMountains("canvas3",mtps3,mtLineColor=mtFillColorList[3],mtFillColor=mtFillColorList[3],mtLineWidth=0);
drawMountains("canvas4",mtps4,mtLineColor=mtFillColorList[4],mtFillColor=mtFillColorList[4],mtLineWidth=0);
drawMountains("canvas5",mtps5,mtLineColor=mtFillColorList[5],mtFillColor=mtFillColorList[5],mtLineWidth=0);
drawMountains("canvas6",mtps6,mtLineColor=mtFillColorList[6],mtFillColor=mtFillColorList[6],mtLineWidth=0);
drawMountains("canvas7",mtps7,mtLineColor=mtFillColorList[7],mtFillColor=mtFillColorList[7],mtLineWidth=0);
*/
//----------------------------
// 调用动画函数
moveMt("canvas0",speed=1);
moveMt("canvas1",speed=2);
moveMt("canvas2",speed=3);
moveMt("canvas3",speed=4);
moveMt("canvas4",speed=5);
moveMt("canvas5",speed=6);
moveMt("canvas6",speed=7);
moveMt("canvas7",speed=8);
</script>
</html>
精简圆滑曲线版:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>千山万水</title>
<style>
body {
margin: 0;
padding: 0;
}
#container {
margin: 0;
padding: 0;
position:absolute;
top:0;
left:0;
width:100%;
height:100vh;
overflow:hidden;
background-color: #fff;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
background-color:#ff3333;
}
canvas {
margin: 0;
padding: 0;
position:absolute;
top:0;
left:-100px;
}
svg{
margin: 0;
padding: 0;
position:absolute;
top:0;
left:0;
}
</style>
</head>
<body>
<!-- 千山万水 -->
<div id="container"></div>
</body>
<script>
// 使用SVG绘制山脉
// 画布高度和页面高度相同
let canvasHeight=window.innerHeight;
console.log(`canvasHeight=${canvasHeight}`);
//----------------------------
function generateMountainsCurvePoints (pointCount=9,mtWidthBase=30,mtWidthVariation=120,mtHeightBase=100,mtHeightVariation=200) {
// 生成随机的山脉曲线点
// 山脉曲线点数组
let mountainCurvePoints=[];
// 起点
let currentX=0;
let currentY=canvasHeight;
// 随机生成山脉曲线点
for (let i = 0; i < pointCount; i++) {
mountainCurvePoints.push([currentX,currentY]);
//生成随机偏移量
//x偏移量限定区间100-200
let xOffset=Math.random()*mtWidthVariation+mtWidthBase;
currentX+=xOffset;
//y值随机变幻区间
currentY=Math.random()*mtHeightVariation+mtHeightBase;
currentY=canvasHeight-currentY;
}
// 终点
mountainCurvePoints.push([currentX+100,canvasHeight]);
// 返回结果数组
return mountainCurvePoints;
}
//----------------------------
//----------------------------
function drawMountainsSVG (canvasId,mountainCurvePoints,mtLineColor='rgb(255,0,0,1)',mtFillColor='rgb(255,0,0,1)',mtLineWidth=1) {
// 绘制山脉
//创建SVG元素svg
const svg = document.createElementNS('http://www.w3.org/2000/svg','svg');
// 设置SVG元素的属性
svg.setAttribute('width',mountainCurvePoints[mountainCurvePoints.length-1][0]);
svg.setAttribute('height',canvasHeight);
svg.setAttribute('id',canvasId);
// 设置SVG元素的属性
svg.setAttribute('viewBox',`0 0 ${mountainCurvePoints[mountainCurvePoints.length-1][0]} ${canvasHeight}`);
// 创建path元素
const path = document.createElementNS('http://www.w3.org/2000/svg','path');
// 构造path文本字符串
let pathText=`M ${mountainCurvePoints[0][0]} ${mountainCurvePoints[0][1]} `;
// 按照mountainCurvePoints的坐标点,绘制山脉曲线
for (let i = 0; i < mountainCurvePoints.length-1; i++) {
//构造path文本字符串
// pathText+=`L ${mountainCurvePoints[i][0]} ${mountainCurvePoints[i][1]} `;
// 绘制圆滑曲线,使用三次贝塞尔曲线
const p0 = mountainCurvePoints[i];
const p1 = mountainCurvePoints[i + 1];
const cp1 = { x: (p0[0] + p1[0]) / 2, y: p0[1] }; // 控制点1,通常在两个点之间垂直于线段的中点
const cp2 = { x: (p0[0] + p1[0]) / 2, y: p1[1] }; // 控制点2,通常在两个点之间垂直于线段的中点,但稍微偏移以避免直线连接
if (i === 0) {
pathText += `M ${p0[0]} ${p0[1]}`; // Move to the first point
} else {
pathText += `C ${cp1.x} ${cp1.y}, ${cp2.x} ${cp2.y}, ${p1[0]} ${p1[1]} `; // Cubic Bezier curve to the next point
}
}
// 闭合曲线
pathText+='Z';
// 设置path元素的属性
path.setAttribute('d',pathText);
// 绘制山脉曲线,使用随机颜色
path.setAttribute('stroke',`${mtLineColor}`);
path.setAttribute('stroke-width',`${mtLineWidth}`);
path.setAttribute('stroke-linecap','round');
path.setAttribute('stroke-linejoin','round');
//添加linearGradient线性渐变填充
const linearGradient = document.createElementNS('http://www.w3.org/2000/svg','linearGradient');
linearGradient.setAttribute('id',`linearGradientFill${canvasId}`);
linearGradient.setAttribute('x1','0%');
linearGradient.setAttribute('y1','0%');
linearGradient.setAttribute('x2','0%');
linearGradient.setAttribute('y2','100%');
const stop1 = document.createElementNS('http://www.w3.org/2000/svg','stop');
stop1.setAttribute('stop-color',`${mtFillColor}`);
stop1.setAttribute('offset','0%');
linearGradient.appendChild(stop1);
const stop2 = document.createElementNS('http://www.w3.org/2000/svg','stop');
stop2.setAttribute('stop-color',`orange`);
stop2.setAttribute('offset','100%');
linearGradient.appendChild(stop2);
// 添加linearGradient元素到svg元素
svg.appendChild(linearGradient);
// 填充颜色
// path.setAttribute('fill',`${mtFillColor}`);
path.setAttribute('fill',`url(#linearGradientFill${canvasId})`);
// 添加path元素到svg元素
svg.appendChild(path);
// 添加svg元素到container元素
document.getElementById('container').appendChild(svg);
}
//----------------------------
// 动画:canvas水平平移动画循环
function moveMt(canvasId,speed=10,stopGate=1000000) {
// 获取Canvas元素
let mt = document.getElementById(canvasId);
// 通过修改left属性实现水平平移动,left的属性无法直接获取,需要通过getComputedStyle()方法获取当前left值,,
// 所能直接修改left属性,实现水平平移动
let mtLeft=parseInt(getComputedStyle(mt).left);
// console.log("canvas left:"+mtLeft);
mt.style.left=mtLeft-speed+"px";
//动画循环
let animationId=requestAnimationFrame(()=>{
moveMt(canvasId,speed);
});
// 触发结束循环的条件是left绝对值大于等于当前画布的宽度
// console.log(`stopGate=${stopGate}`);
if(mtLeft<=-stopGate){
console.log(`${canvasId} 结束循环`);
cancelAnimationFrame(animationId);
}
}
//----------------------------
// 绘制山脉
let pointCount=10000;
let mtWidthVariation=50;
let mtHeightVariation=145;
mtps0=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=870,mtHeightVariation=mtHeightVariation);
mtps1=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=800,mtHeightVariation=mtHeightVariation);
mtps2=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=720,mtHeightVariation=mtHeightVariation);
mtps3=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=630,mtHeightVariation=mtHeightVariation);
mtps4=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=530,mtHeightVariation=mtHeightVariation);
mtps5=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=420,mtHeightVariation=mtHeightVariation);
mtps6=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=320,mtHeightVariation=mtHeightVariation);
mtps7=generateMountainsCurvePoints(pointCount=pointCount,mtWidthBase=30,mtWidthVariation=mtWidthVariation,mtHeightBase=200,mtHeightVariation=mtHeightVariation);
//----------------------------
//SVG模式绘制山脉
let mtFillColorList=['#ff4444','#ff5555','#ff6666','#ff7777','#ff8888','#ff9999','#ffaaaa','#ffbbbb','#ffcccc','#ffdddd','#ffeeee','#ffffff'];
drawMountainsSVG("canvas0",mtps0,mtLineColor=mtFillColorList[0],mtFillColor=mtFillColorList[0],mtLineWidth=0);
drawMountainsSVG("canvas1",mtps1,mtLineColor=mtFillColorList[1],mtFillColor=mtFillColorList[1],mtLineWidth=0);
drawMountainsSVG("canvas2",mtps2,mtLineColor=mtFillColorList[2],mtFillColor=mtFillColorList[2],mtLineWidth=0);
drawMountainsSVG("canvas3",mtps3,mtLineColor=mtFillColorList[3],mtFillColor=mtFillColorList[3],mtLineWidth=0);
drawMountainsSVG("canvas4",mtps4,mtLineColor=mtFillColorList[4],mtFillColor=mtFillColorList[4],mtLineWidth=0);
drawMountainsSVG("canvas5",mtps5,mtLineColor=mtFillColorList[5],mtFillColor=mtFillColorList[5],mtLineWidth=0);
drawMountainsSVG("canvas6",mtps6,mtLineColor=mtFillColorList[6],mtFillColor=mtFillColorList[6],mtLineWidth=0);
drawMountainsSVG("canvas7",mtps7,mtLineColor=mtFillColorList[7],mtFillColor=mtFillColorList[7],mtLineWidth=0);
//----------------------------
// 调用动画函数
moveMt("canvas0",speed=1);
moveMt("canvas1",speed=2);
moveMt("canvas2",speed=3);
moveMt("canvas3",speed=4);
moveMt("canvas4",speed=5);
moveMt("canvas5",speed=6);
moveMt("canvas6",speed=7);
moveMt("canvas7",speed=8);
</script>
</html>

7973

被折叠的 条评论
为什么被折叠?



