本文详细讲解如何使用原生JavaScript实现图片轮播效果,涵盖HTML结构、CSS样式控制及JS逻辑实现。同时分享了前端初学者从HTML5到JavaScript的学习路径,针对学习过程中遇到的迷茫期提供实用建议,强调通过动手实践和巩固基础来建立前端知识体系。
前端学习心得与规划
开发过程中频繁听到对各类插件的依赖请求。虽然引入第三方插件能显著提升开发效率,但作为初学者,笔者更倾向于自主实现功能,主要原因在于拥有充足的学习时间。
原生JS轮播实现教程
本文将分享使用原生JavaScript编写图片轮播组件的具体方法。
经验丰富的开发者可跳过以下个人经验分享部分。
在正式进入技术细节前,先总结自接触前端以来约两个月的学习体会。目前每天保持6至10小时的学习投入,完全依靠自学。尽管外界有观点认为培训效果有限,但笔者目前仅掌握HTML5、CSS3和JavaScript这三大基础技术,其他知识模块均列入后续学习计划。当前处于方向迷茫期,不确定下一步的学习重点,因此决定先扎实掌握这三大基础技术,恳请资深前辈给予指导建议。
从HTML5到CSS3,一路过来,感觉前端挺简单的,就有点信心满满,动力十足,接着学JS,以前学过C#、苹果的swift,都是面向对象的强类型的语言,比较先进,不过我还是喜欢前端,所以转到这里来了,开始学JS也觉得挺容易的,就是感觉这门语言有点乱,跟别人不太一样!而权威指南有些东西不容易弄明白,没办法,就多百度,多看别人对一些比如闭包、原型等概念的理解,慢慢的也就能掌握的7788了,到了这个阶段,你也许已经慢慢的了解到,原来前端它包括很多东西!一堆的第三方类库、框架等等,还有很多其它东西,总之,新名词不断的在你眼前冒出来,有的说这个要过时了,那个即将是主流,好乱!好乱!接下去我该怎么走?先学什么?后学什么?
笔者当前正经历这一迷茫阶段,有时连续两天无法专注学习,甚至影响睡眠,感到心烦意乱,仿佛陷入“走火入魔”的状态。
反思当前状态,试图理清原因未果。于是决定暂时休息,通过跑步和散步来调整身心状态,思考如何重新进入高效学习模式。
最终的解决策略是:通过完成一些简单的实例来重建信心(即“给自己点糖吃”)。
实践发现,这种策略效果显著。成功完成简单实例带来了强烈的成就感,从而恢复了学习动力。通过逐个实例的编写,遇到不懂之处或API不熟悉时,先查阅官方文档,在参考他人代码前先尝试独立编写,实在无法解决再寻求外部帮助。逐步地,笔者感觉重新找回了状态,学习步入正轨。
此外,笔者调研了当前大多数招聘前端岗位的公司对人才的需求,据此重新制定了学习计划。鉴于目前时间充裕,计划先集中一段时间巩固HTML、CSS和JavaScript这三大基础,通过大量练习加深理解,随后再系统回顾文档,深入探究其底层原理。这样无论后续学习何种新技术,都能更快上手。同时,持续了解前端技术发展趋势及职业前景,旨在构建完整的前端知识世界观,以避免在学习过程中迷失方向。
关于具体应学习哪些第三方类库或框架,目前尚不明确。例如jQuery是否已过时、是否需要学习等问题,暂且搁置,优先专注于原生JavaScript的实践,未来自然会清晰。
接下来进入实战环节,展示相关代码及演示效果。
对于面向对象的高级写法,笔者目前尚无法掌握,仅能编写函数式代码。图片素材来源于网络,也可自行制作300x200像素的图片进行测试,点击“渐进渐出”按钮即可启动效果。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
list-style: none;
text-decoration: none;
}
#slide{
position: absolute;
top: 100px;
left: 50px;
width: 300px;
height: 200px;
border: 1px solid gray;
}
#slide .blog-name{
display: block;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 25px;
line-height: 25px;
background-color: rgba(155,155,155,0.5);
z-index: 4;
cursor: pointer;
text-indent: 3px;
}
#slide-nav{
position: absolute;
right: 5px;
bottom: 5px;
z-index: 5;
}
#slide-nav li{
display: inline-block;
width: 16px;
text-align: center;
line-height: 16px;
border-radius: 5px;
cursor: pointer;
overflow:hidden;
}
#slide-nav li:hover,.selected{
background-color: #336699;
color: white;
}
.slide-content1{
position: absolute;
width: 300px;
height: 200px;
font-size: 0;
}
.slide-content1 a{
position: absolute;
cursor: pointer;
}
.slide-content1 a:visited{color: black;}
#model-btn{
position: absolute;
top: -25px;
font-size: 20px;
}
</style>
<script>
window.onload = function(){
var sufuImageScrooller = function(){
//几个工具函数
function show(img){
var id;
for ( var i = 0; i <= 21; i++) {
var op = i * 5;
id = setTimeout(function(e) {
setOpacity(img, e)
}.bind(this,op), i * 50);
}
clearTimeout(id);
}
function hide(img){
var id;
for ( var i = 0; i <= 21; i++) {
var op = 100 - i * 5;
id = setTimeout(function(e) {
setOpacity(img, e)
}.bind(this,op), i * 20);
}
clearTimeout(id);
}
function getById(id){
return document.getElementById(id);
}
function setOpacity(elem,level){
if(elem.filter){
elem.style.filter = "alpha(opacity=" + level + ")"; //兼容IE
}else{
elem.style.opacity = level/100;
}
}
//(渐进渐出模式)主体函数
function inOutModel(nums,navId,imgContainerId,imgInfoId,delay){
//防止多次点击模式选择按钮创建更多的li
if(getById('slide-nav').childElementCount !== 0){return}
//创建导航按钮
var nav = [];
var targetIdext = 0; //保存图片状态信息
var cureentIdext = 0; //保存图片状态信息
var frag = document.createDocumentFragment();
for(var i=0;i<nums;i++){
nav[i] = frag.appendChild(document.createElement('li')); //appendChild方法会返回该li
nav[i].innerHTML = i+1;
}
getById(navId).appendChild(frag);
//初始化为显示第一张图片
var imgs = getById(imgContainerId).getElementsByTagName('a');
var info = getById(imgInfoId);
info.innerHTML = imgs[0].title.slice(0,12)+'...';
nav[0].className = 'selected'; //动态改变li的className来改变它的样式
for(var j=1;j<nav.length;j++){
setOpacity(imgs[j],0);
}
//开始自动轮播
var id;
function start(delay){
id = setInterval(function(){
hide(imgs[cureentIdext]);
nav[cureentIdext].className = '';
if(targetIdext<nums-1){
targetIdext ++;
}else{
targetIdext = 0;
}
cureentIdext = targetIdext;
show(imgs[targetIdext]);
nav[targetIdext].className = 'selected';
info.innerHTML = imgs[targetIdext].title.slice(0,12)+'...';
},delay);
}
start(delay);
//为每个导航按钮添加事件
for(var k=0;k<nav.length;k++){
nav[k].onclick = function(event){
var e = event||window.event; //兼容IE
var t = event.target||event.srcElement; //兼容IE
var idex = parseInt(t.innerHTML)-1;
console.log('idex:'+idex+' t:'+targetIdext+' c:'+cureentIdext);
if(idex === cureentIdext){return;}
hide(imgs[cureentIdext]);
nav[cureentIdext].className = '';
cureentIdext = idex;
show(imgs[idex]);
nav[idex].className = 'selected';
info.innerHTML = imgs[idex].title.slice(0,12)+'...';
}
}
getById(navId).onmouseover = function(){clearInterval(id)};
getById(navId).onmouseout = function(){start(delay)};
}
//从右向左模式函数
function fromRightModel(nums,navId,imgContainerId,imgInfoId,delay){
alert('博主偷懒,忘记实现这个函数了!需要请留言!');
}
function fromTopModel(nums,navId,imgContainerId,imgInfoId,delay){
alert('博主偷懒,忘记实现这个函数了!需要请留言!');
}
return {
inOutModel: inOutModel,
fromRightModel: fromRightModel,
fromTopModel: fromTopModel,
getById: getById
}
}();
sufuImageScrooller.getById('model-btn1').onclick = function(){
sufuImageScrooller.inOutModel(5,'slide-nav','slide-main','slide-info',3500);
};
sufuImageScrooller.getById('model-btn2').onclick = function(){
sufuImageScrooller.fromRightModel(5,'slide-nav','slide-main','slide-info',3500);
};
sufuImageScrooller.getById('model-btn3').onclick = function(){
sufuImageScrooller.fromTopModel(5,'slide-nav','slide-main','slide-info',3500);
};
};
</script>
</head>
<body>
<div id="slide">
<a id="slide-info" class="blog-name" href="http://www.cnblogs.com/susufufu/" target="_blank">苏福的博客</a>
<ul id="slide-nav">
</ul>
<div id="slide-main" class="slide-content1 slide-content2">
<a class="a-img" title="用原生JS读写CSS样式的方法总结" href="http://www.cnblogs.com/susufufu/p/5749922.html" target="_blank">
<div>
<img src="https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=1247027539,1217965501&fm=21&gp=0.jpg">
</div>
</a>
<a class="a-img" title="DOM中的事件处理概览与原理" href="http://www.cnblogs.com/susufufu/p/5768431.html" target="_blank">
<div>
<img src="https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=4286855119,2694540617&fm=21&gp=0.jpg">
</div>
</a>
<a class="a-img" title="选取文档元素的方法总结" href="http://www.cnblogs.com/susufufu/p/5738673.html" target="_blank">
<div>
<img src="https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=4042865154,1782505495&fm=21&gp=0.jpg">
</div>
</a>
<a class="a-img" title="窗口、窗体之间的关系" href="http://www.cnblogs.com/susufufu/p/5714020.html" target="_blank">
<div>
<img src="https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2603911195,1920098549&fm=21&gp=0.jpg">
</div>
</a>
<a class="a-img" title="你真的知道setTimeout是如何运行的吗?" href="http://www.cnblogs.com/susufufu/p/5759480.html" target="_blank">
<div>
<img src="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=4104312586,1589909074&fm=21&gp=0.jpg">
</div>
</a>
</div>
<div id="model-btn">
<input type="button" id="model-btn1" value="渐进渐出">
<input type="button" id="model-btn2" value="从右向左">
<input type="button" id="model-btn3" value="从上至下">
</div>
</div>
</body>
</html>
实现思路主要利用定时器控制图片切换,并通过改变图片的opacity属性来实现过渡动画效果。
HTML结构设计
一、HTML结构较为简单:
<ul id="slide-nav">
</ul>
<div id="slide-main" class="slide-content1">
<a class="a-img" title="" href="" target="_blank">
<div>
<img src="lg1.png">
</div>
</a>
...
</div>
...
其中,slide-info用于显示图片标题,slide-nav为数字导航按钮容器,slide-main为图片容器,内部存放图片链接。
注意,HTML标签中未预先编写li元素,因为这些列表项是通过JavaScript动态创建的。
CSS样式关键点
二、CSS样式设置方面,通过亲自实践即可理解,需注意以下几点:
在自定义布局前,建议先为父元素添加边框(border),以便清晰观察布局结构,确认无误后再移除边框。
ul、li等标签默认带有padding值,因此需将其设置为0以消除默认间距。
*{ margin: 0; padding: 0; list-style: none; text-decoration: none; }
height: 25px;和line-height: 25px;两个相等,可以让字居中
z-index属性仅对兄弟元素及子元素生效,对非直接关联的元素无效。若需将某元素置于其他元素前方,需调整其祖先元素的层级,例如,若你的父辈地位高于旁系亲属的父辈,则你的层级自然高于旁系亲属。
position: absolute;属性的定位参照物是其最近的已定位祖先元素。若父元素未设置定位,则需继续向上查找,直至找到设置了定位属性的祖先元素为止。
若需实现从右向左的轮播效果,需注意设置font-size: 0;以清除图片间的空白间距,使图片紧密排列。
俗话说熟能生巧,只有CSS基础扎实,才能精准把控布局。例如双飞翼布局,无需定位即可实现。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
body{
margin: 0;
padding: 0;
}
.header,.footer{
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
background-color: greenyellow;
}
.container{
overflow: hidden;
*zoom: 1;
}
.left{
float: left;
width: 100px;
height: 100px;
margin-left: -100%;
background-color: green;
}
.main{
float: left;
width: 100%;
height: 100px;
background-color: gray;
}
.right{
float: left;
width: 200px;
height: 100px;
margin-left: -200px;
background-color: gold;
}
.center{
padding-left: 100px;
padding-right: 200px;
}
</style>
</head>
<body>
<div class="header">header</div>
<div class="container">
<div class="main">
<div class="center">main-center</div>
</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
<div class="footer">footer</div>
</body>
</html>
JavaScript代码实现
三、代码实现部分
首先编写代码大纲:
var sufuImageScrooller = function(){
function getById(id){...} //通用获取元素对象
function setOpacity(elem,level){...} //设置透明度
function hide(img){...} //淡入
function show(omg){...} //淡出
function inOutModel(nums,navId,imgContainerId,imgInfoId,delay){ ... } //主函数体
return {
inOutModel: inOutModel,
...
}
}();
通过sufuImageScrooller对象调用inOutModel方法即可实现功能,调用示例为:sufuImageScrooller.inOutModel(5,'slide-nav','slide-main','slide-info',3500);。参数说明如下:nums指定创建的li数量,必须与图片数量一致;navId为数字按钮容器的id;imgContainerId为图片容器的id;imgInfoId为显示图片标题信息的id;delay指定切换图片的延迟时间(毫秒)。
大纲完成后,项目已完成大半,剩余部分为具体细节代码的实现。笔者代码编写能力有限,仅实现了基本功能,欢迎大家提出改进建议。从inOutModel函数入手,逐步深入细节,关键在于动手编写代码,仅阅读代码难以获得深刻体会。
介绍至此结束,如有疑问请多查阅文档API,也可在评论区留言咨询。
以上关于原生JavaScript实现轮播效果及前端学习心得的内容分享完毕,希望能对大家有所帮助,欢迎支持本站。