废话不多说,先看效果图:
实现代码与思路如下:
第一步 添加canvas画布
<body style="background-color: rgb(216, 249, 250);margin: 0px;"> <canvas id="tutorial" width="1520" height="699"></canvas> <div class="text"> <p>鲤鱼跃龙门</p> <p>冲呀!</p> </div> </body>
第二步 获取canvas元素
let canvas = document.getElementById("tutorial"); //检查支持性 if (canvas.getContext) { var ctx = canvas.getContext("2d"); // 获取渲染上下文 // ToDo ... }
第三步 关于白云部分的绘制和动画
- 白云的绘制
用position数组统一设置白云的位置
var img = new Image(); img.src = "./public/cloud.svg"; var position = [{ x: 20, y: 520 }, { x: 350, y: 560 }, { x: 650, y: 490 }, { x: 930, y: 550 }, { x: 1230, y: 570 }]; //设置白云的位置 img.onload = function () { // 开始动画 for (let i = 0; i < position.length; i++) { ctx.drawImage(img, position[i].x, position[i].y); // 每个图片间隔300像素 } };
- 白云的动画
整体的思路就是,结合周期定时器动态设置globalAlpha属性去控制元素的显示与隐藏。
// 淡入淡出动画 function fadeInOut(index) { var opacity = 1; // 初始透明度为1 var increasing = true; // 每隔10毫秒执行一次淡入淡出效果 var intervalId = setInterval(function () { var randomNum = Math.random(); if (increasing) { opacity += randomNum * 0.01; // 透明度逐渐增加 if (opacity >= 1) { increasing = false; // 达到最大透明度后开始减少 } } else { opacity -= randomNum * 0.01; // 透明度逐渐减小 if (opacity <= 0) { // increasing = true; clearInterval(intervalId); // 透明度减小到0后清除定时器 setTimeout(() => fadeInOut(index), 100); // 等待100ms后重新执行淡入淡出 } } imageOpacities[index] = opacity; // 更新图片透明度 drawImage(); // 重新绘制 }, 60); } // 绘制图片 function drawImage() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.save(); // 保存当前绘制状态 // 绘制之前的内容 ctx.beginPath(); ctx.moveTo(75, 25); //二次贝塞尔曲线 ctx.quadraticCurveTo(25, 25, 25, 62.5); ctx.quadraticCurveTo(25, 100, 50, 100); ctx.quadraticCurveTo(50, 120, 30, 125); ctx.quadraticCurveTo(60, 120, 65, 100); ctx.quadraticCurveTo(125, 100, 125, 62.5); ctx.quadraticCurveTo(125, 25, 75, 25); ctx.stroke(); ctx.drawImage(imgDoor, 250, -120); // ctx.drawImage(imgFish, 1150, 450, 200, 200); for (let i = 0; i < position.length; i++) { ctx.globalAlpha = imageOpacities[i]; ctx.drawImage(img, position[i].x, position[i].y); // 每个图片间隔300像素 } // 绘制鱼 ctx.globalAlpha = fishOpacity; ctx.drawImage(imgFish, fishX, fishY, fishWidth, fishHeight); ctx.globalAlpha = 1 - fishOpacity; ctx.drawImage(imgDragon, 250, 100, 600, 600); ctx.restore(); // 恢复之前保存的绘制状态 } //用处 img.onload = function () { // 开始动画 position.forEach((item, index) => { fadeInOut(index); }); };
第四步 关于鱼的绘制和动画
// Fish 图片的初始位置和大小 var fishX = 1150; var fishY = 450; var fishWidth = 200; var fishHeight = 200; // 鱼的透明度 var fishOpacity = 1; // 跳跃动画 function jumpAnimation() { var startY = fishY; var startx = fishX; var maxHeight = startY - 150; // 鱼的最高跳跃高度 var speed = 2; // 跳跃速度 var gravity = 0.1; // 重力加速度 var isRising = true; // 是否处于上升状态 var jumpInterval = setInterval(function () { // 鱼上升 if (isRising) { fishY -= speed; fishX -= speed + 3; if (fishY <= maxHeight) { isRising = false; } } // 鱼下落 else { fishY += speed; fishX -= speed + 3; if (fishY >= startY) { clearInterval(jumpInterval); // 开始消失效果 fadeOut(); } } drawImage(); // 重新绘制鱼 }, 30); } // 消失效果 function fadeOut() { var opacityDecrement = 0.05; // 透明度减少的步长 var fadeInterval = setInterval(function () { fishOpacity -= opacityDecrement; // 透明度逐渐减小 if (fishOpacity <= 0) { fishOpacity = 0; clearInterval(fadeInterval); } drawImage(); // 重新绘制鱼 }, 50); } //用处 imgFish.onload = function () { // 图片加载完成后开始动画 setTimeout(function () { jumpAnimation(); // 1秒后开始跳跃动画 }, 1000); };
第五步 关于对文字的样式
<style> .text { position: absolute; top: 28px; left: 25px; } p { text-align: center; margin: 10px; } </style>
就这,over over ~