响应式SPRITES图片实现方法探究

腾讯云正在走向全面支持响应式和Retina屏的道路上,我们广泛使用了SVG Sprites技术。在实践过程出现了“某些元素的背景图片来自于一张SVG Sprites,同时该元素也需要支持响应式”的情况,就需要解决“在元素尺寸发生变化时,来自Sprites的这张背景图片如何同步等比缩放?“的问题。

我曾经探讨过“响应式图像”的实现方法,当然这些方法都不适用背景图。我们来分解下这个问题,具体要完成哪些任务?

HTML元素在缩放时,如何保持宽高比不变?

对于这个问题,我在“使用PADDING-TOP:(PERCENTAGE)实现响应式背景图片”这篇文章中给出了解决方法,不再赘述。

See the Pen responsive image sprites 1 by wenjul (@wenjul) on CodePen.

Sprites中的背景图片如何跟随容器尺寸的变化而等比缩放?

background-size正是用来解决这个问题的。大家应该比较熟悉关键字“cover“(缩放背景图片以完全覆盖背景定位区,可能背景图片部分看不见)和”contain“(缩放背景图片以完全装入背景定位区,可能背景定位区部分空白)的效果,这两个关键字主要解决整张背景图如何适应容器,比较适用于单张图片,不适用于Sprites图。

如何计算background-size: <percentage>?

百分比值(<percentage>)是背景图相对于背景定位区(background positioning area)的百分比,可以控制在容器元素内仅显示Sprites图的部分内容。比如下图中,Sprites图是由四张头像拼成的,要想在容器内仅显示第一张头像,background-size的值应该多少呢?

demo-1

先看下100%的效果,也就是说Sprites图和容器是1:1的比例,显然不是我们要的效果。

demo-2

我们仅需要Sprites图的1/4显示在容器内,那么Sprites图与容器的比例应该是4:1,计算公式为:

background-size : ( Sprites width / image width) (Sprites height / image height)

demo-3

上面这个公式比较容易理解,但是如何在容器元素显示其他的头像呢?

当然是通过background-position来改变背景图片的初始位置。我们通常使用<length>(如px)控制背景图片相对于容器元素的偏移量,显然不适用我们这种情况,因为整张Sprites图片是可以等比缩放的,那么单张图片的左上角相对于Sprites图片的左上角的距离也是变化的,所以使用<length>是会出错的,如下例。

demo-4

如何计算background-position: <percentage>?

background-position值还可以使用 <percentage>和关键词(top, bottom, left, right, center),可以把关键词理解为<percentage>特殊形式,两者的计算方式是相同的。但是,<percentage>和<length>的计算方式是不同的:<length>的参照点是图片的左上角,<percentage>的参照点是随着取值变化的。

background-position:30px 40px; 为例,计算方法为:Sprites图的左上角相对于容器元素的左上角向右偏移30px,向下偏移40px。

demo-5

background-position:<percentage>就大不同了:如background-position:0% 0%(或top left)是将图片的左上角与容器元素的左上角对齐,background-position:100% 100%(或bottom right)是将图片的右下角与容器元素的右下角对齐,background-position:50% 50%(或center center)是将图片的中心点与容器元素的中心点对齐,background-position:33% 15%是将图片的横向33%和纵向15%的交汇点放置在容器元素的横向33%与15%的交汇点上。

demo-6

理解 <percentage>和<length>之间计算方式的差异是至关重要的。那么如果要在容器元素内显示第二张图片,怎么计算<percentage>的具体值呢?

demo-7

我们已知的信息如下:

  • 容器元素的尺寸:elW * elH
  • 单张图片的尺寸:imgW * imgH
  • Sprites图片的尺寸:spritesW * spritesH
  • 单张图片在Sprites图上的位置:imgPosX, imgPosY

我们假设:

  • 点的位置为 (x, y)
  • 容器上的(x, y)点与容器左上角的距离为 cX, cY
  • Sprites图上的(x, y)点与本张图片左上角的距离为 sX, sY

如果要把某张图片完全显示在容器元素内,我们可以推导出:

  • elW = imgW, elH = imgH
  • cX = sX, cY = sY

根据上面的信息,我就可以计算出具体的(x, y)值了,下面以 x% 为例:

  • cX = elW * x
  • sX = spritesW * x – imgPosX
  • elW * x = spritesW * x – imgPosX

解方程后就得到计算公式了:

  • x = imgPosX / (spritesW – elW) = imgPosX / (spritesW – imgW)
  • y = imgPosY / (spritesH – elH) = imgPosY / (spritesH – imgH)

把我们上面例子的信息代入方程式:

  • x = w / (4w -w) = 1/3
  • y = 0 / (h – h ) = 0

查看效果

手动计算累死人?Maxim来解救你!

Maxim是我们团队开发的可视化的构建工具,支持windows和Mac,开发时无需考虑background-sizebackground-position,发布时将文件拖入Maxim内,自动完成Sprites拼合,并补全background-sizebackground-position值,轻松实现响应式Sprites图。Maxim的更多功能也等你发现,赶快下载一个试试吧!!!

《响应式SPRITES图片实现方法探究》有1个想法

发表评论