热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

html5+css3气泡组件的实现方法

本篇内容主要讲解“html5+css3气泡组件的实现方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“htm

本篇内容主要讲解“html5+css3气泡组件的实现方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“html5+css3气泡组件的实现方法”吧!

前言

气泡组件在实际工作中非常普遍,无论是网页中还是app中,比如:

html5+css3气泡组件的实现方法

html5+css3气泡组件的实现方法

html5+css3气泡组件的实现方法

html5+css3气泡组件的实现方法

html5+css3气泡组件的实现方法

我们这里所谓气泡组件是指列表型气泡组件,这里就其dom实现,css实现,js实现做一个讨论,最后对一些细节点做一些说明,希望对各位有用

小钗最近初学CSS,这里做一个专题,便于自身CSS提升,文章有不少问题与可优化点,请各位指导

组件分类

单由气泡组件来说,他仍然属于“弹出层”类组件,也就是说其会具有这些特性:

① 布局为脱离文档流

② 可以具有mask蒙版,并且可配置点击蒙版是否关闭的特性

③ 可选的特性有点击浏览器回退关闭组件以及动画的显示与隐藏动画特性

其中比较不同的是:

① 不是居中定位

② 具有一个箭头标识,并且可以设置再上或者在下

③ 因为具有箭头,而且这个箭头是相对于一个元素的,一般意义上我们任务是相对某个按钮,所以说具有一个triggerEL

所以单从这里论述来说,我们的组件名为BubbleLayer,其应该继承与一个通用的Layer

但是,就由Layer来说,其最少会具有以下通用特性:

① 创建——create

② 显示——show

③ 隐藏——hide

④ 摧毁——destroy

而以上特性并不是Layer组件所特有的,而是所有组件所特有,所以在Layer之上还应该存在一个AbstractView的抽象组件

至此继承关系便出来了,抛开多余的接口不看,简单来说是这样的:

html5+css3气泡组件的实现方法

组件dom层面实现最简单实现

单从dom实现来说,其实一个简单的ul便可以完成任务

代码如下:



     
  • 价格:¥35

  •  
  • 评分:80

  •  
  • 级别:5


当然这里要有相关的css

代码如下:


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

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

html5+css3气泡组件的实现方法

代码如下:





 
 
 

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

不足与扩展

上面作为基本实现,没有什么问题,但是其实际应用场景会有以下不足:

① 基本的ul层级需要一个包裹层,包裹层具有一个up或者down的class,然后在决定那个箭头是向上还是向下

② 我们这里不能使用伪类,其原因是,我们的小三角标签并不是一定在中间,其具有一定滑动的特性,也就是说,这个小三角需要被js控制其左右位置,他需要是一个标签

根据以上所述,我们的结构似乎应该是这个样子滴:

代码如下:



 
 

       
  • 价格:¥35

  •    
  • 评分:80

  •    
  • 级别:5

  •  


① 根元素上我们可以设置当前应该是up还是down的样式

② i标签根据根元素的up或者down选择是向上还是向下,并且该标签可被js操作

到此,似乎整个组件便比较完全了,但是真实的情况却不是如此,怎么说了,上面的结构太局限了

该组件需要一个容器,这个容器标签应该位于ul之上,这个时候容器内部所装载的dom结构便可以不是ul而是其他什么结构了

其次,在手机上,我们可视项目在4S手机上不会超过5个,往往是4个,所以我们应该在其容器上设置类似overflow之类的可滚动属性

组件回归·最终结构

由上所述,基于其是继承至Layer的事实,我们可以形成这样的结构:

代码如下:



 
 

 

 

   

         
  • 价格:¥35

  •      
  • 评分:80

  •      
  • 级别:5

  •    

 

 

这个也可以是我们整个弹出层类的基本结构,我们可以在此上做很多扩展,但是这里我们不扯太多,单就气泡组件做论述

就气泡组件,其结构是:

代码如下:



 
 

   

         
  • 价格:¥35

  •      
  • 评分:80

  •      
  • 级别:5

  •    

 


js层面的实现

这里仍然是采用的blade中的那一套继承机制,如果有不明白又有点兴趣的同学请移步:【blade的UI设计】理解前端MVC与分层思想

关于模板

因为我们这一部分的主题为重构相关,所以我们这里的关注点是CSS,我们首先生成我们的模板:

代码如下:



 
 

   

       <% for(var i = 0, len = data.length; i
         <% var itemData = data[i]; %>
         

  •        <%if(typeof itemFn == &#39;function&#39;) { %><%=itemFn.call(itemData) %> <% } else { %><%=itemData.name%><%} %>
       <% } %>
       

 


这里给出了几个关键的定制化点:

① wrapperClass用以添加业务团队定制化的class以改变根元素的class,如此的好处是便于业务团队定制化气泡组件的样式

② 给出了项目列表Ul的可定制化className,通用单单只是方便业务团队做样式改变

③ 默认情况下返回的是传入项目的name字段,但是用户可传入一个itemFn的回调,定制化返回

以上模板基本可满足条件,如果不满足,便可把整个模板作为参数传入了

关于js实现

由于继承的实现,我们大部分工作已经被做了,我们只需要在几个关键地方编写代码即可

代码如下:


define([&#39;UILayer&#39;, getAppUITemplatePath(&#39;ui.bubble.layer&#39;)], function (UILayer, template) {
 return _.inherit(UILayer, {
   propertys: function ($super) {
     $super();
     //html模板
     this.template = template;
     this.needMask = false;

     this.datamodel = {
       data: [],
       wrapperClass: &#39;cui-bubble-layer&#39;,
       upClass: &#39;cui-pop--triangle-up&#39;,
       downClass: &#39;cui-pop--triangle-down&#39;,
       curClass: &#39;active&#39;,
       itemStyleClass: &#39;&#39;,
       needBorder: true,
       index: -1,
       dir: &#39;up&#39;  //箭头方向默认值
     };

     this.events = {
       &#39;click .cui-pop-list>li&#39;: &#39;clickAction&#39;
     };

     this.OnClick= function (data, index, el, e) {
       console.log(arguments);
//        this.setIndex(index);
     };

     this.width = null;

     //三角图标偏移量
     this.triangleLeft = null;
     this.triangleRight = null;

     this.triggerEl = null;

   },

   initialize: function ($super, opts) {
     $super(opts);
   },

   createRoot: function (html) {
     this.$el = $(html).hide().attr(&#39;id&#39;, this.id);
   },

   clickAction: function (e) {
     var el = $(e.currentTarget);
     var i = el.attr(&#39;data-index&#39;);
     var data = this.datamodel.data[i];
     this.onClick.call(this, data, i, el, e);
   },

   initElement: function () {
     this.el = this.$el;
     this.triangleEl = this.$(&#39;.cui-pop-triangle&#39;);
     this.windowWidth = $(window).width();
   },

   setIndex: function (i) {
     var curClass = this.datamodel.curClass;
     i = parseInt(i);
     if (i <0 || i > this.datamodel.data.length || i == this.datamodel.index) return;
     this.datamodel.index = i;

     //这里不以datamodel改变引起整个dom变化了,不划算
     this.$(&#39;.cui-pop-list li&#39;).removeClass(curClass);
     this.$(&#39;li[data-index="&#39; + i + &#39;"]&#39;).addClass(curClass);
   },

   //位置定位
   reposition: function () {
     if (!this.triggerEl) return;
     var offset = this.triggerEl.offset();
     var step = 6, w = offset.width - step;
     var top = 0, left = 0, right;
     if (this.datamodel.dir == &#39;up&#39;) {
       top = (offset.top + offset.height + 8) + &#39;px&#39;;
     } else {
       top = (offset.top - this.el.offset().height - 8) + &#39;px&#39;;
     }

     left = (offset.left + 2) + &#39;px&#39;;

     if (offset.left + (parseInt(this.width) || w) > this.windowWidth) {
       this.el.css({
         width: this.width || w,
         top: top,
         right: &#39;2px&#39;
       });
     } else {
       this.el.css({
         width: this.width || w,
         top: top,
         left: left
       });
     }

     if (this.triangleLeft) {
       this.triangleEl.css({ &#39;left&#39;: this.triangleLeft, &#39;right&#39;: &#39;auto&#39; });
     }
     if (this.triangleRight) {
       this.triangleEl.css({ &#39;right&#39;: this.triangleRight, &#39;left&#39;: &#39;auto&#39; });
     }
   },

   addEvent: function ($super) {
     $super();
     this.on(&#39;onCreate&#39;, function () {
       this.$el.removeClass(&#39;cui-layer&#39;);
       this.$el.css({ position: &#39;absolute&#39; });
     });
     this.on(&#39;onShow&#39;, function () {
       this.setzIndexTop(this.el);
     });
   }

 });

});



这里开始调用的,便可做简单实现:

代码如下:


&#39;click .demo1&#39;: function (e) {
 if (!this.demo1) {
   var data = [{ name: &#39;普通会员&#39; },
   { name: &#39;vip&#39; },
   { name: &#39;高级vip&#39; },
   { name: &#39;钻石vip&#39;}];
   this.list = new UIBubbleLayer({
     datamodel: {
       data: data
     },
     triggerEl: $(e.currentTarget),
     width: &#39;150px&#39;,
     triangleLeft: &#39;20px&#39;
   });
 }
 this.list.show();
}

稍作修改便可形成另一种样子:

html5+css3气泡组件的实现方法

只不过我们还得考虑这个场景的发生,在项目过多过长时我们仍需要做处理:

html5+css3气泡组件的实现方法

这里有很多办法可以处理,第一个是直接传入maxHeight,如果高度超出的话便出现滚动条,第二个是动态在组件内部计算,查看组件与可视区域的关系

我们这里还是采用可视区域计算吧,于是对原组件做一些改造,加一个接口:

代码如下:

this.checkHeightOverflow();

就这一简单接口其实可分为几个段落的实现

第一个接口为检测可视区域,这个可以被用户重写

代码如下:

isSizeOverflow

第二个接口是如果可视区域超出,也就是第一个接口返回true时的处理逻辑

代码如下:

handleSizeOverflow

考虑到超出的未必是高度,所以这里height改为了Size

当然,这里会存在资源销毁的工作,所以会新增一个hide接口

代码如下:


isSizeOverflow: function () {
 if (!this.el) return false;
 if (this.el.height() > this.windowHeight * 0.8) return true;
 return false;
},

handleSizeOverflow: function () {
 if (!this.isSizeOverflow()) return;

 this.listWrapper.css({
   height: (parseInt(this.windowHeight * 0.8) + &#39;px&#39;),
   overflow: &#39;hidden&#39;,
   position: &#39;relative&#39;
 });

 this.listEl.css({ position: &#39;absolute&#39;, width: &#39;100%&#39; });

 //调用前需要重置位置
 this.reposition();

 this.scroll = new UIScroll({
   wrapper: this.listWrapper,
   scroller: this.listEl
 });
},

checkSizeOverflow: function () {
 this.handleSizeOverflow();
},

addEvent: function ($super) {
 $super();
 this.on(&#39;onCreate&#39;, function () {
   this.$el.removeClass(&#39;cui-layer&#39;);
   this.$el.css({ position: &#39;absolute&#39; });
 });
 this.on(&#39;onShow&#39;, function () {

   //检查可视区域是否超出;
   this.checkSizeOverflow();
   this.setzIndexTop(this.el);
 });
 this.on(&#39;onHide&#39;, function () {
   if (this.scroll) this.scroll.destroy();
 });
}

html5+css3气泡组件的实现方法

到此,我们的功能也基本结束了,最后实现一个定制化一点的功能,将我们的气泡组件变成黑色:

html5+css3气泡组件的实现方法

到此,相信大家对“html5+css3气泡组件的实现方法”有了更深的了解,不妨来实际操作一番吧!这里是编程笔记网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!


推荐阅读
  • 如何在HTML中获取鼠标的当前位置
    本文介绍了在HTML中获取鼠标当前位置的三种方法,分别是相对于屏幕的位置、相对于窗口的位置以及考虑了页面滚动因素的位置。通过这些方法可以准确获取鼠标的坐标信息。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • position属性absolute与relative的区别和用法详解
    本文详细解读了CSS中的position属性absolute和relative的区别和用法。通过解释绝对定位和相对定位的含义,以及配合TOP、RIGHT、BOTTOM、LEFT进行定位的方式,说明了它们的特性和能够实现的效果。同时指出了在网页居中时使用Absolute可能会出错的原因,即以浏览器左上角为原始点进行定位,不会随着分辨率的变化而变化位置。最后总结了一些使用这两个属性的技巧。 ... [详细]
  • 移动端常用单位——rem的使用方法和注意事项
    本文介绍了移动端常用的单位rem的使用方法和注意事项,包括px、%、em、vw、vh等其他常用单位的比较。同时还介绍了如何通过JS获取视口宽度并动态调整rem的值,以适应不同设备的屏幕大小。此外,还提到了rem目前在移动端的主流地位。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • 本文介绍了解决IE678伪类不兼容问题的方法,包括少用CSS3和HTML5独有的属性,使用CSS hacker,使用last-child清除浮动、批量添加标签、去掉list item最后一个的border-right等技巧。同时还介绍了使用after清除浮动时加上IE独有属性zoom:1的处理方法。另外,本文还提到可以使用jQuery代替批量添加标签的功能,以及使用负边距和CSS2选择器element+element去掉list item最后一个的border-right的方法。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
author-avatar
小米-发烧友
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有