偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

【HTML5&CSS3進(jìn)階學(xué)習(xí)01】氣泡組件的實(shí)現(xiàn)

開發(fā) 前端
我們這里所謂氣泡組件是指列表型氣泡組件,這里就其dom實(shí)現(xiàn),css實(shí)現(xiàn),js實(shí)現(xiàn)做一個討論,最后對一些細(xì)節(jié)點(diǎn)做一些說明,希望對各位有用

氣泡組件在實(shí)際工作中非常普遍,無論是網(wǎng)頁中還是app中,比如:

我們這里所謂氣泡組件是指列表型氣泡組件,這里就其dom實(shí)現(xiàn),css實(shí)現(xiàn),js實(shí)現(xiàn)做一個討論,***對一些細(xì)節(jié)點(diǎn)做一些說明,希望對各位有用

小釵最近初學(xué)CSS,這里做一個專題,便于自身CSS提升,文章有不少問題與可優(yōu)化點(diǎn),請各位指導(dǎo)

組件分類

單由氣泡組件來說,他仍然屬于“彈出層”類組件,也就是說其會具有這些特性:

① 布局為脫離文檔流

② 可以具有mask蒙版,并且可配置點(diǎn)擊蒙版是否關(guān)閉的特性

③ 可選的特性有點(diǎn)擊瀏覽器回退關(guān)閉組件以及動畫的顯示與隱藏動畫特性

其中比較不同的是:

① 不是居中定位

② 具有一個箭頭標(biāo)識,并且可以設(shè)置再上或者在下

③ 因?yàn)榫哂屑^,而且這個箭頭是相對于一個元素的,一般意義上我們?nèi)蝿?wù)是相對某個按鈕,所以說具有一個triggerEL

所以單從這里論述來說,我們的組件名為BubbleLayer,其應(yīng)該繼承與一個通用的Layer

但是,就由Layer來說,其最少會具有以下通用特性:

① 創(chuàng)建——create

② 顯示——show

③ 隱藏——hide

④ 摧毀——destroy

而以上特性并不是Layer組件所特有的,而是所有組件所特有,所以在Layer之上還應(yīng)該存在一個AbstractView的抽象組件

至此繼承關(guān)系便出來了,拋開多余的接口不看,簡單來說是這樣的:

#p#

組件dom層面實(shí)現(xiàn)

最簡單實(shí)現(xiàn)

單從dom實(shí)現(xiàn)來說,其實(shí)一個簡單的ul便可以完成任務(wù)

  1. <ul class="cui-bubble-layer" style="position: absolute; top: 110px; left: 220px;"> 
  2. <li data-index="0" data-flag="c">價格:¥35</li> 
  3. <li data-index="1" data-flag="c">評分:80</li> 
  4. <li data-index="2" data-flag="c">級別:5</li> 
  5. </ul> 

當(dāng)然這里要有相關(guān)的css

  1. .cui-bubble-layer { 
  2.     background: #f2f2f2; 
  3.     border: #bcbcbc 1px solid; 
  4.     border-radius: 3px 

至此形成的效果是醬紫滴:

  1. <!doctype html> 
  2. <html> 
  3. <head> 
  4.   <meta charset="utf-8" /> 
  5.   <title>Blade Demo</title> 
  6.   <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
  7.   <meta content="telephone=no" name="format-detection" /> 
  8.   <meta name="apple-mobile-web-app-capable" content="yes" /> 
  9.   <style type="text/css"
  10.     body, button, input, select, textarea { font: 400 14px/1.5 Arial, "Lucida Grande" ,Verdana, "Microsoft YaHei" ,hei; } 
  11.     body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { margin: 0; padding: 0; } 
  12.     body { background: #f5f5f5; } 
  13.     ul, ol { list-style: none; } 
  14.      
  15.     .cui-bubble-layer { background: #f2f2f2; border: #bcbcbc 1px solid; border-radius: 3px; } 
  16.   </style> 
  17. </head> 
  18. <body> 
  19.   <ul class="cui-bubble-layer" style="position: absolute; top: 110px; left: 220px;"
  20.     <li data-index="0" data-flag="c">價格:¥35</li> 
  21.     <li data-index="1" data-flag="c">評分:80</li> 
  22.     <li data-index="2" data-flag="c">級別:5</li> 
  23.   </ul> 
  24. </body> 
  25. </html> 

這個時候在為其加一個偽類,做點(diǎn)樣式上的調(diào)整,便基本實(shí)現(xiàn)了,這里用到了偽類的知識點(diǎn):

  1. cui-bubble-layer:before {  
  2. position: absolute; content: ""; width: 10px; height: 10px; -webkit-transform: rotate(45deg);  
  3. background: #f2f2f2;  
  4. border-top: #bcbcbc 1px solid;  
  5. border-left: #bcbcbc 1px solid;  
  6. top: -6px; left: 50%; margin-left: -5px; z-index: 1; 

這里設(shè)置了一個絕對定位的矩形框,為其兩個邊框設(shè)置了值,然后變形偏斜45度形成小三角,然后大家都知道了

  1. <!doctype html> 
  2. <html> 
  3. <head> 
  4.   <meta charset="utf-8" /> 
  5.   <title>Blade Demo</title> 
  6.   <meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
  7.   <meta content="telephone=no" name="format-detection" /> 
  8.   <meta name="apple-mobile-web-app-capable" content="yes" /> 
  9.   <style type="text/css"
  10.     body, button, input, select, textarea { font: 400 14px/1.5 Arial, "Lucida Grande" ,Verdana, "Microsoft YaHei" ,hei; } 
  11.     body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea, p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { margin: 0; padding: 0; } 
  12.     body { background: #f5f5f5; } 
  13.     ul, ol { list-style: none; } 
  14.      
  15.     .cui-bubble-layer { background: #f2f2f2; border: #bcbcbc 1px solid; border-radius: 3px; } 
  16.     .cui-bubble-layer > li { padding: 5px 10px; } 
  17.     .cui-bubble-layer:before { position: absolute; content: ""; width: 10px; height: 10px; -webkit-transform: rotate(45deg); background: #f2f2f2; border-top: #bcbcbc 1px solid; border-left: #bcbcbc 1px solid; top: -6px; left: 50%; margin-left: -5px; z-index: 1;</style> 
  18. </head> 
  19. <body> 
  20.   <ul class="cui-bubble-layer" style="position: absolute; top: 110px; left: 220px;"
  21.     <li data-index="0" data-flag="c">價格:¥35</li> 
  22.     <li data-index="1" data-flag="c">評分:80</li> 
  23.     <li data-index="2" data-flag="c">級別:5</li> 
  24.   </ul> 
  25. </body> 
  26. </html> 

http://sandbox.runjs.cn/show/9ywitfn8

不足與擴(kuò)展

上面作為基本實(shí)現(xiàn),沒有什么問題,但是其實(shí)際應(yīng)用場景會有以下不足:

① 基本的ul層級需要一個包裹層,包裹層具有一個up或者down的class,然后在決定那個箭頭是向上還是向下

② 我們這里不能使用偽類,其原因是,我們的小三角標(biāo)簽并不是一定在中間,其具有一定滑動的特性,也就是說,這個小三角需要被js控制其左右位置,他需要是一個標(biāo)簽

根據(jù)以上所述,我們的結(jié)構(gòu)似乎應(yīng)該是這個樣子滴:

  1. <section class="cui-bubble-layer up-or-down-class"
  2.   <i class="cui-icon-triangle"></i> 
  3.   <ul> 
  4.     <li data-index="0" data-flag="c">價格:¥35</li> 
  5.     <li data-index="1" data-flag="c">評分:80</li> 
  6.     <li data-index="2" data-flag="c">級別:5</li> 
  7.   </ul> 
  8. </section> 

① 根元素上我們可以設(shè)置當(dāng)前應(yīng)該是up還是down的樣式

② i標(biāo)簽根據(jù)根元素的up或者down選擇是向上還是向下,并且該標(biāo)簽可被js操作

到此,似乎整個組件便比較完全了,但是真實(shí)的情況卻不是如此,怎么說了,上面的結(jié)構(gòu)太局限了

該組件需要一個容器,這個容器標(biāo)簽應(yīng)該位于ul之上,這個時候容器內(nèi)部所裝載的dom結(jié)構(gòu)便可以不是ul而是其他什么結(jié)構(gòu)了

其次,在手機(jī)上,我們可視項(xiàng)目在4S手機(jī)上不會超過5個,往往是4個,所以我們應(yīng)該在其容器上設(shè)置類似overflow之類的可滾動屬性

組件回歸·最終結(jié)構(gòu)

由上所述,基于其是繼承至Layer的事實(shí),我們可以形成這樣的結(jié)構(gòu):

  1. <section class="cui-pop cui-bubble-layer"
  2.   <i class="cui-pop-triangle"></i> 
  3.   <div class="cui-pop-head"
  4.   </div> 
  5.   <div class="cui-pop-body"
  6.     <ul> 
  7.       <li data-index="0" data-flag="c">價格:¥35</li> 
  8.       <li data-index="1" data-flag="c">評分:80</li> 
  9.       <li data-index="2" data-flag="c">級別:5</li> 
  10.     </ul> 
  11.   </div> 
  12.   <div class="cui-pop-footer"
  13.   </div> 
  14. </section> 

這個也可以是我們整個彈出層類的基本結(jié)構(gòu),我們可以在此上做很多擴(kuò)展,但是這里我們不扯太多,單就氣泡組件做論述

就氣泡組件,其結(jié)構(gòu)是:

  1. <section class="cui-pop cui-bubble-layer"
  2.   <i class="cui-pop-triangle"></i> 
  3.   <div class="cui-pop-body"
  4.     <ul> 
  5.       <li data-index="0" data-flag="c">價格:¥35</li> 
  6.       <li data-index="1" data-flag="c">評分:80</li> 
  7.       <li data-index="2" data-flag="c">級別:5</li> 
  8.     </ul> 
  9.   </div> 
  10. </section> 

#p#

js層面的實(shí)現(xiàn)

這里仍然是采用的blade中的那一套繼承機(jī)制,如果有不明白又有點(diǎn)興趣的同學(xué)請移步:【blade的UI設(shè)計(jì)】理解前端MVC與分層思想

關(guān)于模板

因?yàn)槲覀冞@一部分的主題為重構(gòu)相關(guān),所以我們這里的關(guān)注點(diǎn)是CSS,我們首先生成我們的模板:

  1. <section class="cui-pop <%=wrapperClass %> <%if(dir == 'up'){ %> <%=upClass %> <% } else { %> <%=downClass %> <% } %>"
  2.   <i class="cui-pop-triangle"></i> 
  3.   <div class="cui-pop-body"
  4.     <ul class="cui-pop-list <%=itemStyleClass %>"
  5.     <% for(var i = 0, len = data.length; i < len; i++) { %> 
  6.       <% var itemData = data[i]; %> 
  7.       <li data-index="<%=i%>" data-flag="c" class="<% if(index == i){ %><%=curClass %><%} %>" > 
  8.         <%if(typeof itemFn == 'function') { %><%=itemFn.call(itemData) %> <% } else { %><%=itemData.name%><%} %> 
  9.     <% } %> 
  10.     </ul> 
  11.   </div> 
  12. </section> 

這里給出了幾個關(guān)鍵的定制化點(diǎn):

① wrapperClass用以添加業(yè)務(wù)團(tuán)隊(duì)定制化的class以改變根元素的class,如此的好處是便于業(yè)務(wù)團(tuán)隊(duì)定制化氣泡組件的樣式

② 給出了項(xiàng)目列表Ul的可定制化className,通用單單只是方便業(yè)務(wù)團(tuán)隊(duì)做樣式改變

③ 默認(rèn)情況下返回的是傳入項(xiàng)目的name字段,但是用戶可傳入一個itemFn的回調(diào),定制化返回

以上模板基本可滿足條件,如果不滿足,便可把整個模板作為參數(shù)傳入了

關(guān)于js實(shí)現(xiàn)

由于繼承的實(shí)現(xiàn),我們大部分工作已經(jīng)被做了,我們只需要在幾個關(guān)鍵地方編寫代碼即可

  1. define(['UILayer', getAppUITemplatePath('ui.bubble.layer')], function (UILayer, template) { 
  2.   return _.inherit(UILayer, { 
  3.     propertys: function ($super) { 
  4.       $super(); 
  5.       //html模板 
  6.       this.template = template; 
  7.       this.needMask = false
  8.  
  9.       this.datamodel = { 
  10.         data: [], 
  11.         wrapperClass: 'cui-bubble-layer'
  12.         upClass: 'cui-pop--triangle-up'
  13.         downClass: 'cui-pop--triangle-down'
  14.         curClass: 'active'
  15.         itemStyleClass: ''
  16.         needBorder: true
  17.         index: -1, 
  18.         dir: 'up'  //箭頭方向默認(rèn)值 
  19.       }; 
  20.  
  21.       this.events = { 
  22.         'click .cui-pop-list>li''clickAction' 
  23.       }; 
  24.  
  25.       this.onClick = function (data, index, el, e) { 
  26.         console.log(arguments); 
  27. //        this.setIndex(index); 
  28.       }; 
  29.  
  30.       this.width = null
  31.  
  32.       //三角圖標(biāo)偏移量 
  33.       this.triangleLeft = null
  34.       this.triangleRight = null
  35.  
  36.       this.triggerEl = null
  37.  
  38.     }, 
  39.  
  40.     initialize: function ($super, opts) { 
  41.       $super(opts); 
  42.     }, 
  43.  
  44.     createRoot: function (html) { 
  45.       this.$el = $(html).hide().attr('id'this.id); 
  46.     }, 
  47.  
  48.     clickAction: function (e) { 
  49.       var el = $(e.currentTarget); 
  50.       var i = el.attr('data-index'); 
  51.       var data = this.datamodel.data[i]; 
  52.       this.onClick.call(this, data, i, el, e); 
  53.     }, 
  54.  
  55.     initElement: function () { 
  56.       this.el = this.$el; 
  57.       this.triangleEl = this.$('.cui-pop-triangle'); 
  58.       this.windowWidth = $(window).width(); 
  59.     }, 
  60.  
  61.     setIndex: function (i) { 
  62.       var curClass = this.datamodel.curClass; 
  63.       i = parseInt(i); 
  64.       if (i < 0 || i > this.datamodel.data.length || i == this.datamodel.index) return
  65.       this.datamodel.index = i; 
  66.  
  67.       //這里不以datamodel改變引起整個dom變化了,不劃算 
  68.       this.$('.cui-pop-list li').removeClass(curClass); 
  69.       this.$('li[data-index="' + i + '"]').addClass(curClass); 
  70.     }, 
  71.  
  72.     //位置定位 
  73.     reposition: function () { 
  74.       if (!this.triggerEl) return
  75.       var offset = this.triggerEl.offset(); 
  76.       var step = 6, w = offset.width - step; 
  77.       var top = 0, left = 0, right; 
  78.       if (this.datamodel.dir == 'up') { 
  79.         top = (offset.top + offset.height + 8) + 'px'
  80.       } else { 
  81.         top = (offset.top - this.el.offset().height - 8) + 'px'
  82.       } 
  83.  
  84.       left = (offset.left + 2) + 'px'
  85.  
  86.       if (offset.left + (parseInt(this.width) || w) > this.windowWidth) { 
  87.         this.el.css({ 
  88.           width: this.width || w, 
  89.           top: top, 
  90.           right: '2px' 
  91.         }); 
  92.       } else { 
  93.         this.el.css({ 
  94.           width: this.width || w, 
  95.           top: top, 
  96.           left: left 
  97.         }); 
  98.       } 
  99.  
  100.       if (this.triangleLeft) { 
  101.         this.triangleEl.css({ 'left'this.triangleLeft, 'right''auto' }); 
  102.       } 
  103.       if (this.triangleRight) { 
  104.         this.triangleEl.css({ 'right'this.triangleRight, 'left''auto' }); 
  105.       } 
  106.     }, 
  107.  
  108.     addEvent: function ($super) { 
  109.       $super(); 
  110.       this.on('onCreate'function () { 
  111.         this.$el.removeClass('cui-layer'); 
  112.         this.$el.css({ position: 'absolute' }); 
  113.       }); 
  114.       this.on('onShow'function () { 
  115.         this.setzIndexTop(this.el); 
  116.       }); 
  117.     } 
  118.  
  119.   }); 
  120.  
  121. }); 

這里開始調(diào)用的,便可做簡單實(shí)現(xiàn):

  1. 'click .demo1': function (e) { 
  2.   if (!this.demo1) { 
  3.     var data = [{ name: '<span class="center">普通會員</span>' }, 
  4.     { name: '<span class="center">vip</span>' }, 
  5.     { name: '<span class="center">高級vip</span>' }, 
  6.     { name: '<span class="center">鉆石vip</span>'}]; 
  7.     this.list = new UIBubbleLayer({ 
  8.       datamodel: { 
  9.         data: data 
  10.       }, 
  11.       triggerEl: $(e.currentTarget), 
  12.       width: '150px', 
  13.       triangleLeft: '20px' 
  14.     }); 
  15.   } 
  16.   this.list.show(); 

稍作修改便可形成另一種樣子:

只不過我們還得考慮這個場景的發(fā)生,在項(xiàng)目過多過長時我們?nèi)孕枰鎏幚恚?/p>

這里有很多辦法可以處理,***個是直接傳入maxHeight,如果高度超出的話便出現(xiàn)滾動條,第二個是動態(tài)在組件內(nèi)部計(jì)算,查看組件與可視區(qū)域的關(guān)系

我們這里還是采用可視區(qū)域計(jì)算吧,于是對原組件做一些改造,加一個接口:

  1. this.checkHeightOverflow(); 

就這一簡單接口其實(shí)可分為幾個段落的實(shí)現(xiàn)

***個接口為檢測可視區(qū)域,這個可以被用戶重寫

  1. isSizeOverflow 

第二個接口是如果可視區(qū)域超出,也就是***個接口返回true時的處理邏輯

  1. handleSizeOverflow 

考慮到超出的未必是高度,所以這里height改為了Size

當(dāng)然,這里會存在資源銷毀的工作,所以會新增一個hide接口

  1. isSizeOverflow: function () { 
  2.   if (!this.el) return false; 
  3.   if (this.el.height() > this.windowHeight * 0.8) return true; 
  4.   return false; 
  5. }, 
  6.  
  7. handleSizeOverflow: function () { 
  8.   if (!this.isSizeOverflow()) return; 
  9.  
  10.   this.listWrapper.css({ 
  11.     height: (parseInt(this.windowHeight * 0.8) + 'px'), 
  12.     overflow: 'hidden', 
  13.     position: 'relative' 
  14.   }); 
  15.  
  16.   this.listEl.css({ position: 'absolute', width: '100%' }); 
  17.  
  18.   //調(diào)用前需要重置位置 
  19.   this.reposition(); 
  20.  
  21.   this.scroll = new UIScroll({ 
  22.     wrapper: this.listWrapper, 
  23.     scroller: this.listEl 
  24.   }); 
  25. }, 
  26.  
  27. checkSizeOverflow: function () { 
  28.   this.handleSizeOverflow(); 
  29. }, 
  30.  
  31. addEvent: function ($super) { 
  32.   $super(); 
  33.   this.on('onCreate', function () { 
  34.     this.$el.removeClass('cui-layer'); 
  35.     this.$el.css({ position: 'absolute' }); 
  36.   }); 
  37.   this.on('onShow', function () { 
  38.  
  39.     //檢查可視區(qū)域是否超出; 
  40.     this.checkSizeOverflow(); 
  41.     this.setzIndexTop(this.el); 
  42.   }); 
  43.   this.on('onHide', function () { 
  44.     if (this.scroll) this.scroll.destroy(); 
  45.   }); 

到此,我們的功能也基本結(jié)束了,***實(shí)現(xiàn)一個定制化一點(diǎn)的功能,將我們的氣泡組件變成黑色:

結(jié)語

今天的學(xué)習(xí)到此為止,因?yàn)樾♀Ocss也算是初學(xué),若是文中有誤,請?zhí)岢?/p>

該組件的動畫以來我準(zhǔn)備做到Layer基類上,而是會介紹css3的動畫技術(shù),這里便不介紹了

下一期,我們就mobile的整體布局,以及header組件的實(shí)現(xiàn)做說明學(xué)習(xí)

代碼地址:https://github.com/yexiaochai/cssui/tree/gh-pages

demo地址:http://yexiaochai.github.io/cssui/demo/debug.html#bubble.layer

 

責(zé)任編輯:張偉 來源: 博客園
相關(guān)推薦

2011-06-09 12:59:23

HTML 5CSS

2015-07-06 09:57:04

HTML5CSS框架BootFlat

2011-05-16 09:47:15

CSS3HTML5

2011-06-13 10:07:33

HTML 5CSS3移動應(yīng)用

2010-03-22 08:56:12

2011-11-25 13:18:40

HTML 5

2012-02-29 09:27:36

ibmdw

2011-03-22 08:54:02

HTML 5CSS3JavaScript

2012-05-11 09:37:34

HTML5

2011-06-27 09:47:37

HTML 5

2012-02-27 10:00:50

HTML 5

2012-04-10 10:31:07

2011-11-18 13:25:48

HTML 5

2012-05-24 11:03:55

HTML5

2011-08-30 16:39:34

HTML 5

2010-04-01 13:03:10

2010-07-23 10:08:44

Dojo 1.5

2012-02-29 15:46:48

HTML 5

2011-11-11 10:01:37

HTML 5

2017-07-11 15:00:04

前端CSS3D視角
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號