为了减少网络请求个数量,提高网站的访问速度,我们一般都会把一些小的图片合并成一张sprite图,然后根据background-position来进行定位。在web端由于是固定的大小与left 、top,所以定位起来会比较准确、简单。但是在移动端就不一样了,各种手机的屏幕大小不一样,很难做到使用sprite图然后根据background-position来定位。所以普遍的做法都是使用单张图片,然后使用background-size: cover|100%|contain来控制背景图的大小。其实这样会简单得多,但是呢,如果图片太多,网速不好的情况下加载速度就惨不忍睹了。

还是以视觉稿为 640px为例,这是视觉稿的一部分:

根据这个视觉稿,我切出来合并的sprite图张这样:

这是640px视觉稿切出来的图,如果只是适配640px的屏幕,直接使用px定位完全没有问题,但是考虑到其他的屏幕,所以我们会使用rem来等比例缩放背景图。是的,把原尺寸转换为rem就可以了。代码如下:

html代码结构

<div class="test-sprites"><ul class="f-cb"><li class="icon1"></li><li class="icon2"></li><li class="icon3"></li><li class="icon4"></li><li class="icon5"></li><li class="icon6"></li></ul></div>

sass 代码

.test-sprites{margin-top: 30px;ul{padding: 0;margin: 0;}li{width: 0.48rem;height: 0.7rem;overflow: hidden; border: 1px solid #ccc; margin-left: 0.3rem;float: left;background:transparent url('http://nos.netease.com/edu-image/9BC0742AEB1A0B756EFC71B9DF77E452.png') 0 -0.02rem no-repeat;background-size: 10.72rem 4.42rem;}.icon2{width: 0.74rem; height: 0.64rem;background-position: -1.88rem -0.05rem;}.icon3{width: 0.71rem;height: 0.74rem;background-position: -3.91rem -0.02rem;}.icon4{width: 0.72rem;height: 0.73rem;background-position: -5.91rem -0.03rem;}.icon5{width: 0.73rem;height: 0.73rem;background-position: -7.92rem -0.01rem;}.icon6{width: 0.67rem;height: 0.57rem;background-position: -9.96rem -0.08rem;}
}

我们平常使用background-size: 100%|cover|contain只是根据元素的宽高进行缩放的,那只对单张图片有用,因为此时百分比的大小是相对于元素的大小的,也就是说,一个100px*100px的div,使用一张1000px*1000px的sprite图做背景图片的,如果此时你给div加上background-size: 100%|cover|contain的话,那么整张sprite图就会被压缩成100*100的大小,这恐怕不是你想要的吧。

而我们的sprite是要根据它的原始大小来进行缩放的,先把px转化为rem,按照我的习惯是直接除以100px。也就得到类似background-size: 10.72rem 4.42rem;(原始1072px*442px)。这样sprite图就可以根据font-size进行缩放了。而且定位background-position直接使用原始的left-top 值除以100px就可以了,就是那么简单。那我们直接上效果图:

看,是不是感觉适配得还不错。对的,大体上是可以了,但是呢,认真看看有一些手机里面,总会发现有点缺陷,有些图片少了那么1px,其实如果要求不严格的话这样也就差不多了。但是本着精益求精的原则,我们肯定是需要解决这个问题的。于是在网上查找,功夫不负有心人

属性值为百分比时,将以图片的 中心点 为基准计算其相对位置,而使用px像素值时将以图片的 左上角(0 0)为基准。如果是10% 20%的这个值,那么就以图片的10% 20%的坐标点,放置在容器的10% 20%的位置。那这样理解的话,就是说明,如果是用百分比来作 background-position 的属性值的话,那么背景图片相对于容器的中心点是随时都在改变的。

属性值为百分比时,将以图片的 中心点 为基准计算其相对位置,而使用px像素值时将以图片的 左上角(0 0)为基准。如果是10% 20%的这个值,那么就以图片的10% 20%的坐标点,放置在容器的10% 20%的位置。那这样理解的话,就是说明,如果是用百分比来作 background-position 的属性值的话,那么背景图片相对于容器的中心点是随时都在改变的。
按照我的理解,就是把sprite图上的某一个点移动到元素上的某一个点,让这两个点重合。举个例子:我有一个400*400的div,200*200的sprite图,然后我给元素设置了background-position: 100% 100%;那么我们先找出这两个点,元素的(100% 100%)点A就是元素的右下角,sprite图的(100% 100%)点B在sprite图的右下角。如图

加了background-position: 100% 100%;之后,就是把sprite图的B点移动到A点。如图

,就是这么个情况。代码如下:

<style type="text/css">.box{width: 400px;height: 400px;border: 1px solid #ccc;margin: 100px auto;background: url(../images/200-1.jpg) no-repeat;background-position: 100% 100%;}
</style>
<div class="box"></div>

但是这个是在我们知道百分比的情况下的,而我们需要做positon定位的时候需要的正是这个百分比,所以我们应该根据其他的变量把百分比求出来。我们可以把以上的情况转换成跟元素、sprite图、坐标有关的场景,比如类似:

当给元素加background-position: 10% 20%的时候,sprite图会先参考自身移动(-10% -20%)也就是改变自己的中心点,然后再根据元素的宽高来移动(10% 20%),最后sprite图会移动到一个点(X Y)。这个点就是我们需要显示在元素中icon的坐标。根据这个方式,总是可以把sprite图的某个点定位到元素的(0 0)位置。

那重新梳理一下:
如果使用px来定位的话,那么sprite图是以左上角(0 0) 为中心点的,比如加上background-position:10px 20px;(此时sprite图的中心点在(0 0))那么图片的左边缘跟上边缘会往下移动20px,往左移动10px;我们平常使用的也是这种情况。

但是使用百分比来定位的话,那图片就不是以左上角为中心点了。比如加上background-position:10% 20%;那么背景sprite图片的中心点就会改变成图片 (10% 20%) 这个点了,比如原始sprite图片宽度为50px*50px,原始原始的中心点是(0 0);加了background-position:10% 20%;之后呢,中心点就变成了 (50px*10%  50px*20%) 也就是(5px, 10px)这个点,然后就会根据这个中心点来进行移动,假设元素的大小为200px*200px,根据推理,加了background-position:10% 20%;移动的步骤类似如下:

1、背景图片sprite图的中心点会改变成图片 10% 20% 这个点 即50*10% 50*20% 也就是(5px, 10px)(相当于把sprite图先移动(-5px -10px),也就是把sprite图的中心点移动端元素的左上角(0 0)处);

2、然后以sprite图的(5px 10px)点为中心点移动元素宽高度的10% 元素高度的20%,也就是往右往下移动了 20px 40px;
需要注意的是,这次的移动是以(5px 10px)这个中心点来移动的,就是把这个点先移动到父元素 0 0 的位置,再移动 20px 40px;
所以最终移动的距离是 (-5px+20px -10px+40px) 也就是 向右移动了15px 向下移动了30px 。

根据以上的推理,要想得到定位的百分比值(n m),我们需要 元素的宽高(w h), sprite图的宽高(k g),我们需要显示icon的坐标(x y),我们以向右向下移动端为正,向上向左为负。可以得到计算公式如下:

left: -n* k + n*w = -x
top: -m* g + m*h = -y

根据上面的公式,我们可以得到:

n = -x / (w-k) * 100%
m = -y / (h-g) * 100%

那举个例子:我们有一张200*200的sprite图,需要显示黄色的区块。


当我们的div宽度为 100*100时,可以得出n:100%, m: 100%,所以我们应该给元素加上background-position: 100% 100%;代码及效果如下:

<style type="text/css">.box{width: 100px;height: 100px;border: 1px solid #ccc;margin: 100px auto;background: url(../images/200-1.jpg) no-repeat;background-position: 100% 100%;}
</style>
<div class="box">
</div>

当div的宽度为 150*300时,可以得出n:200% m: -100%;所以我们应该给元素加上background-position: 200% -100%;效果如下

经过验证,上面的计算公式的确是可以的,就是那么简单。但是我们也不能用一次就算一次吧,经过以上公式的整理,可以用sass写出一个fucntion 或者mixin,代码如下:

//$spriteWidth 雪碧图的宽度px
//$spriteHeight 雪碧图的高度px
//$iconWidth 需要显示icon的宽度px
//$iconHeight 需要显示icon的高度px
//$iconX icon的原始x坐标
//$iconY icon的原始y坐标
//
@mixin bgPosition($spriteWidth, $spriteHeight, $iconWidth, $iconHeight, $iconX, $iconY){background-position: (($iconX / ($spriteWidth - $iconWidth)) * 100% ($iconY / ($spriteHeight - $iconHeight)) * 100%);
}//使用的方式
.test-sprites{margin-top: 30px;ul{padding: 0;margin: 0;}li{width: 0.48rem;height: 0.7rem;overflow: hidden; box-sizing: border-box; margin-left: 0.3rem;float: left;background:transparent url('http://nos.netease.com/edu-image/9BC0742AEB1A0B756EFC71B9DF77E452.png') 0 -0.02rem no-repeat;background-size: 10.72rem 4.42rem;}.icon2{width: 0.74rem; height: 0.64rem;@include bgPosition(1072, 442, 74, 64, 188, 5); }.icon3{width: 0.71rem;height: 0.74rem;@include bgPosition(1072, 442, 71, 74, 391, 2);}.icon4{width: 0.72rem;height: 0.73rem;@include bgPosition(1072, 442, 72, 73, 591, 3); }.icon5{width: 0.73rem;height: 0.73rem;@include bgPosition(1072, 442, 73, 73, 792, 1); }.icon6{width: 0.67rem;height: 0.57rem;@include bgPosition(1072, 442, 67, 57, 996, 8);}
}

就是下面这个图片,按照这样的方式,经过实践是没有问题的


但是呢,以上的bgPosition感觉不够简洁,因为每次都要输入sprite图的宽高,那么可以在bgPosition的基础上再拓展一下;

//同一张sprite图,横图
@mixin bgPositionSameSprite($iconWidth, $iconHeight, $iconX, $iconY){$spriteWidth : 1072;$spriteHeight : 442;@include bgPosition($spriteWidth, $spriteHeight, $iconWidth, $iconHeight, $iconX, $iconY);
}//同一张sprite图、竖图
@mixin bgPositionSameSprite-tow($iconWidth, $iconHeight, $iconX, $iconY){$spriteWidth : 300;$spriteHeight : 1000;@include bgPosition($spriteWidth, $spriteHeight, $iconWidth, $iconHeight, $iconX, $iconY);
}

这样我们就只要输入四个参数了,那还能不能再简洁点呢,那只能看情况了,如果你的每个icon大小都一样的话,是完全没有问题的,你只需要输入每个icon的坐标就行,比如这样的图


然后你就可以写这样的一个方法

//同一张sprite图并且每个icon的大小相同
@mixin bgPositionSameSpriteAndWidth($iconX, $iconY){$spriteWidth : 220;$spriteHeight : 220;$iconWidth : 61;$iconHeight : 61;@include bgPosition($spriteWidth, $spriteHeight, $iconWidth, $iconHeight, $iconX, $iconY);
}
//使用
i{padding-top: 100%;width: 100%;display: block;background: url(http://nos.netease.com/edu-image/3A65D313376F13CE75CE01C2593BD1CE.png) 0 0 no-repeat;background-size: 2.2rem 2.2rem;
}.i-sina{@include bgPositionSameSpriteAndWidth(10, 10);
}.i-qzone{@include bgPositionSameSpriteAndWidth(80, 10);
}.i-qq{@include bgPositionSameSpriteAndWidth(150, 10);
}.i-douban{@include bgPositionSameSpriteAndWidth(10, 80);
}.i-yixin{@include bgPositionSameSpriteAndWidth(80, 80);
}.i-renren{@include bgPositionSameSpriteAndWidth(150, 80);
}

以上方式方案可以完美解决适配定位问题,还能解放生产力。如果有不对的地方,还望指正。

参考文献移动端适配之雪碧图(sprite)背景图片定位

移动端适配之雪碧图(sprite)背景图片定位相关推荐

  1. 雪碧图 sprite

    1.什么是雪碧图 在网站开发中很多时候要用到雪碧图.雪碧图的意思就是说将一些log 商标 标志 等在网页中需要用到的背景图片整合 到一张图片当中.这样的话.然后通过background-positio ...

  2. 前端开发工具介绍----合成雪碧图工具(css sprite)

    合成雪碧图Sprite工具 1.国外的在线合成工具:http://csssprites.com/ 选择需要合并的文件----设置option选项(包括:元素的间距,排列方式,背景颜色,边框)----- ...

  3. 在html中雪碧图的坐标怎么看,详解CSS Sprite雪碧图的应用

    CSS雪碧图,即CSS Sprite,也有人叫它CSS精灵图,是一种图像拼合技术.该方法是将多个小图标和背景图像合并到一张图片上,然后利用CSS的背景定位来显示需要显示的图片部分. 雪碧图的使用场景 ...

  4. CSS Sprite雪碧图详解

    CSS雪碧图,即CSS Sprite,也有人叫它CSS精灵图,是一种图像拼合技术.该方法是将多个小图标和背景图像合并到一张图片上,然后利用CSS的背景定位来显示需要显示的图片部分. 雪碧图的使用场景 ...

  5. grunt压缩雪碧图

    grunt 打包雪碧图 插件grunt-spritesmith 简易配置 // 项目配置(任务配置)grunt.initConfig({// 读取我们的项目配置并存储到pkg属性中pkg: grunt ...

  6. CSS 背景图标(雪碧图、精灵图、iconfont)

    目录 雪碧图(精灵图) icon-font 雪碧图(精灵图) 特点: 一个网站有很多背景图(一般是系统UI图片, 不是用户自己上传的那种)时, 会多次向服务器发起请求, 造成服务器压力. 为了解决这个 ...

  7. css sprit雪碧图制作,使用教程

    写在前面: 在网页制作中,雪碧图也是前端攻城狮必须掌握的一项小技能.百度词条对雪碧图的解释是:CSS雪碧 即CSS Sprite,也有人叫它CSS精灵,是一种CSS图像合并技术,该方法是将小图标和背景 ...

  8. css中雪碧图(sprite)的使用及制作方法

    雪碧图(sprite)是减少请求次数的有效手段,其原理是把多张图片进行合成,使用时通过css进行定位. 1.先看一下雪碧图 没有使用雪碧图时图标是这样一个个的单独文件: 合成雪碧图后是这样拼在一起的一 ...

  9. 雪碧图sprity 合并多图使用心得

    介绍 sprity 是一个模块化的雪碧图生成工具 会根据目录中的图片生成相应的雪碧图和样式文件,支持retina图,可以内嵌base64 编码格式的图,支持不同的图片格式和有不同的图片引擎可以选择. ...

最新文章

  1. 一行命令搞定图像质量评价 | 附代码和操作步骤
  2. 创业公司自曝「被谷歌封杀」,阻断一切访问,上诉只得到机器人回复
  3. p750tm安装linux系统,Android 开发环境(虚拟机,LINUX, secureCRT)安装过程.pdf
  4. PHP is_null,empty以及isset,unset的区别
  5. Angular Component 的 renderer 创建机制以及 Angular 版本号的确定方式
  6. 数据库Mysql的学习(六)-子查询和多表操作
  7. if __name__ == __main___一文带你弄懂python中if __name__ == #39;__main__#39;
  8. oracle关于字符串函数,Oracle字符串处理函数
  9. GlusterFS更换故障Brick
  10. mysql学生信息管理系统设计_学生信息管理系统的设计与实现(MyEclipse,MySQL)
  11. 老司机教你如何快速入门Linux | 小白必知
  12. html轮播图背景色,轮播图的做法(更换背景颜色)
  13. 计算机怎么使用远程桌面工具,win7一键开启远程桌面工具
  14. 关于BUCK-BOOST电路的负压生成
  15. CF卡显示位置不可用无法访问介质受写入保护怎么办
  16. 三菱Q系列通过wifi联服务器,三菱Q系列PLC以太网通讯,三步可以搞定!
  17. linux pam limits.so,linux – 即使需要pam_limits.so,ulimit也不会读取打开文件描述符limits.conf设置...
  18. 用matlab作乌鸦喝水,仿真程序动画作品--乌鸦喝水
  19. win凭据添加计算机名,使用Windows凭据管理自动登录局域网的方法
  20. IBM MQ部署实施过程详解

热门文章

  1. 文墨绘学:小学语文考什么?
  2. 2022-4-1 Leetcode 面试题10.01合并排序的数组
  3. 北京中考英语听说计算机考试时间,2019年北京中考英语听说考时间确定
  4. 界面美化专家——有道桌面小词典篇
  5. ATmega16 定时计数器器应用
  6. 6G中的卫星通信高效天基计算技术
  7. 使用sqlserver2008时找不到配置管理器
  8. UE4之不失比例的贴图
  9. slic去除识别效果图中的裂纹(修改opencv中的库函数)
  10. 川崎机器人signal_川崎机器人常用指令表