前言
最近几天,银杏叶子都枯黄了,风一吹,杏叶纷纷扬扬,特别好看。此次,我们将借助豆包 MarsCode 云 IDE,将这银杏飘落的效果实现,搬好小板凳,咱们出发吧。下图是周末的时候在青城山拍的。
豆包 MarsCode 官网: 豆包 MarsCode - 编程助手
静态页面构建
在构建静态页面时,我们首先引入了一张银杏叶图片 ginkgo.svg
。前端选择vue框架。
问:ginkgo.svg为一张银杏树叶图,帮我将他放到页面中,给我完整的vue代码
将 MarsCode 生成的代码复制过来后,顺利编译通过,点击右侧 web 预览,能在页面中看到单张银杏叶。
掉落动画
现在这张银杏叶只是一张静态的图片,我们要让银杏叶 “动” 起来。
问:给这片银杏叶添加掉落动画。
MarsCode 迅速响应,添加了 @keyframes 动画规则,银杏叶开始缓缓掉落。
不过这银杏叶掉落的样子看起来很机械,不像真实世界里的树叶飘落那么自然。
融入物理要素
真实世界里,树叶飘落受重力与空气阻力左右,速度也不会恒定,我们需要告诉MarsCode,要引入 “verticalAcceleration” 变量,计算垂直加速度,更新速度与位置,并且需要添加随机水平位移以模拟风的影响
问:树叶不应该速度一致地下落,它可能会因为风或者空气阻力,下落时的加速度可能为负值
经过改造,有了一定的速度变化和加速度的影响,但是还不够自然,在下落过程中,我们还需要为银杏叶添加方向上的随机改变。
三维旋转
为了使银杏叶在下降过程中有更逼真的三维效果,我们需要利用 CSS 的 transform-style
属性创建 3D 空间,并通过 perspective
属性设定观察者视角。使用 transform
属性的 rotate3d
函数,为银杏叶赋予三维旋转效果。
问:树叶在下降过程中可以进行三维的旋转。
这样,银杏叶在飘落时不仅有水平和垂直方向的运动,还能进行三维旋转,视觉效果更加真实。
生成更多银杏叶
现在这一片叶子的效果虽然不错,但还不够壮观,我们要让画面里有更多的银杏叶一起飘落,而且它们的初速度、加速度等都得是随机。
问:生成更多的银杏叶,下落位置,速度,旋转都随机
MarsCode 为我们构建了一个名为 “leaves” 的数组,该数组用于存储众多银杏叶的各类信息,如大小、所处位置、旋转角度以及飘落速度等。在动画更新函数里,循环来逐一处理每片树叶的状态更新,模拟出银杏叶在风中各自不同的动态变化过程。
背景烘托
最后,为了增加氛围感,我们给增加一个银杏树的背景图,背景图就去豆包聊天 中叫它帮我们生成一张。
问:生成图片:一棵树叶茂盛的银杏树,叶子黄黄的了,树在屏幕的左边,树很大,只看得见树干很部分的银杏叶,比例 「16:9」,风格为手绘,背景颜色为适合的纯颜色
选一张你觉得最好看的,把背景图加上,最后效果:
结尾
在使用 MarsCode 时,一个指令下去常常达不到最理想的效果,得反复调整、多次尝试。但这也正说明 MarsCode 有无限可能。不管我们有啥想法,它都能帮咱们去试试,总能找到办法把咱的创意实现或给我们提供实现的思路,这也是 MarsCode 最厉害的地方,让我们能够尝试更多的可能。
完整代码
<template>
<div>
<img class="leaf" v-for="(leaf, index) in leaves" :key="index" src="./assets/ginkgo.svg" :alt="leaf.alt" :style="{ width: leaf.size + 'px', height: leaf.size + 'px', top: leaf.position + 'px', left: leaf.left + 'px', position: 'absolute', transform: 'rotateX(' + leaf.rotationX + 'deg) rotateY(' + leaf.rotationY + 'deg) rotateZ(' + leaf.rotationZ + 'deg)' }">
</div>
</template>
<script>
export default {
data() {
return {
leaves: [
{ size: 50, velocity: 2, horizontalVelocity: 2, position: 0, left: 4, rotationX: 0, rotationY: 0, rotationZ: 0, image: './assets/ginkgo.svg', alt: 'Leaf' },
{ size: 50, velocity: 3, horizontalVelocity: 3, position: 0, left: 61, rotationX: 0, rotationY: 0, rotationZ: 0, image: './assets/ginkgo.svg', alt: 'Leaf' },
{ size: 50, velocity: 4, horizontalVelocity: 4, position: 0, left: 0, rotationX: 0, rotationY: 0, rotationZ: 0, image: './assets/ginkgo.svg', alt: 'Leaf' },
{ size: 50, velocity: 1, horizontalVelocity: 1, position: 0, left: 4, rotationX: 0, rotationY: 0, rotationZ: 0, image: './assets/ginkgo.svg', alt: 'Leaf' },
{ size: 50, velocity: 3, horizontalVelocity: 2, position: 0, left: 0, rotationX: 0, rotationY: 0, rotationZ: 0, image: './assets/ginkgo.svg', alt: 'Leaf' },
],
};
},
mounted() {
this.startAnimation();
},
methods: {
startAnimation() {
const gravity = 0.2; // 减小重力加速度,使下降变慢
const airResistance = 0.01; // 空气阻力系数
const windForce = 0.5; // 风力大小
setInterval(() => {
this.leaves.forEach(leaf => {
let velocity = leaf.velocity; // 初始速度
let horizontalVelocity = leaf.horizontalVelocity; // 初始水平速度
// 更新叶子的旋转角度
leaf.rotationX += 1; // 这里可以根据需要调整旋转速度
leaf.rotationY += 1;
leaf.rotationZ += 1;
if (leaf.rotationX >= 360) {
leaf.rotationX = 0;
}
if (leaf.rotationY >= 360) {
leaf.rotationY = 0;
}
if (leaf.rotationZ >= 360) {
leaf.rotationZ = 0;
}
// 应用重力和空气阻力
velocity += gravity;
velocity *= (1 - airResistance);
// 应用风力
if (Math.random() < 0.5) { // 50%的概率受到风力影响
horizontalVelocity += windForce;
} else {
horizontalVelocity -= windForce;
}
// 更新叶子的位置
leaf.position += velocity;
leaf.left += horizontalVelocity;
// 防止叶子飞出屏幕
if (leaf.position > window.innerHeight) {
leaf.position = 0;
leaf.left = Math.random() * window.innerWidth;
} else if (leaf.position < 0) { // 如果叶子上升到屏幕顶部
leaf.position = 0;
leaf.velocity = 0; // 重置速度,使其不再上升
}
});
}, 1000 / 60); // 每秒60帧
},
},
};
</script>
<style>
body{
background: no-repeat url("./assets/background1.png");
background-size: contain;
max-width: 100vw;
max-height: 100vh;
overflow: hidden;
}
.leaf {
transform-style: preserve-3d;
}
</style>