我希望,你把篮球和鸡联系起来想一想。。。

"我希望,你把篮球和鸡联系起来想一想。"

"篮球和鸡?"

"我有一个好点子..."

目录

创建页面

页面准备

首先开始万恶的第一步,创建一个空的HTML页,页面默认目录内容如下方代码块。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
	</body>
</html>

再分别准备鸡的gif、篮球素材、爆炸gif素材如下。

实现基础样式

万事俱备只欠东风,先在页面设计一个固定的区域框框,把鸡给框起来。

<div class="container">
		<img src="img/c.gif" class="rooster" id="rooster" />
</div>

实现鸡的跑马灯

通过@keyframes动画实现跑马灯效果,固定在左侧刷出,在右侧消失。配合上gif动态图整个页面的氛围一下就燃起来了。。

@keyframes moveRooster {
				0% {
					left: 0;
					/* 起始位置在左边 */
				}

				100% {
					left: 100%;
					/* 结束位置在右边 */
				}
			}

篮球弹跳

实现篮球击出

主角之一鸡有了,现在还差篮球,把篮球图片放到页面上,再给它一个居中效果,这下就齐活了。

给区域添加一个监听器,当点击时则让篮球朝着对应的区域击出,这里需要注意几点:

  1. 如果正在击出的过程中,需要组织多次点击
  2. 获取篮球中心位置及点击位置计算方向
  3. 通过设置移动的距离,再飞行的过程中添加动画
  4. 设置动画时长
	// 添加事件监听器到整个文档
				document.addEventListener('click', (event) => {
					if (isBouncing) return; // 如果正在弹跳,阻止多次点击

					isBouncing = true; // 设置为正在弹跳状态

					// 获取篮球中心位置
					const ballRect = basketball.getBoundingClientRect();
					const ballCenterX = ballRect.left + ballRect.width / 2;
					const ballCenterY = ballRect.top + ballRect.height / 2;

					// 获取点击位置
					const clickX = event.clientX;
					const clickY = event.clientY;

					// 计算方向
					const deltaX = clickX - ballCenterX;
					const deltaY = clickY - ballCenterY;
					const angle = Math.atan2(deltaY, deltaX); // 计算角度
					
					const distance = 420; // 向上飞出的距离
					const offsetX = Math.cos(angle) * distance; // X方向的位移
					const offsetY = Math.sin(angle) * distance; // Y方向的位移

					// 先让篮球向上飞出
					basketball.style.transition = 'transform 0.5s ease'; // 设置飞出时的过渡时间
					basketball.style.transform = `translate(${offsetX}px, ${-distance}px)`; // 向上和方向移动篮球

					setTimeout(() => {
						basketball.style.transition = 'transform 0.7s ease'; 
						basketball.style.transform = 'translate(0, 0)'; 
						basketball.style.transition = 'transform 0.2s ease'; 
						basketball.style.transform += ' translateY(-30px)'; 
						setTimeout(() => {
							basketball.style.transform = 'translate(0)'; 
							isBouncing = false;
							basketball.style.transition = 'transform 0.2s ease';
						}, 200); // 给拍动效果一些时间后检测碰撞
					}, 500); // 向上移动的时间
				});

检查是否击中鸡并计算得分

现在鸡也能飞了,球也能打了,该计算得分了,不然搁这砸来砸去的也没有一点成就感。

这里主要通过JS获取鸡和篮球的矩形,计算两者的中心点和距离,再得到其半径距离,根据距离判断是否击中,目前来说这种效果不是很好,建议可以用getBoundingClientRect()获取两者的位置来判断是否相交,这样应该效果好一点。

实现看一眼就爆炸效果

通过上述步骤已经完成了大部分工作,鸡也飞了,球也打了,分也得了。。但是这鸡被打中后还是大摇大摆的飞走了,感觉不是太符合物理定律,怎么着也得给一点回应吧,那就让它爆炸得了。。

单独写一个函数,当篮球击中鸡时设置为爆炸的gif,0.5s后让鸡从起点再次飞出。

总结

技术点

  1. @keyframes 是 CSS 动画的一个重要部分,用于创建和定义 CSS 动画的关键帧。通过使用 @keyframes,可以控制动画在不同时间点的样式变化。

基本语法

@keyframes animation-name {
    from {
        /* 起始状态的样式 */
    }
    to {
        /* 结束状态的样式 */
    }
}

/* 或者使用百分比 */
@keyframes animation-name {
    0% {
        /* 起始状态的样式 */
    }
    100% {
        /* 结束状态的样式 */
    }
}

关键属性

  • animation-name:指定动画的名称,与 @keyframes 中定义的名称相同。
  • from 和 to:这两个关键字表示动画的起始和结束状态。也可以使用百分比来定义多个中间状态。
  • 百分比:除了 from 和 to,还可以使用 0%、25%、50%、75% 和 100% 等来定义多个关键帧,从而实现更复杂的动画效果。

完整代码

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>公鸡与篮球</title>
		<style>
			body {
				overflow: hidden;
				/* 隐藏溢出部分 */
				margin: 0;
				/* 移除默认边距 */
				background-color: white;
				/* 背景色 */
			}

			.container {
				position: relative;
				width: 1000px;
				/* 设置容器宽度 */
				height: 600px;
				/* 可以设置一个合适的高度 */
				margin: 100px auto 0;
				/* 上边距100px,左右居中 */
				display: flex;
				flex-direction: column;
				align-items: center;
				/* 居中对齐 */
				justify-content: flex-start;
				/* 顶部对齐 */
				/* border: 2px solid #333; /* 添加边框,便于查看范围 */
				*/ background-color: #fff;
				/* 设置容器背景色 */
				box-shadow: rgba(0, 0, 0, 0.15) 0px 5px 15px 0px;
			}

			.score {
				position: absolute;
				top: 20px;
				/* 距离顶部的距离 */
				right: 20px;
				/* 距离右边的距离 */
				font-size: 24px;
				/* 字体大小 */
				font-weight: bold;
				/* 字体加粗 */
				color: #333;
				/* 字体颜色 */
				z-index: 10;
				/* 确保得分在其他元素之上 */
			}

			.rooster {
				width: 200px;
				/* 公鸡图片宽度 */
				position: absolute;
				animation: moveRooster 4s linear infinite;
				/* 添加动画 */
			}

			@keyframes moveRooster {
				0% {
					left: 0;
					/* 起始位置在左边 */
				}

				100% {
					left: 100%;
					/* 结束位置在右边 */
				}
			}

			.ball {
				margin-top: 450px;
				/* 与公鸡图片的距离 */
				display: flex;
				justify-content: center;
				/* 居中对齐 */
				width: 100%;
				/* 容器宽度 */
				cursor: pointer;
				/* 鼠标悬停时显示手形光标 */
			}

			.ball img {
				width: 100px;
				/* 篮球图片宽度 */
				transition: transform 0.2s ease;
				/* 添加平滑过渡效果 */
			}
		</style>
	</head>
	<body>
		<div class="container">
			<div class="score" id="score">得分: 0</div> <!-- 得分显示 -->
			<img src="img/c.gif" class="rooster" id="rooster" />
			<div class="ball" id="basketball">
				<img src="img/篮球.png" alt="篮球" />
			</div>
		</div>

		<script>
			document.addEventListener('DOMContentLoaded', (event) => {
				const basketball = document.getElementById('basketball');
				const rooster = document.getElementById('rooster');
				const scoreDisplay = document.getElementById('score');
				let isBouncing = false;
				let score = 0; // 初始化得分

				// 添加事件监听器到整个文档
				document.addEventListener('click', (event) => {
					if (isBouncing) return; // 如果正在弹跳,阻止多次点击

					isBouncing = true; // 设置为正在弹跳状态

					// 获取篮球中心位置
					const ballRect = basketball.getBoundingClientRect();
					const ballCenterX = ballRect.left + ballRect.width / 2;
					const ballCenterY = ballRect.top + ballRect.height / 2;

					// 获取点击位置
					const clickX = event.clientX;
					const clickY = event.clientY;

					// 计算方向
					const deltaX = clickX - ballCenterX;
					const deltaY = clickY - ballCenterY;
					const angle = Math.atan2(deltaY, deltaX); // 计算角度

					// 计算移动的距离,修改这里可以调整飞出的高度和距离
					const distance = 420; // 向上飞出的距离
					const offsetX = Math.cos(angle) * distance; // X方向的位移
					const offsetY = Math.sin(angle) * distance; // Y方向的位移

					// 先让篮球向上飞出
					basketball.style.transition = 'transform 0.5s ease'; // 设置飞出时的过渡时间
					basketball.style.transform = `translate(${offsetX}px, ${-distance}px)`; // 向上和方向移动篮球

					// 在向上飞出后再添加向下的动画
					setTimeout(() => {
						basketball.style.transition = 'transform 0.7s ease'; // 设置掉落时的过渡时间
						basketball.style.transform = 'translate(0, 0)'; // 重置篮球位置
						basketball.style.transition = 'transform 0.2s ease'; // 短暂时间的上下拍动
						basketball.style.transform += ' translateY(-30px)'; // 向上拍动,增加拍动幅度

						// 检查篮球是否击中公鸡
						setTimeout(() => {
							const hit = isHit();
							console.log('Hit:', hit);
							if (hit) {
								score++; // 得分加1
								scoreDisplay.textContent = '得分: ' + score; // 更新得分显示
								explodeRooster(); // 处理公鸡爆炸效果
							}
							basketball.style.transform = 'translate(0)'; // 恢复到原始位置
							isBouncing = false; // 重置状态
							basketball.style.transition = 'transform 0.2s ease'; // 恢复过渡时间
						}, 200); // 给拍动效果一些时间后检测碰撞
					}, 500); // 向上移动的时间
				});

				// 检查篮球是否击中公鸡
				function isHit() {
					const roosterRect = rooster.getBoundingClientRect(); // 获取公鸡的矩形
					const ballRect = basketball.getBoundingClientRect(); // 获取篮球的矩形

					// 计算公鸡的中心点
					const roosterCenterX = roosterRect.left + roosterRect.width / 2;
					const roosterCenterY = roosterRect.top + roosterRect.height / 2;

					// 计算篮球的中心点
					const ballCenterX = ballRect.left + ballRect.width / 2;
					const ballCenterY = ballRect.top + ballRect.height / 2;

					// 计算两者的距离
					const distanceX = ballCenterX - roosterCenterX;
					const distanceY = ballCenterY - roosterCenterY;
					const distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY); // 计算两点之间的距离

					// 计算半径
					const ballRadius = ballRect.width / 2; // 取篮球宽度的一半作为半径
					const roosterRadius = Math.sqrt((roosterRect.width / 2) ** 2 + (roosterRect.height / 2) **
					2); // 取公鸡的对角线的一半作为半径

					// 设置额外的阈值,调整这个值来缩小范围
					const hitThreshold = 200; // 可以根据需要调整这个值

					// 碰撞检测条件,减去阈值
					const hit = distance < (ballRadius + roosterRadius - hitThreshold);

					// 打印碰撞检测结果
					console.log('Collision Detected:', hit);
					return hit;
				}


				// 公鸡爆炸效果
				function explodeRooster() {
					const originalSrc = rooster.src; // 保存原始公鸡图片的路径
					rooster.src = 'img/explosion.gif'; // 设置为爆炸GIF
					setTimeout(() => {
						rooster.src = originalSrc; // 还原公鸡图片
						rooster.style.animation = 'moveRooster 5s linear infinite'; // 恢复公鸡的动画
					}, 500); // 持续0.5秒
					rooster.style.animation = 'none'; // 暂停公鸡的动画
				}
			});
		</script>
	</body>
</html>
相关推荐
猫爪笔记3 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
爱上语文5 小时前
HTML和CSS 表单、表格练习
前端·css·html
惜.己5 小时前
Jmeter中的断言(二)
测试工具·jmeter·1024程序员节
小肚肚肚肚肚哦6 小时前
盘点浏览器盒模型中各种 width、height 、边距和位置属性
css·html
NightCyberpunk6 小时前
HTML、CSS
前端·css·html
南城FE6 小时前
12个更现代化的CSS单行优化技巧
前端·css
啵咿傲9 小时前
重绘&重排、CSS树&DOM树&渲染树、动画加速 ✅
前端·css
前端Hardy9 小时前
HTML&CSS:数据卡片可以这样设计
前端·javascript·css·3d·html
流烟默9 小时前
CSS中Flex布局应用实践总结
前端·css·flex布局
大G哥11 小时前
我用豆包MarsCode IDE 做了一个 CSS 权重小组件
前端·css