效果演示

html 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Grass, Puppet, Sun, and Rain Scene</title>
<style>
body { margin: 0; padding: 0; display: grid; place-items: center; height: 100dvh; }
#grass { display: block; margin: 0 auto; background-color: rgb(213, 234, 233); image-rendering: pixelated; }
</style>
</head>
<body>
<canvas id="grass" width="500" height="400"></canvas>
<script>
const canvasElement = document.getElementById("grass"), canvasContext = canvasElement.getContext("2d"); canvasContext.imageSmoothingEnabled = false;
let grassBlades = [], amplitude = 1.6, speed = 0.05, offset = 1, raindrops = [], rainSpeed = 4;
const puppetImage = new Image(); puppetImage.src = 'https://png.pngtree.com/png-vector/20220611/ourmid/pngtree-scarecrow-straw-straw-man-clipping-path-vector-png-image_37165776.png';
function drawBlade(startX, startY, controlPointX1, controlPointY1, controlPointX2, controlPointY2, endX, endY, swayAmount) { canvasContext.beginPath(); canvasContext.moveTo(startX, startY); canvasContext.bezierCurveTo(controlPointX1, controlPointY1, controlPointX2, controlPointY2, endX, endY); canvasContext.strokeStyle = "green"; canvasContext.lineWidth = 3; canvasContext.stroke(); }
function drawSun() { canvasContext.beginPath(); canvasContext.arc(80, 80, 40, 0, Math.PI * 2, false); canvasContext.fillStyle = "yellow"; canvasContext.fill(); }
function drawRaindrop(x, y) { canvasContext.beginPath(); canvasContext.moveTo(x, y); canvasContext.lineTo(x + 2, y + 10); canvasContext.strokeStyle = "blue"; canvasContext.lineWidth = 2; canvasContext.stroke(); }
function updateRaindrops() { if (raindrops.length < 100) raindrops.push({ x: Math.random() * canvasElement.width, y: 0 }); for (let i = 0; i < raindrops.length; i++) { const drop = raindrops[i]; drawRaindrop(drop.x, drop.y); drop.y += rainSpeed; if (drop.y > canvasElement.height) { drop.y = 0; drop.x = Math.random() * canvasElement.width; } } }
function drawGrassScene() { canvasContext.clearRect(0, 0, canvasElement.width, canvasElement.height); drawSun(); canvasContext.drawImage(puppetImage, 150, 120, canvasElement.width / 2, canvasElement.height / 1.5);
if (grassBlades.length === 0) { for (let i = 0; i < 350; i++) { const randomX = Math.random() * canvasElement.width, startY = canvasElement.height, controlPointX1 = randomX - Math.random() * 30, controlPointY1 = startY - Math.random() * 100, controlPointX2 = randomX + Math.random() * 30, controlPointY2 = startY - Math.random() * 150, endX = randomX, endY = startY - Math.random() * 200, randomSway = Math.random() * 0.5 - 0.25;
grassBlades.push({ startX: randomX, startY, controlPointX1, controlPointY1, controlPointX2, controlPointY2, endX, endY, swayAmount: randomSway }); } }
for (let i = 0; i < grassBlades.length; i++) { const blade = grassBlades[i]; blade.controlPointX1 += Math.sin(offset) * amplitude; blade.controlPointX2 += Math.sin(offset + 1) * amplitude; blade.endX += Math.sin(offset + 0) * amplitude; drawBlade(blade.startX, blade.startY, blade.controlPointX1, blade.controlPointY1, blade.controlPointX2, blade.controlPointY2, blade.endX, blade.endY, blade.swayAmount); }
updateRaindrops(); offset += speed; requestAnimationFrame(drawGrassScene); }
puppetImage.onload = drawGrassScene;
</script>
</body>
</html>