前言
滚动条作为网页开发中常见的元素,承担了重要的作用,使连续的文本、图片或任何其他内容可以在计算机显示器、窗口或视窗上按预定的方向(上、下、左或右)滚动,以便所有内容都可以查看。
滚动条的作用不容小觑,那么除此之外它还能实现哪些好玩的事情呢?用它做一个小游戏怎么样。
先来看看成品吧:
代码片段
原理
用户使用某种直接操作的方法与滚动条元素交互,滚动条将操作转换为滚动命令,用户通过滚动条元素和滚动内容的可视化更新接收反馈。那么我们就可以尝试将滚动条的变化体现在元素上,比如使用滚动条控制元素移动。就像这样:
当文档内容的宽高大于可视区域时,在该区域中就会出现滚动条,例如:
<style>
.control {
position: absolute;
bottom: 0px;
left: 0px;
width: 100px;
overflow-x: scroll;
overflow-y: hidden;
}
.control div {
width: 1000px;
height: 1px;
}
</style>
<div class="control"><div></div></div>
在用户与滚动条做交互时会触发 onscroll
事件,在事件中使用元素的 transform
属性改变目标的位置就可以打到上面图示上的不停的拖动滚动条来改变元素位置的效果了。
代码示例:
<script>
const player = document.getElementsByClassName('player')[0]
const control = document.getElementsByClassName('control')[0]
let position = 0
control.onscroll = function () {
position += 1
if (position > 100) {
player.style.transform = `translate(${200 - position}px, 0px)`
} else {
player.style.transform = `translate(${position}px, 0px)`
}
position === 200 ? (position = 0) : null
}
</script>
完整的示例可以在码上掘金上查看:
代码片段
实现
运动员的实现,运动员由三个部分组成,头部,胳膊,以及水花组成。头部与身体部分,块级元素相对较少,利用元素的伪元素,进行布局即可实现。由图可见,水花部分由多个div组成,每个div的位置与大小都不同,需要一一设置,这里使用 div:nth-of-type(1)
进行元素选取。
单个运动员有些无聊了,不妨多加几个,然后为他们分别设置一个能力值,当然是随机的,然后让他们的游泳速度跟能力值成正比,看他们谁游的快。
每隔3s中重新初始化运动员的能力,毕竟有的人前期猛后面就不行了,有的人是潜力股。
为运动员分配随机值
const polePosition = document.getElementById('polePosition')
const world = document.getElementById('world')
const players = document.getElementsByClassName('player')
console.log([...players])
let position = 0
let frame = null
let playersAblility = [] // 运动员的能力
let timer = null // 计时器
function random(min, max) {
return Math.floor(Math.random() * (max - min)) + min
}
// 初始化运动员能力
function setPlayerAbility() {
playersAblility = []
for (let player of players) {
const offset = random(1, 100)
playersAblility.push(offset)
}
}
setPlayerAbility()
// 计时器
function setTimer() {
if (!timer) {
timer = setInterval(() => {
// 分配运动员体力
setPlayerAbility()
}, 3000)
}
}
setTimer()
传入位置,控制运动员运动。
// 游泳
function setPlayerSwim(position) {
const list = [...players]
list.forEach((player, index) => {
const offset = playersAblility[index]
const translate = `translate(${position + offset}px,0)`
player.style.transform = translate
player.setAttribute('data-position', position + offset)
})
}
使用 requestAnimationFrame
api 使页面动起来。在这个方法中,需要使赛道跟随运动员动起来。
// 谁是第一
function whoIsFirst() {
const list = [...players]
.map(v => {
return v.getAttribute('data-position')
})
.sort((a, b) => b - a)
return list[0]
}
// loop
function loop() {
const firstPosition = whoIsFirst() || 25
console.log(firstPosition)
if (firstPosition > 2430 - 25) {
timer = null
return
}
position += 1
setPlayerSwim(position)
polePosition.style.transform = `translate(${firstPosition}px, 0px)` // 第一的位置
world.style.transform = `translate(-${position}px, 0px)`
frame = window.requestAnimationFrame(loop)
}
// 开始按钮
const startBtn = document.getElementById('startBtn')
startBtn.onclick = () => {
if (!frame) {
loop()
}
}
总结
学习需要尝试一些新的东西,多做尝试,在平常不起眼的元素中发掘不一样的玩法。