仿百度新闻首页

xiaoxiao2021-02-28  8

偶尔在网上看到百度新闻的效果很炫、就自己粗略的仿制一下效果、效果地址:http://news.baidu.com/n?cmd=1&class=reci#0

先说下思路:1、我们可以发现 里面所有的块是由一个个小的单元组成的、最大的总共两个 有四个小单元加间距组成  横着和竖着的是由两个小单元组成

2、这些大的单元 总数是固定的 (这些大的多了也会不怎么美观) 所有单元的位置都是随机的

3、当滚动鼠标的时候  所有单元的位置会再一次的随机分配、窗口大小改变的时候 会重新计算基本单元的 宽度  当点击导航的时候会重新加载数据

4、我设计的 每一排可放的 小单元的个数是可变的 (可选参数  默认为6个) 这里我们设计的 总共有四排 (这样做 主要是想 整个页面是一屏 不会出现滚动条是最好)

5、首先计算出 小单元的数量 (4*你传的个数) 然后根据 我们放这些 单元的盒子 的宽度  计算出单元的宽度 和 高度(默认为宽度的65%) 同事计算出总数的坐标(这里的坐标是以可以放多少个小单元的数量为准的 )

这里是关键  是后面怎么使用这些坐标  而且是随机的    我的思路如下(有更好的思路欢迎交流):

1、我是用两个对象 一个是保存单元总数的对象(包含每个坐标的信息)如下图:

一个是保存上面对象 key值得数据:

这个数组  主要是用来去随机数的  然后根据随机数 对应的值 去取上面对象里面的 值  ( 这个值就包含我们需要的 坐标)

2、第二点就是怎么取坐标值  因为我们要把我们的每一个单元 全部都放在 我们的盒子里面  而且刚好占满我们的 盒子 不多不少 当然也不能重叠、因此先放最小的肯定是不行的因为我们的位置是随机的,因此我们先把大一点的单元搞定  

3、我们每次在取坐标的时候  我们要判断(最小的单元就不需要了 随便放)这个单元的类型 然后它占的坐标全部从我们上面的辅助的数组中清空(这里注意:不能把这个位置删掉,还记得我们第一张图上面的index属性吗? 如果删掉就会找不到对应的值了 使用数组的splice方法把对应的值为空就可以了 后面 我们做一下判断 如果为空 就重新取值就好了)

基本上就是这三点核心 其它的我们来看代码吧(这个效果图不好放  大家有兴趣复制一下 看下效果):

html:

<div class="box"> <ul class="naver"> <li class="naver-l active">导航一</li> <li class="naver-l">导航二</li> <li class="naver-l">导航三</li> <li class="naver-l">导航四</li> <li class="naver-l">导航五</li> </ul> <div class="container" style="height: 500px"> </div> </div> css:

*{margin:0;padding:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;-o-box-sizing:border-box;-ms-box-sizing:border-box;box-sizing:border-box}body,html{width:100%;overflow-x:hidden;color:#4d4d4d;font:14px/1.5 "Helvetica Neue",Helvetica,Arial,"Microsoft Yahei","Hiragino Sans GB","Heiti SC","WenQuanYi Micro Hei",sans-serif}body{-webkit-tap-highlight-color:rgba(255,0,0,0.5);-webkit-font-smoothing:antialiased;background-color:#fff}a{text-decoration:none}img{display:block;width:100%;vertical-align:middle}ul,li{list-style:none}.box{width:80%;overflow:hidden;margin:20px auto}.naver{width:100%;height:60px;padding:1px}.naver .naver-l{float:left;height:100%;line-height:58px;margin:0 1px;padding:0px 15px;font-size:16px;font-family:500;cursor:pointer}.naver .naver-l:hover{background-color:#ccc}.naver .naver-l.active{background-color:pink}.container{width:100%;overflow:hidden;clear:both;position:relative;margin-top:20px}.c-item{position:absolute;overflow:hidden;-webkit-transition:all 1s;-o-transition:all 1s;-moz-transition:all 1s;transition:all 1s;cursor:pointer;font-size:24px}.c-item .item-m{font-size:18px;width:100%;height:100%;position:absolute;left:0px;top:-100%;background-color:#000;filter:Alpha(opacity=70);-moz-opacity:.7;opacity:.7;color:#fff;-webkit-transition:all .2s;-o-transition:all .2s;-moz-transition:all .2s;transition:all .2s}.c-item:hover .item-m{top:0px} /*# sourceMappingURL=nav-list.css.map */ javascript:

1、方法的调用:

new NavList({ container: document.querySelector(".container"),//放小单元的盒子 navigation: document.querySelectorAll(".naver-l"),//导航栏 adaptation: true,//是否自适应屏幕大小 line_num: 7,//每行显示的小单元个数 });2、方法的思路:首先:根据页面大小 创建我们所需要的 各种单元的集合对象 append 进入页面中 可以给一个初始的left and top (不然的话 后面 计算left top的时候 就没有动画效果了);其次就是为 改变每一单元的属性值了

3、javascript代码 (有点长  不好的地方希望多交流):

;(function(win,doc){ var NavList; NavList = (function(){ function NavList(options){ this._pNode = options['container'] || '',//盒子元素 this._adaptation = options['adaptation'] || true,//是否自适应 this._navigation = options['navigation'] || '', this._line_num = options['line_num'] || 6,//每一行展示 单元的数量 默认为四行 this._offset = 5,//单元之间的间距 this._minUnit = '',//储存最小单元的width height this._w_Unit = '',//储存 width*2的单元 this._h_Unit = '',//储存 height*2的单元 this._w_h_Unit = '',//储存 height*2 width*2 的单元 this._unit_obj = [],//储存所有单元的info this._unit_dom = [],//储存创建好的dom 元素 this._unit_pos = '',//储存每个小单元的坐标 this._pos_arr = [],//用于计算的每个小单元的坐标 this._pos_value = '',//创建dom节点的时候 获取到的每个坐标值 this._unit_pos_obj = '',//储存每个小单元的坐标 this._pNode_width = '',//盒子的宽度 this._count = 0, this.init();//页面初始化 } return NavList.prototype.init = function(){ var _pNode = this._pNode; if(!_pNode || _pNode.nodeType != 1 ) return false; if( this._adaptation ) { this.addEvent(win,"resize",this.pnodeResizeHandler,false); } if( !!this._navigation ){ Array.prototype.forEach.call(this._navigation,(item)=>{ this.addEvent(item,"click",this.navClickHandler,false); }) } this.addEvent(win,"mousewheel",this.mouseWheelHandler,false); /** * 功能页面初始化 如果是开发的话 我们也可以在初始化的时候加载数据 然后再初始化页面 */ this.dataInitHandler(); console.log("NavList 初始化完成"); }, NavList.prototype.showDomHandler = function(_obj,i){ if(!_obj) return false; this._unit_dom.push( this.singleDom( { "name": "div", "cl": _obj[i]['type'] == 'm' ? "c-item c-itme_m" : ( _obj[i]['type'] == 'w' ? "c-item c-itme_w" : (_obj[i]['type'] == 'h' ? "c-item c-itme_h" : "c-item c-itme_wh") ), "attr": { "style": `height: ${_obj[i]['height']}px;width: ${_obj[i]['width']}px;background-color: ${this.getColorHandler()};left: 45%;top: 0px;`, } } ) ) this._unit_dom[i].appendChild( this.singleDom( { "name": "span", "_html": "这是一个元素" + i } ) ) this._unit_dom[i].appendChild( this.singleDom( { "name": "div", "cl": "item-m", "_html": "这是一个元素" + i + "的子元素" } ) ) this._pNode.appendChild( this._unit_dom[i] ); }, NavList.prototype.randomSortHandler = function(_arr){ var _len = _arr.length,_random; if(_len == 0) return false; _random = parseInt( Math.random()*(_len-1) ); this._pos_arr.push( _arr[_random] ); _arr.splice(_random,1) arguments.callee.call(this,_arr); }, NavList.prototype.changePosHandler = function(_pos_arr){ /** * 在创建dom 之前对 this._unit_pos 坐标 和 this._unit_obj 进行随机排序 */ var _this = this; this._pos_arr = []; this.randomSortHandler(_pos_arr); this._pos_arr.forEach( function(item,index){ _this._unit_pos_obj[item]['index'] = index; } ) }, NavList.prototype.createDomHandler = function(_pos_arr){ var _obj = this._unit_obj,_this = this; this.changePosHandler(_pos_arr); for(let i=0,len=_obj.length;i<len;i++){ this.showDomHandler(_obj,i); } setTimeout(()=>{ try { this.changeUnitHandler(this); } catch(e) { alert("哎呀 发生错误了 我要重新加载数据了"); this.dataInitHandler(); } }, 25) }, NavList.prototype.dataInitHandler = function(){ this._pNode.innerHTML = ''; this._unit_dom = []; this._unit_pos = []; this._unit_obj = []; /** * 获取 页面的width * * 计算 我们空间内可以放的 色块的个数 * * 调整 我们的距离 width */ var _pNode = this._pNode,_pNode_width = _pNode.offsetWidth,_single_w = _pNode_width/this._line_num - this._offset; this._minUnit = { type: "m", width: parseInt(_single_w), height: parseInt((_single_w*0.65)), } /** * 基础单元出来之后 获取所有类型的单元 */ this._w_Unit = { type: "w", width: this._minUnit['width']*2 + this._offset, height: this._minUnit['height'] } this._h_Unit = { type: "h", width: this._minUnit['width'], height: this._minUnit['height']*2 + this._offset } this._w_h_Unit = { type: "wh", width: this._minUnit['width']*2 + this._offset, height: this._minUnit['height']*2 + this._offset } /** * 我们这里默认的是四行 可以传参数 但是不能低于四行 总共 this._line_num * 4 个小单元 * * 减去 2*4 - 6*2 剩下的小单元为 this._line_num * 4 - 20; */ var _unc = this._line_num * 4 - 2*4 - 6*2; for(let i=0;i<4;i++){ if( i < 2 ){ this._unit_obj.push( this._w_h_Unit ); this._unit_obj.push( this._w_Unit ); } this._unit_obj.push( this._h_Unit ); } while(_unc--){ this._unit_obj.push( this._minUnit ); } // console.log(this._unit_obj); /** * 所有单元出来之后 先获得我们所有的坐标点 然后创建dom结构 */ this.getPositionHandler(); var _arr = this._unit_pos,_pos_arr = []; for(let i=0,len=_arr.length;i<len;i++){ _pos_arr[i] = _arr[i]; } this.createDomHandler(_pos_arr); // console.log(this._w_h_Unit); }, NavList.prototype.getPositionHandler = function(){ var _num = this._line_num,_obj = {},_left,_top = this._offset,_line = '0',_arr = [],_index = 0;//默认的为4行 for(let i = 1; i<= 4; i++){ _line = i + ''; _left = 0; _top = (this._offset + this._minUnit['height'])*(i-1); for(let j=0;j<_num;j++){ _left = ( this._minUnit['width'] + this._offset )*j; _arr.push(_line+_left); _obj[_line+_left] = {"left": _left,"top": _top,"index": _index++,"_line": _line};//保存每一个坐标 } } this._unit_pos_obj = _obj; this._unit_pos = _arr; console.log(_arr); // console.log(_obj); }, NavList.prototype.pnodeResizeHandler = function(_this,el){ clearTimeout(_this._resize_timer); _this._resize_timer = setTimeout(function(){ _this.dataInitHandler(); }, 200) }, NavList.prototype.changeUnitHandler = function(_this,type){ /** * type = true 则改变 小单元的值 */ var _c_items = _this._pNode.querySelectorAll(".c-item"),_arr = _this._unit_pos,_pos_arr = []; _this._count = 0; for(let i=0,len=_arr.length;i<len;i++){ _pos_arr[i] = _arr[i]; } _this.changePosHandler(_pos_arr); Array.prototype.forEach.call(_c_items,function(item,index){ _this.getRandomHandler( _this._unit_obj[index]['type'] ); item.style.top = _this._pos_value['top'] + "px"; item.style.left = _this._pos_value['left'] + "px"; }) }, NavList.prototype.mouseWheelHandler = function(_this,el){ /** * 打乱 单元的位置 */ try { _this.changeUnitHandler(_this); } catch(e) { alert("哎呀 发生错误了 我要重新加载数据了"); _this.dataInitHandler(); } }, NavList.prototype.navClickHandler = function(_this,el){ var _cl_name = el.className; if(_cl_name.indexOf("active") != -1) return false; el.parentNode.querySelector(".active").className = _cl_name; _cl_name += " active"; el.className = _cl_name; /** * 这里改变 单元的值 同时重新 计算坐标 */ _this.dataInitHandler(); }, NavList.prototype.getRandomHandler = function(_type){ var _len = this._pos_arr.length,_obj3,_obj1,_obj2,_random,_pos,_index3,_index1,_index2; if(!_len) return false; _random = this._count++; if(this._count == _len){ this._count = 0; } /** * 在这里 我们要判断 以下几点 * * 1、this._pos_arr[_random] 不能为空 */ _pos = this._pos_arr[_random]; if(!_pos){ arguments.callee.call(this,_type); return false; } _pos = this._unit_pos_obj[_pos];//获取到当前值 /** * 解决 双层高的 不会跑到最下面 */ if( _type == "h" || _type == "wh"){ if(_pos['_line'] == "4"){ arguments.callee.call(this,_type); return false; } } /** * 2、判断 _type 同事判断 改坐标点的 后一个 下一个 对角的 坐标是否 都是存在的 有一个不存在 就重新取值 * */ _obj1 = this._unit_pos_obj[_pos['_line'] + (_pos['left'] + this._minUnit['width'] + this._offset)]; _obj2 = this._unit_pos_obj[parseInt(_pos['_line']) + 1 + '' + _pos['left']]; _obj3 = this._unit_pos_obj[parseInt(_pos['_line']) + 1 + '' + (_pos['left'] + this._minUnit['width'] + this._offset)]; if( _type == "w"){ if(!_obj1){ arguments.callee.call(this,_type); return false; }else{ _index1 = _obj1['index'];//这个其实是不准确的 if(!this._pos_arr[_index1]){ arguments.callee.call(this,_type); return false; }else{ this._pos_arr.splice(_index1,1,''); } } } if(_type == "h"){ if(!_obj2){ arguments.callee.call(this,_type); return false; }else{ _index2 = _obj2['index']; if(!this._pos_arr[_index2]){ arguments.callee.call(this,_type); return false; }else{ this._pos_arr.splice(_index2,1,''); } } } if(_type == "wh"){ if(!_obj1 || !_obj2 || !_obj3){ arguments.callee.call(this,_type); return false; }else{ _index1 = _obj1['index']; _index2 = _obj2['index']; _index3 = _obj3['index']; if(!this._pos_arr[_index1] || !this._pos_arr[_index2] || !this._pos_arr[_index3]){ arguments.callee.call(this,_type); return false; }else{ this._pos_arr.splice(_index3,1,''); this._pos_arr.splice(_index2,1,''); this._pos_arr.splice(_index1,1,''); } } } this._pos_arr.splice(_random,1,''); this._pos_value = _pos; }, NavList.prototype.getColorHandler = function(){ return "#" + parseInt( Math.random()*16 ).toString(16) + parseInt( Math.random()*16 ).toString(16) + parseInt( Math.random()*16 ).toString(16); }, NavList.prototype.singleDom = function(options){ /** * name 必填 否则报错 */ var el,attr = options["attr"],type = options["type"],init = options["init"]; if(!options || !options["name"]) throw new Error("options is error"); el = doc.createElement(options["name"]); el.className = options["cl"] || ''; el.innerHTML = options["_html"] || ''; if(attr){ // attr.forEach(function(item,index){ // el.setAttribute(item["key"], item["value"]); // }) for(var key in attr){ el.setAttribute(key,attr[key]); } } if(type){ this.addEvent(el,type,options["handler"],false); } return el; }, NavList.prototype.addEvent = function(el, eType, handle, bol){ console.log(el); if(el.addEventListener){ //如果支持addEventListener el.addEventListener(eType, handle.bind(null,this,el), bol); }else if(el.attachEvent){ //如果支持attachEvent el.attachEvent("on"+eType, handle.bind(null,this,el)); }else{ //否则使用兼容的onclick绑定 el["on"+eType] = handle.bind(null,this,el); } }, NavList; })(), win.NavList = NavList; })(window,document)

转载请注明原文地址: https://www.6miu.com/read-1100207.html

最新回复(0)