社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
页面特效的制作,特别需要HTML、CSS有固定的布局,所以说现在越来越流行组件开发的模式,就是用JS写一个类,当你实例化这个类的时候,页面上的效果布局也能自动完成。
new Carousel();
实例化后,页面中就有一个轮播图的布局结构,而且可以通过参数传递进去。
这个new里面封装了HTML、CSS、JS的业务逻辑。组件开发的规律就是所有按钮、小圆点、图片等等都是这个类(的实例的)属性,自己管理自己。
组件开发的好处就是在用的时候可以高度自定义,在new的时候应该能传入一个JSON参数进行配置,当你的JSON里面的属性改变的时候,我们的UI界面逻辑就要有响应的变化。
面向对象+设计模式组合各种类(通常是中介者模式),就是组件化开发。
本质思想,组件只考虑两个事情:
l 别人怎么控制我,要提供很多函数,这个函数可以改变我的状态。
l 我怎么给别人提供接口,比如轮播图被点击时,要提供一个click事件回调。
组件只需要对自己负责,至于别人怎么调用我的接口,在我提供的接口中做什么,自己不需要考虑。
特点:
组件都是可以单独测试的,所有组件都可以单独上树,进行测试。
DOM都是动态生成的,组件开发中,现在90%以上的,都是将DOM写在JS中,在“查看源代码”中看见的是空标签。
组件是嵌套的,往往大组件是小组件的中介者。
优点:
l 方便维护,功能易于插拔,很容易找出BUG的地方。
l 易于复用,比如我们做一个分页条组件,此时可以非常自由在其他项目使用。
组件开发是一个非常实用的技术,组件开发越来越火,催生了一些组件开发的框架:React、Vue、Angular等。
JS对象、DOM对象,JS对象的属性是DOM对象
用轮播图的面向对象举例,JS对象中有自己的参数属性(比如当前显示图片的编号、速度、间隔时间、宽度、高度),还DOM属性。
<script type="text/javascript" src="js/jquery-1.12.3.min.js"></script> <script type="text/javascript" src="js/Carousel.js"></script> <script type="text/javascript"> new Carousel({ "id" : "Carousel", "images" : [ {"picUrl" : "images/0.jpg", "link" : "http://www.iqianduan.cn"}, {"picUrl" : "images/1.jpg", "link" : "http://www.iqianduan.cn"}, {"picUrl" : "images/2.jpg", "link" : "http://www.iqianduan.cn"}, {"picUrl" : "images/3.jpg", "link" : "http://www.iqianduan.cn"}, {"picUrl" : "images/4.jpg", "link" : "http://www.iqianduan.cn"} ], "width" : 560, "height": 300, "speed" : 500, "interval" : 2000 }); </script>
CSS样式:carousel样式后面动态创建
#Carousel{ width: 560px; height: 300px; position: relative; overflow: hidden; } .leftBtn,.rightBtn{ position: absolute; top:50%; width: 30px; height: 30px; background-color: orange; } .leftBtn{left: 10px;} .rightBtn{right: 10px;} .circls{ position: absolute; bottom: 10px;left: 100px; list-style: none; } .circls li{ float: left; width: 20px; height: 20px; background-color: orange; margin-right: 10px; } .circls li.cur{background-color: red;}
(function(){ //强行暴露一个变量,一枝红杏出墙来 window.Carousel = Carousel; //轮播图类 function Carousel(JSON){ this.$dom = $("#" + JSON.id); //DOM元素 this.$imagesUl = null; this.$imagesUlLis = null; this.width = JSON.width; this.height = JSON.height; this.$leftBtn = null; this.$rightBtn = null; this.$circleOl = null; this.$circleLis = null; this.interval = JSON.interval; this.speed = JSON.speed; //滑动速度 this.idx = 0;//信号量 this.imagesURLArr = JSON.images;//图片地址数组 this.pictureLength = JSON.images.length;//图片长度 this.init(); this.bindEvent(); this.autoPlay(); //定时器 } //初始化DOM Carousel.prototype.init = function(){ //创建ul节点 this.$imagesUl = $("<ul></ul>"); this.$dom.append(this.$imagesUl); //创建li节点 for(var i = 0; i < this.pictureLength; i++) { $("<li><img src='"+this.imagesURLArr[i].picurl+"'/></li>") .appendTo(this.$imagesUl); }; //获得li元素引用 this.$imagesUlLis = this.$imagesUl.find("li"); //大盒子的布局 this.$dom.css({ "width" : this.width, "height" : this.height, "position" : "relative", "overflow" : "hidden" }); //猫腻,让所有li藏起来(left移动到显示区域外) this.$imagesUlLis.css({ "position" : "absolute", "left": this.width, "top": 0 }); //只显示第一张图 this.$imagesUlLis.eq(0).css("left",0); //创建按钮 this.$leftBtn = $("<a href='javascript:;' class='leftBtn'></a>"); this.$rightBtn = $("<a href='javascript:;' class='rightBtn'></a>"); this.$leftBtn.appendTo(this.$dom); this.$rightBtn.appendTo(this.$dom); //创建小圆点 this.$circleOl = $("<ol class='circls'></ol>"); this.$circleOl.appendTo(this.$dom); for (var i = 0; i < this.pictureLength; i++) { $("<li></li>").appendTo(this.$circleOl); }; //获得ol的li元素 this.$circleLis = this.$circleOl.find("li"); //加cur this.$circleLis.eq(0).addClass("cur"); } })();
事件监听方法:
Carousel.prototype.bindEvent = function(){ var self = this; //右边按钮的监听 this.$rightBtn.click(function(){ if(self.$imagesUlLis.is(":animated")) return; self.showNext(); }); //左边按钮的监听 this.$leftBtn.click(function(){ if(self.$imagesUlLis.is(":animated")) return; self.showPrev(); }); }
showNext() 显示下一张方法
//展示下一张 Carousel.prototype.showNext = function(){ this.$imagesUlLis.eq(this.idx).animate({"left" : -this.width},this.speed); this.idx++; if(this.idx > this.pictureLength - 1){ this.idx = 0; } this.$imagesUlLis.eq(this.idx).css("left",this.width).animate({"left" : 0},this.speed); //圆点的cur this.changeCirclesCur(); }
changeCirclesCur()小圆点方法
Carousel.prototype.changeCirclesCur = function(){ this.$circleLis.eq(this.idx).addClass("cur").siblings().removeClass("cur"); }
showPrev() 显示上一张方法
//展示上一张 Carousel.prototype.showPrev = function(){ this.$imagesUlLis.eq(this.idx).animate({"left" : this.width},this.speed); this.idx--; if(this.idx < 0){ this.idx = this.pictureLength - 1; } this.$imagesUlLis.eq(this.idx).css("left",-this.width).animate({"left" : 0},this.speed); //圆点的cur this.changeCirclesCur(); }
//自动轮播 Carousel.prototype.autoPlay = function(){ var self = this; this.timer = setInterval(function(){ self.showNext(); },this.interval); }
bindEvent()
Carousel.prototype.bindEvent = function(){ var self = this; //鼠标停表 this.$dom.mouseenter(function(){ clearInterval(self.timer); }); //离开开启 this.$dom.mouseleave(function(){ self.autoPlay(); }); //圆点的监听 this.$circleLis.click(function(){ self.show($(this).index()); }); }
//小圆点点击展示任意 Carousel.prototype.show = function(number){ var old = this.idx; //旧idx信号量 this.idx = number; //当前点击的信号量,改变全局 //判断 if(this.idx > old){ //从右到左 this.$imagesUlLis.eq(old).animate({"left" : -this.width},this.speed); this.$imagesUlLis.eq(this.idx).css("left",this.width).animate({"left" : 0},this.speed); }else if(this.idx < old){//从左到右 this.$imagesUlLis.eq(old).animate({"left" : this.width},this.speed); this.$imagesUlLis.eq(this.idx).css("left",-this.width).animate({"left" : 0},this.speed); } //圆点的cur this.changeCirclesCur(); }
俄罗斯方块一共有7种:S、Z、J、L、O、I、T
首先做两种图形:
// S 、Z 、J 、L 、O 、I 、T
var block_json = { "I":[ //I有2种方向 [ [0,1,0,0], [0,1,0,0], [0,1,0,0], [0,1,0,0] ], [ [0,0,0,0], [0,0,0,0], [1,1,1,1], [0,0,0,0] ] ], "L":[ //L有4种方向 [ [0,1,0,0], [0,1,0,0], [0,1,1,0], [0,0,0,0] ], [ [1,1,1,0], [1,0,0,0], [0,0,0,0], [0,0,0,0] ], [ [1,1,0,0], [0,1,0,0], [0,1,0,0], [0,0,0,0] ], [ [0,0,1,0], [1,1,1,0], [0,0,0,0], [0,0,0,0] ] ], "J":[//J有4种方向 [ [0,1,0,0], [0,1,0,0], [1,1,0,0], [0,0,0,0] ], [ [1,0,0,0], [1,1,1,0], [0,0,0,0], [0,0,0,0] ], [ [1,1,0,0], [1,0,0,0], [1,0,0,0], [0,0,0,0] ], [ [1,1,1,0], [0,0,1,0], [0,0,0,0], [0,0,0,0] ] ], "O":[ //O有1种方向 [ [1,1,0,0], [1,1,0,0], [0,0,0,0], [0,0,0,0] ] ], "Z":[ //Z有2种方向 [ [1,1,0,0], [0,1,1,0], [0,0,0,0], [0,0,0,0] ], [ [0,0,1,0], [0,1,1,0], [0,1,0,0], [0,0,0,0] ] ], "S":[ //S有2种方向 [ [0,1,1,0], [1,1,0,0], [0,0,0,0], [0,0,0,0] ], [ [0,1,0,0], [0,1,1,0], [0,0,1,0], [0,0,0,0] ] ], "T":[//T有4种方向 [ [1,1,1,0], [0,1,0,0], [0,0,0,0], [0,0,0,0] ], [ [0,1,0,0], [1,1,0,0], [0,1,0,0], [0,0,0,0] ], [ [0,1,0,0], [1,1,1,0], [0,0,0,0], [0,0,0,0] ], [ [0,1,0,0], [0,1,1,0], [0,1,0,0], [0,0,0,0] ] ] }
都是套路,和贪吃蛇没区别。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Document</title> <style type="text/css"> table{ margin:50px auto; } table,tr,td{border: 1px solid #000;border-collapse:collapse;} td{width: 18px;height: 18px;} </style> </head> <body> <div id="app"></div> </body> <script type="text/javascript" src="js/Game.js"></script> <script type="text/javascript" src="js/Block.js"></script> <script type="text/javascript"> var game = new Game() </script> </html>
循环创建12*20的table表格,原因:为了方块能居中。
(function(){ window.Game = function(){ this.init() } //20 * 12创建表格 Game.prototype.init = function(){ this.dom = document.createElement('table'); document.getElementById("app").appendChild(this.dom); var tr,td; //循环插入行 for(var i = 0;i < 20;i++){ tr = document.createElement('tr'); this.dom.appendChild(tr); for(var j = 0;j < 12;j++){ //循环插入列 td = document.createElement('td'); tr.appendChild(td); } } } })();
//如果别的类修改Game类的表格颜色,尽量提供一个方法给其他类调用,不要让其他类修改自己的属性 //设置table表格的颜色 Game.prototype.setClass = function(row, col, classname){ this.dom.getElementsByTagName('tr')[row].getElementsByTagName('td')[col].className = classname }
在index.html中写两个类:
.L{background: skyblue;}
.I{background: pink;}
(function(){ window.Block = function(){ //在所有的形状中,选择一个砖块形状 var arr = ["I","L","J"]; this.allType = arr[~~(Math.random() * arr.length)] console.log(this.allType) //自己所有的方向个数 this.allDirectionNumber = block_json[this.allType].length; //随意一个方向 this.direction = ~~(Math.random() * this.allDirectionNumber); //得到形状,马上渲染图形的而进行code码 this.code = block_json[this.allType][this.direction]; //4 * 4小方块的初始位置 this.row = 0; this.col = 4; //保证方块从中间出现 } })();
(function(){ window.Block = function(){ ... } //渲染砖块 Block.prototype.render = function(){ for(var i = 0; i < 4;i++){ for(var j = 0; j < 4;j++){ //显示4 * 4矩阵颜色,写class类 game.setClass(this.row + i, this.col + j, "gray"); if(this.code[i][j] == 1){ //如果4 * 4 二维数组编码中有1就渲染颜色,0就没色 game.setClass(this.row + i, this.col + j, this.allType) } } } } })();
别忘记在Game类中添加定时器并render block(渲染方块)
(function(){ window.Game = function(){ this.init(); this.start(); //实例化砖块类 this.block = new Block(); } Game.prototype.start = function(){ var self = this; setInterval(function(){ //渲染砖块 self.block.render(); },30); } })();
//砖块下落 Block.prototype.down = function(){ this.row++; } //清屏方法 Game.prototype.clearClass = function(){ for(var i = 0; i < 20;i++){ for(var j = 0; j < 12;j++){ game.setClass(i, j, ""); } } } Game.prototype.start = function(){ this.f = 0; var self = this; setInterval(function(){ self.f++; //清屏 self.clearClass() //渲染砖块 self.block.render(); //每间隔20帧下落 self.f % 20 == 0 && self.block.down(); },30); }
砖块就能下落了
Map地图类存储死亡的方块
(function(){ window.Map = function(){ this.code = [ [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0] ] } })()
用for循环更优雅的创建二维数组
this.code = (function(){ var arr = []; for(var i = 0;i < 20;i++){ arr.push([]); for(var j = 0;j < 12;j++){ arr[i].push(0) } } return arr; })();
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!