用贪吃蛇小游戏的思路手写一个无限循环滚动轮播图

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用贪吃蛇小游戏的思路手写一个无限循环滚动轮播图相关的知识,希望对你有一定的参考价值。

在某些业务场景下,接入第三方库实现轮播图效果可能并没有那么好用,笔者在接入Swiper插件失败后,还是决定手写一个。那么关于手写轮播图有很多文章已经讲过了,其核心原理是将图片排成一排,设置外层的Div超出隐藏,然后改变定位来实现轮播效果,这样通常不能首尾循环滚动,本文记录了一种对无限循环滚动效果的实现方式。

实现的思路很简单,就是和“贪吃蛇”游戏中蛇身体的移动逻辑一样,每次前进的时候先删除尾部元素,然后再添加到头部,这样无论身体多庞大,始终只有两个元素在改变位置:

用贪吃蛇小游戏的思路手写一个无限循环滚动轮播图_前端

基础效果

有了思路,就不难写出轮播了,这里为了方便使用Vue2创建演示,后面会放上完整Demo及源码,文章只讲思路,就不贴大段代码了,有需要的小伙伴可以先点个收藏~

其中前进还是一样通过改变​​left​​来滚动,只是在滚动结束后便立刻修改数据:

// 核心代码
const ulDom = document.getElementsByClassName(ul)[0] // 拿到页面Dom实例
ulDom.style.left = xxx // 控制滚动,注意需要设置transition才有动画

this.images.push(this.images.shift()) // 对轮播列表的数组首尾元素互换

用贪吃蛇小游戏的思路手写一个无限循环滚动轮播图_CSS_02

但是回退就有点不一样了,试想如果此时在第一张图,那么向左跳转的话是没有数据的,也就会产生空白的一片,所以回退做了特殊处理,先把尾部添加到数组前面,同时悄悄地轮播到下一张(去除动画效果),然后才进行回退的操作,等动画结束后​​pop()​​把数组末尾删除:

用贪吃蛇小游戏的思路手写一个无限循环滚动轮播图_数组_03

从页面效果上可能没什么感觉,我们放慢来看看​​DOM​​是如何变化的:

用贪吃蛇小游戏的思路手写一个无限循环滚动轮播图_数据_04

列表虚拟化

可能大家也注意到了,在这个实例中“当前选中”下标是要另外计算的,因为真实的数组下标总是在来回加1减1地改变而已,所以我们可以在此基础上轻松做出一个虚拟列表,做到真正的“无限”滚动。

假设轮播数组足够大,且页面结构又繁多复杂情况下,直接渲染轮播会产生很多DOM结构,这将导致页面性能下降,下面放上完整在线代码演示,你可以修改“列表总数”为​​9999​​,然后关闭虚拟列表开关,此时你可能会卡到根本点不动轮播:

一般来说可能不会有大量轮播图的场景,笔者的业务需求是在数据大屏中展示海报视频等轮播,而数据量是没有上限的,就可能会出现大量轮播数据的请求。

此时根据“展示个数”动态的修改实际渲染的DOM个数,无论来多少张轮播都不会影响到性能了,利用Vue的计算属性可以很轻松地做到:

computed: 
realImages()
return this.images.slice(0, Number(this.slidesPerView) + 2)
// this.slidesPerView 即为展示个数,轮播图实际渲染个数总长度只会比展示个数多两个

图片加载闪动

这是后续的一个优化点,由于数据截取的原因,我会一直改变渲染的数组,在页面中的表现为图片突然更换了地址,如果该元素节点存在上一张图片,则会产生闪动:

如下图,可以看到我停留在第10张时啥也没做,但由于新的图片url其实还在加载,等到加载完了显示出来,图片突然闪动变化,体验就非常怪。

用贪吃蛇小游戏的思路手写一个无限循环滚动轮播图_JavaScript_05

于是我重新写了一个图片容器组件来代替​​img​​​标签,组件在img上层覆盖上一个loading遮罩,利用img标签的​​onLoad​​事件来判断图片加载完成,再隐藏loading,每次src改变的时候就重新出现loading,代码实现非常简单:

<template>
<div class="img__box">
<div v-show="loading" class="load"></div>
<img v-show="!loading" :src="src" @load="loadDone"
</div>
</template>

<script>export default
props:
src: ,
,
data()
return
loading: false,

,
watch:
src()
this.loading = true
,
,
methods:
loadDone()
this.loading = false</script>

<style scoped>.img__box
position: relative;
overflow: hidden;

.img__box > img
display: block;
width: 100%;
height: 100%;
object-fit: cover;

.load
position: absolute;
width: 100%;
height: 100%;

.load::after
position: absolute;
content: ;
top: 50%;
left: 50%;
width: 30px;
margin-left: -15px;
height: 30px;
margin-top: -15px;
border: 2px solid rgba(255, 255, 255, 0.7);
border-top-color: transparent;
border-radius: 100%;
animation: circle infinite 0.75s linear;


@keyframes circle
0%
transform: rotate(0);

100%
transform: rotate(360deg);


</style>

这样把轮播的​​img​​标签直接替换为这个组件就解决问题了:

用贪吃蛇小游戏的思路手写一个无限循环滚动轮播图_数组_06

最后附上:完整的Demo源码

以上是关于用贪吃蛇小游戏的思路手写一个无限循环滚动轮播图的主要内容,如果未能解决你的问题,请参考以下文章

vue慕课网音乐项目手记:5-手写滚动轮播图(上)

js原生选项(包含无缝滚动轮播图)一

用C语言编写 贪吃蛇的思路啥怎么样的

C语言零基础项目:贪吃蛇!详细思路+源码分享

使用lua语言制作贪吃蛇游戏(love2d)蛇对象的设计

C语言实现《贪吃蛇》小游戏,代码分享+思路注释