zoukankan      html  css  js  c++  java
  • 利用jq实现自适应边缘情况的气泡Tip

    由于项目已经接近尾声,所以打算把此次项目中频繁使用的Tip浮窗拎出来分享下。

    需求简述

    项目中会经常出现超出长度显示省略号的情况,而这种情况老项目都是使用title来显示全部信息。本次项目产品觉得title的显示太过缓慢,需要移上等待一段时间才显示,所以希望可以自己实现一个小tip,能够更加符合项目的需求变化。

    然而这个需求提出之后,大家都提出了很多问题,其中问题最大的是:

    如何处理Tip超出屏幕范围,被遮住大部分内容的情况?

    于是,必须实现一个能够根据边缘情况,自动调整显示方式的Tip。本文主要围绕这个需求点,抛开一些业务上的逻辑实现一个demo。

    技术点

    1. jq委托事件

    在实际项目中为了方便调用,需要能像使用title一样方便的实现效果,可能是个人对jq的使用更加熟悉一点,所以并没有打算将这个功能封装成Angular的directive(会抽空封装起来,毕竟使用jq委托的形式,有点脱离了整个架构体系)。所以采用了将其委托于body上,这样即使是动态生成的dom也可以响应事件。(本文主要实现一个小demo,所以并没有这么做)

    2. css3伪类

    使用:beforecss伪类,来实现tip上的气泡箭头。
    顺便贴上css代码:

    .box{
          background: #cd0200;
           100px;
          height: 100px;
        }
    .tip{
        background: #fff;
        position: fixed;
        max- 200px;
        height: auto;
        box-shadow: 1px 1px 9px #ccc;
        top:-10px;
        left: 10px;
        padding: 10px;
        border-radius: 3px;
        z-index: 2;
    }
    .tip:before{
        content: " ";
         0;
        height: 0;
        border-left: 10px solid transparent;
        border-right: 10px solid transparent;
        position: absolute;
    }
    body{
        background: #666;
        height: 2000px;
        font-size: 10px;
    }
    

    3. jq对象的offset属性和一些dom对象属性

    因为需要根据边缘情况,动态修改布局。所以需要检测Tip出现时的位置情况,然后做响应的布局响应。

    功能实现

    第一步自然是事件的定义,由于项目中dom可能是动态生成的,所以不能使用普通的mouseenter事件。这里我们用到了上面提到的事件委托:

    $('body').delegate('[gint-title]', 'mouseenter', function () {
    //...
    })
    

    选择器选择属性的写法是 [gint-title] ,至于为什么用mouseenter而不是mouseover,有兴趣的同学可以自行测试下两者的区别,这里就不继续讨论了。

    本文主要代码基于实现一个demo,所以上面的观点只是个人认为项目中重要的知识点,所以顺带说一下,demo的实现还是脱离事件委托,使用jq自带的hover

    $(".box").hover(function(target){
        //...
    },function(){
        $(".tip").hide();
    })
    $(window).scroll(function() {  
        $(".tip").hide();
    }); 
    

    由于Tip需要一直显示在屏幕中,所以干脆让他的position定义为fixed。但是fixed定位会使Tip在滚动的时候依然屹立于屏幕之中,所以添加了上面代码中的scroll事件。

    下面这张图片,主要说明了需要使用到的获取布局的方法。

    Tip布局说明

    于是我们可以在代码中先定义几个可能经常会用到的变量:

    var dom = $(this);
    var left = dom.offset().left - $(document).scrollLeft();
    //由于Tip默认是显示在下方的 
    //所以这里的top需要加上dom的高度 再减去箭头间隔
    var top = dom.offset().top + dom.height() - $(document).scrollTop() + 7;
    var css = "";
    

    这里声明一个css变量,主要用来动态的修改伪类的定义,让箭头可以根据情况变化(比如:Tip出现在上方时,箭头朝下,出现在下方时,箭头朝上)。

    由于伪类无法使用jq封装好的方法来修改,所以需要添加一个style标签,用来动态变化伪类的定义。

    //判断页面是否存在自定义style
    if(!$("#mystyle").length){
        var style = $("<style id='mystyle'>.tip:before{left:10px}</style>");
        $("body").append(style);
    }
    

    接下来就是对边缘条件的判断:

    //当Tip没有被浏览器底部遮住的时候
    if($(window).height() - top > $(".tip").height()){
        css+="border-bottom: 7px solid #fff;top:-7px;"
    }else{
        css+="border-top: 7px solid #fff;bottom:-6px;"
        top = dom.offset().top - $(document).scrollTop() - $(".tip").height()-20-7;
    }
    //当Tip被浏览器左侧遮住的时候
    if(left<0){
        left = 0
        css +="left:15px;"
    //当Tip没被右侧遮住
    }else if(($(window).width() - left - $(this).width()) > $(".tip").width()-50){
        css +="left:15px;"
    }else{
        left = $(window).width() - $(".tip").width()+20;
        //将箭头跟着gint-title的位置 动态变化
        var _leftpx = $(window).width() - (dom.offset().left - $(document).scrollLeft()) - $(this).width()+15;
        css +="right:"+_leftpx+"px;" 
    }
    //重写style的伪类定义
    $("#mystyle").html(".tip:before{"+css+"}");
    //动态改变tip的布局,并显示tip
    $(".tip").css({"left":left+"px","top":top+"px"}).show();
    

    好了,基本的页面逻辑都已经涉及到了,还有些偏向于计算方面的逻辑需要你仔细对照我提供的布局图,进行抽象理解。还有代码计算中出现的一些数字,是为了让布局更加美观所添加的边界值,可以自行去掉,体会下我添加的用意就清楚了。

    再丢上一个 在线demo链接 我提供了几个例子,可以自行修改显示框的大小,来调试代码的情况。如果发现了问题,欢迎跟我沟通!

  • 相关阅读:
    js&jquery避免报错的方法
    if-else用法
    js-form表单元素的自定义属性
    a标签
    jQuery知识集锦
    JDK动态代理
    hibernate之多对一单向关联
    STL算法设计理念
    计算机常识--win7 删除文件、拒绝訪问等等,所有提示权限不够 解决的方法
    大话设计模式C++实现-第8章-工厂方法模式
  • 原文地址:https://www.cnblogs.com/cydiacen/p/Tip.html
Copyright © 2011-2022 走看看