音效素材网提供各类素材,打造精品素材网站!

站内导航 站长工具 投稿中心 手机访问

音效素材

html5+css3气泡组件的实现
日期:2021-09-05 22:58:10   来源:脚本之家

前言

气泡组件在实际工作中非常普遍,无论是网页中还是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便可以完成任务


复制代码
代码如下:

<ul class="cui-bubble-layer" style="position: absolute; top: 110px; left: 220px;">
<li data-index="0" data-flag="c">价格:¥35</li>
<li data-index="1" data-flag="c">评分:80</li>
<li data-index="2" data-flag="c">级别:5</li>
</ul>

当然这里要有相关的css


复制代码
代码如下:

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

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

html5+css3气泡组件的实现


复制代码
代码如下:

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Blade Demo</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta content="telephone=no" name="format-detection" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<style type="text/css">
body, button, input, select, textarea { font: 400 14px/1.5 Arial, "Lucida Grande" ,Verdana, "Microsoft YaHei" ,hei; }
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; }
body { background: #f5f5f5; }
ul, ol { list-style: none; }

.cui-bubble-layer { background: #f2f2f2; border: #bcbcbc 1px solid; border-radius: 3px; }
</style>
</head>
<body>
<ul class="cui-bubble-layer" style="position: absolute; top: 110px; left: 220px;">
<li data-index="0" data-flag="c">价格:¥35</li>
<li data-index="1" data-flag="c">评分:80</li>
<li data-index="2" data-flag="c">级别:5</li>
</ul>
</body>
</html>

这个时候在为其加一个伪类,做点样式上的调整,便基本实现了,这里用到了伪类的知识点:


复制代码
代码如下:

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;
}

这里设置了一个绝对定位的矩形框,为其两个边框设置了值,然后变形偏斜45度形成小三角,然后大家都知道了


复制代码
代码如下:

<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Blade Demo</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta content="telephone=no" name="format-detection" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<style type="text/css">
body, button, input, select, textarea { font: 400 14px/1.5 Arial, "Lucida Grande" ,Verdana, "Microsoft YaHei" ,hei; }
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; }
body { background: #f5f5f5; }
ul, ol { list-style: none; }

.cui-bubble-layer { background: #f2f2f2; border: #bcbcbc 1px solid; border-radius: 3px; }
.cui-bubble-layer > li { padding: 5px 10px; }
.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>
</head>
<body>
<ul class="cui-bubble-layer" style="position: absolute; top: 110px; left: 220px;">
<li data-index="0" data-flag="c">价格:¥35</li>
<li data-index="1" data-flag="c">评分:80</li>
<li data-index="2" data-flag="c">级别:5</li>
</ul>
</body>
</html>

html5+css3气泡组件的实现

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

不足与扩展

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

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

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

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


复制代码
代码如下:

<section class="cui-bubble-layer up-or-down-class">
<i class="cui-icon-triangle"></i>
<ul>
<li data-index="0" data-flag="c">价格:¥35</li>
<li data-index="1" data-flag="c">评分:80</li>
<li data-index="2" data-flag="c">级别:5</li>
</ul>
</section>

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

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

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

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

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

组件回归·最终结构

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


复制代码
代码如下:

<section class="cui-pop cui-bubble-layer">
<i class="cui-pop-triangle"></i>
<div class="cui-pop-head">
</div>
<div class="cui-pop-body">
<ul>
<li data-index="0" data-flag="c">价格:¥35</li>
<li data-index="1" data-flag="c">评分:80</li>
<li data-index="2" data-flag="c">级别:5</li>
</ul>
</div>
<div class="cui-pop-footer">
</div>
</section>

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

就气泡组件,其结构是:


复制代码
代码如下:

<section class="cui-pop cui-bubble-layer">
<i class="cui-pop-triangle"></i>
<div class="cui-pop-body">
<ul>
<li data-index="0" data-flag="c">价格:¥35</li>
<li data-index="1" data-flag="c">评分:80</li>
<li data-index="2" data-flag="c">级别:5</li>
</ul>
</div>
</section>

js层面的实现

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

关于模板

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


复制代码
代码如下:

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

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

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

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

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

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

关于js实现

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


复制代码
代码如下:

define(['UILayer', getAppUITemplatePath('ui.bubble.layer')], function (UILayer, template) {
return _.inherit(UILayer, {
propertys: function ($super) {
$super();
//html模板
this.template = template;
this.needMask = false;</p> <p> this.datamodel = {
data: [],
wrapperClass: 'cui-bubble-layer',
upClass: 'cui-pop--triangle-up',
downClass: 'cui-pop--triangle-down',
curClass: 'active',
itemStyleClass: '',
needBorder: true,
index: -1,
dir: 'up' //箭头方向默认值
};</p> <p> this.events = {
'click .cui-pop-list>li': 'clickAction'
};</p> <p> this.onClick = function (data, index, el, e) {
console.log(arguments);
// this.setIndex(index);
};</p> <p> this.width = null;</p> <p> //三角图标偏移量
this.triangleLeft = null;
this.triangleRight = null;</p> <p> this.triggerEl = null;</p> <p> },</p> <p> initialize: function ($super, opts) {
$super(opts);
},</p> <p> createRoot: function (html) {
this.$el = $(html).hide().attr('id', this.id);
},</p> <p> clickAction: function (e) {
var el = $(e.currentTarget);
var i = el.attr('data-index');
var data = this.datamodel.data[i];
this.onClick.call(this, data, i, el, e);
},</p> <p> initElement: function () {
this.el = this.$el;
this.triangleEl = this.$('.cui-pop-triangle');
this.windowWidth = $(window).width();
},</p> <p> 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;</p> <p> //这里不以datamodel改变引起整个dom变化了,不划算
this.$('.cui-pop-list li').removeClass(curClass);
this.$('li[data-index="' + i + '"]').addClass(curClass);
},</p> <p> //位置定位
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 == 'up') {
top = (offset.top + offset.height + 8) + 'px';
} else {
top = (offset.top - this.el.offset().height - 8) + 'px';
}</p> <p> left = (offset.left + 2) + 'px';</p> <p> if (offset.left + (parseInt(this.width) || w) > this.windowWidth) {
this.el.css({
width: this.width || w,
top: top,
right: '2px'
});
} else {
this.el.css({
width: this.width || w,
top: top,
left: left
});
}</p> <p> if (this.triangleLeft) {
this.triangleEl.css({ 'left': this.triangleLeft, 'right': 'auto' });
}
if (this.triangleRight) {
this.triangleEl.css({ 'right': this.triangleRight, 'left': 'auto' });
}
},</p> <p> addEvent: function ($super) {
$super();
this.on('onCreate', function () {
this.$el.removeClass('cui-layer');
this.$el.css({ position: 'absolute' });
});
this.on('onShow', function () {
this.setzIndexTop(this.el);
});
}</p> <p> });</p> <p>});


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


复制代码
代码如下:

'click .demo1': function (e) {
if (!this.demo1) {
var data = [{ name: '<span class="center">普通会员</span>' },
{ name: '<span class="center">vip</span>' },
{ name: '<span class="center">高级vip</span>' },
{ name: '<span class="center">钻石vip</span>'}];
this.list = new UIBubbleLayer({
datamodel: {
data: data
},
triggerEl: $(e.currentTarget),
width: '150px',
triangleLeft: '20px'
});
}
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;
},</p> <p>handleSizeOverflow: function () {
if (!this.isSizeOverflow()) return;</p> <p> this.listWrapper.css({
height: (parseInt(this.windowHeight * 0.8) + 'px'),
overflow: 'hidden',
position: 'relative'
});</p> <p> this.listEl.css({ position: 'absolute', width: '100%' });</p> <p> //调用前需要重置位置
this.reposition();</p> <p> this.scroll = new UIScroll({
wrapper: this.listWrapper,
scroller: this.listEl
});
},</p> <p>checkSizeOverflow: function () {
this.handleSizeOverflow();
},</p> <p>addEvent: function ($super) {
$super();
this.on('onCreate', function () {
this.$el.removeClass('cui-layer');
this.$el.css({ position: 'absolute' });
});
this.on('onShow', function () {</p> <p> //检查可视区域是否超出;
this.checkSizeOverflow();
this.setzIndexTop(this.el);
});
this.on('onHide', function () {
if (this.scroll) this.scroll.destroy();
});
}

html5+css3气泡组件的实现

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

html5+css3气泡组件的实现

结语

今天的学习到此为止,因为小钗css3也算是初学,若是文中有误,请提出

该组件的动画以来我准备做到Layer基类上,而是会介绍css3的动画技术,这里便不介绍了

    您感兴趣的教程

    在docker中安装mysql详解

    本篇文章主要介绍了在docker中安装mysql详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编...

    详解 安装 docker mysql

    win10中文输入法仅在桌面显示怎么办?

    win10中文输入法仅在桌面显示怎么办?

    win10系统使用搜狗,QQ输入法只有在显示桌面的时候才出来,在使用其他程序输入框里面却只能输入字母数字,win10中...

    win10 中文输入法

    一分钟掌握linux系统目录结构

    这篇文章主要介绍了linux系统目录结构,通过结构图和多张表格了解linux系统目录结构,感兴趣的小伙伴们可以参考一...

    结构 目录 系统 linux

    PHP程序员玩转Linux系列 Linux和Windows安装

    这篇文章主要为大家详细介绍了PHP程序员玩转Linux系列文章,Linux和Windows安装nginx教程,具有一定的参考价值,感兴趣...

    玩转 程序员 安装 系列 PHP

    win10怎么安装杜比音效Doby V4.1 win10安装杜

    第四代杜比®家庭影院®技术包含了一整套协同工作的技术,让PC 发出清晰的环绕声同时第四代杜比家庭影院技术...

    win10杜比音效

    纯CSS实现iOS风格打开关闭选择框功能

    这篇文章主要介绍了纯CSS实现iOS风格打开关闭选择框,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作...

    css ios c

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的

    Win7给电脑C盘扩容的办法大家知道吗?当系统分区C盘空间不足时,就需要给它扩容了,如果不管,C盘没有足够的空间...

    Win7 C盘 扩容

    百度推广竞品词的投放策略

    SEM是基于关键词搜索的营销活动。作为推广人员,我们所做的工作,就是打理成千上万的关键词,关注它们的质量度...

    百度推广 竞品词

    Visual Studio Code(vscode) git的使用教程

    这篇文章主要介绍了详解Visual Studio Code(vscode) git的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...

    教程 Studio Visual Code git

    七牛云储存创始人分享七牛的创立故事与

    这篇文章主要介绍了七牛云储存创始人分享七牛的创立故事与对Go语言的应用,七牛选用Go语言这门新兴的编程语言进行...

    七牛 Go语言

    Win10预览版Mobile 10547即将发布 9月19日上午

    微软副总裁Gabriel Aul的Twitter透露了 Win10 Mobile预览版10536即将发布,他表示该版本已进入内部慢速版阶段,发布时间目...

    Win10 预览版

    HTML标签meta总结,HTML5 head meta 属性整理

    移动前端开发中添加一些webkit专属的HTML5头部标签,帮助浏览器更好解析HTML代码,更好地将移动web前端页面表现出来...

    移动端html5模拟长按事件的实现方法

    这篇文章主要介绍了移动端html5模拟长按事件的实现方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家...

    移动端 html5 长按

    HTML常用meta大全(推荐)

    这篇文章主要介绍了HTML常用meta大全(推荐),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    cdr怎么把图片转换成位图? cdr图片转换为位图的教程

    cdr怎么把图片转换成位图? cdr图片转换为

    cdr怎么把图片转换成位图?cdr中插入的图片想要转换成位图,该怎么转换呢?下面我们就来看看cdr图片转换为位图的...

    cdr 图片 位图

    win10系统怎么录屏?win10系统自带录屏详细教程

    win10系统怎么录屏?win10系统自带录屏详细

    当我们是使用win10系统的时候,想要录制电脑上的画面,这时候有人会想到下个第三方软件,其实可以用电脑上的自带...

    win10 系统自带录屏 详细教程

    + 更多教程 +
    HTMLCSSDreamweaverFrontpage