实现微信对话框的图片样式

不知道大家有没有注意到,微信里面,我们聊天的时候,发文字和发图片的时候,气泡对话框样式是有所不同的。有啥不同呢?且看下图。

Paste_Image.png

可以看到,发图片的时候,气泡对话框箭头的背景也是图片的一部分。出于好奇和需求,我试着尝试实现这一样式。实现是在移动端下进行的。

用到的css属性

background: inherit: 表示继承父级的背景属性,其中包括背景图片。
background-origin: 规定 background-position 属性相对于什么位置来定位。
background-clip: 设置元素的背景(背景图片或颜色)是否延伸到边框下面。

方法一

原理是,定义一个块级元素,把图片设置为块级元素的背景图片,图片位置左移20px,然后使用伪元素,把三角形实现出来,同时继承父级的背景图片,border的宽度是20px,和上面的左移尺寸一样,这样图片拼接才顺畅。代码如下:

<div class="dialog"></div>

<style>
.dialog {
    position: relative;
    width: 200px;
    height: 200px;
    border-radius: 10px;
    margin-left: 40px;
    background: url("card.png") -20px 0 no-repeat;
    background-size: 220px auto;
}
 .dialog:after {
     content: '';
     position: absolute;
     top: 30px;
     left: -40px;
     border: solid #ccc;
     border-width: 20px;
     border-right-color: transparent;
     background: inherit;
     background-size: auto;
     background-clip: border-box;
     background-origin: border-box;
     background-position: 20px -30px;
}
</style>

实现的效果图是这样的:


Paste_Image.png

看起来还不错,达到了预期效果。但是,仔细看下代码,里面的宽度和高度都是固定的,也就是说,不同的图片,在这里显示尺寸都是一样的,这个展示不太友好。

方法二

为了做到自适应,我选择使用img来自动控制大小。对img指定宽度,然后高度自适应。原理跟方法一有点类似。这里大家可以先思考下,如何做。
实现的代码如下:

<div class="dialog">
    <div class="pic-wrap">
        <img src="test.png" alt="">
    </div>
</div>
<style>
    .dialog {
        position: relative;
        width: 200px;
        border-radius: 10px;
        margin-left: 40px;
        background-size: 2px 2px;
        background: url(test.png) -9999px 0 no-repeat;
        img{
            width: 100%;
            position: relative;
            left: -20px;
            bottom: 0;
            top: 0;
            border-radius: 10px;
            display: block;
        }
        .pic-wrap{
            overflow: hidden;
            border-radius: 10px;
        }
    }

    .dialog:after {
        content: '';
        position: absolute;
        top: 30px;
        left: -38px;
        border: solid #ccc;
        border-width: 10px 20px;
        background: inherit;
        border-right-color: transparent;
        background-clip: border-box;
        background-origin: border-box;
        background-position: 20px -30px;
    }
</style>

简单说下原理,三角形的做法还是跟方法一一样,不同的是对话框内图片的处理。这次采用了img标签,并且在img外包了一层,以控制img的展示。首先,img先设置position:absolute,然后,设置left: -20px。然后外层设置宽度,高度由图片控制,设置overflow:hidden,裁剪掉多余的图片部分。
实现的效果如下图:

Paste_Image.png

ok ,这次可以自适应了,但是图片必须要固定宽度,这个展示也不是那么好。最好是可以根据图片的比例,来自动设置宽度和高度,于是就有了方法三。

方法三

在这个方法里面,我的想法是可以做到,图片的高宽可以按照图片的比例来进行展示,而不是固定宽度和高度。这个也是可以实现的,但是需要使用javascript来配合。

原理是这样的:等图片load完之后,拿到图片的大小,然后对图片的展示宽度按照一定的规则进行计算,我这里是采用 (图片的高度/屏幕的高度) * 图片的高度 * 0.5。然后动态设置dialogwidthbackground-size

实现的代码如下:

<!-- html & css -->
<div class="dialog">
    <div class="pic-wrap">
        <img src="test.png" alt="">
    </div>
</div>
<style>
    .dialog {
        position: relative;
        border-radius: 10px;
        margin-left: 40px;
        background: url(test.png) -9999px 0 no-repeat;
        img{
            width: 100%;
            position: relative;
            left: -20px;
            bottom: 0;
            top: 0;
            border-radius: 10px;
            display: block;
        }
        .pic-wrap{
            overflow: hidden;
            border-radius: 10px;
        }
    }

    .dialog:after {
        content: '';
        position: absolute;
        top: 30px;
        left: -38px;
        border: solid #ccc;
        border-width: 10px 20px;
        background: inherit;
        background-size: inherit;
        border-right-color: transparent;
        background-clip: border-box;
        background-origin: border-box;
    }
</style>

/** javascript **/
var dialog = (function(){
    $('img').load(function(){
        var img_real_height = parseInt($(this).height());
        var win_height = parseInt(window.innerHeight);

        var img_width = img_real_height / win_height * (img_real_height) * 0.5;

        $(this).parents('.dialog').css(
            {
                'width': img_width,
                backgroundSize: img_width+'px auto'
            }
        );
    })
})()

但是这个方式也有缺点,就是图片的展示宽度很难用一个比较合理的公式去计算,如果你的图片规格都是差不多的,那可以用这种方法,但是如果你的图片规格多种,就不建议用这种方式了。

方法四

在经过一番思考之后,我决定再去仔细看看微信的处理方法。发现了一个规则:微信里面,如果图片的高度大于宽度,则固定高度,如果图片的高度小于宽度,则固定宽度

ok,那我就来实现一番。

<!-- html & css -->
<div class="dialog" style="background-image: url(../images/test1.jpg)">     
    <div class="pic-wrap">
        <img src="../images/test1.jpg">
    </div>
</div>

<style>
 .dialog {
    position: relative;
    border-radius: 10px;
    background-position: -9999px 0;
    background-repeat: no-repeat;
    margin-left: 10px;

    img{
       position: relative;
       left: -20px;
       border-radius: 10px;
       display: block;
     }

     // 横向
     &.landscape {
         height: auto;
         background-size: px2rem(180px) auto;
         img{
             width: px2rem(180px);
         }
     }

     // 竖向
     &.vertical{
         height: px2rem(180px);
         background-size: auto px2rem(180px);
         img{
             height: px2rem(180px);
         }
     }

     .pic-wrap{
         overflow: hidden;
         border-radius: 10px;
      }
  }

.dialog:after {
    z-index: -2;
    content: '';
    position: absolute;
    top: 10px;
    left: -12px;
    border: solid $bgGrey;
    border-right-color: transparent;
    border-width: 8px 6px;
    background-image: inherit;
    background-size: inherit;
    background-repeat: no-repeat;
    background-clip: border-box;
    background-origin: border-box;
    background-position: 0px -6px;
}
/**  javascript **/
var dialog = (function(){
    function loadImg() {
        $('img').load(function(){
            var img_real_height = parseInt($(this).height());
            var img_real_width = parseInt($(this).width());

            var max_width = '180px';
            var max_height = '180px';

            if(img_real_width / img_real_height > 1) {
                // 横向处理
                $(this).parents('.dialog').addClass('landscape');
            }else{
                // 竖向处理
                $(this).parents('.dialog').addClass('vertical');
            }

        })
    }

    loadImg();
})()

实现的效果如下:

Paste_Image.png

补充

在上述获取图片大小的时候,我使用了load()方法,但是我发现这个方法不太靠谱,会偶尔出现获取不到图片尺寸的情况。要解决这个情况,最好是通过后台接口来取得图片的尺寸,这样会靠谱点。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • | 微信会话框 细心的前端们会发现如果你在微信里发一张和你当前背景一样的图片,那么微信的会给这张图片加边框,并且...
    笔者阿蓉阅读 2,649评论 0 1
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    love2013阅读 2,279评论 0 11
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    wzhiq896阅读 1,689评论 0 2
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,629评论 1 92
  • 1.块级元素和行内元素 块级(block-level)元素;行内(内联、inline-level)元素。 块元素的...
    饥人谷_小侯阅读 1,927评论 1 4