在 iOS 开发中如何优雅地进行图片缩放?

对于图片拉伸是移动开发中很常见的需求,在前一阵子做项目中需要做一个类似于QQ聊天气泡,这个气泡会根据文字的多少而变化,当时有了三种方案:

  • 重写drawRect方法,使用贝赛尔曲线画一个气泡
  • 用一个大图作为背景,管它怎么拉伸,肯定不会变形
  • 使用图片,同时使用系统提供的API对图片进行局部拉伸

来分析一下这三种做法利弊:

  • 第一种:劳民伤财,drawRect的使用带来离屏渲染,如果滑动聊天界面将使内存急剧增加,同时我也不会使用贝赛尔曲线,呜呜!
  • 第二种:大图的话,显然所占空间会比较大,这样导致最后的安装包较大,尺寸不合适的图片加载也会对性能有所影响
  • 第三种:显然这是一种划算的做法,对于怎么进行局部拉伸也是这篇博客的重点

代码实现图片缩放

至于 iOS 5 之类的方法,这里就不再谈了。在 iOS 6 的时候,系统为我们提供了这样一个方法

    public func resizableImageWithCapInsets(capInsets: UIEdgeInsets, resizingMode: UIImageResizingMode) -> UIImage

对于拉伸的方式,有以下两种:

  • IUIImageResizingModeStretch:拉伸模式,通过拉伸UIEdgeInsets指定的矩形区域是我们要保护的区域,也就是不被拉伸的区域
  • UIImageResizingModeTile:平铺模式,通过重复显示UIEdgeInsets指定的矩形区域是要保护的区域,也就是不被重复显示的区域

拉伸模式

来做四个测试,假如我们的原始图像尺寸为60*128当我们设置capInsets为以下四种值的时候有什么样子的效果:

  • 1:capInsets参数为UIEdgeInsetsMake(0, 0, 0, 0)
  • 2:capInsets参数为UIEdgeInsetsMake(42, 0, 0, 0)
  • 3:capInsets参数为UIEdgeInsetsMake(0, 20, 0, 0)
  • 4:capInsets参数为UIEdgeInsetsMake(42, 20, 42, 20)

在一个180*384的窗口进行测试图像,对于实践的结果,可以在这个地址中看到。

四种测试结果是:

  • 1: 原始图像拉伸,比例放大
  • 2: 我们对图片上面的区域进行了保护,其他区域进行了拉伸,保护区域在Y轴保持了原比例,但是X轴方向进行了拉伸
  • 3: 我们对图片的左侧区域进行了保护,其他区域进行了拉伸,保护区域在X轴保持了原比例,但是在Y轴方向进行了拉伸
  • 4: 我们对除了中心区域的位置进行了保护,中心区域进行了拉伸,四个角进行了双层保护,其余被保护区域在X、Y轴的拉伸与第2、3种情况下相同,效果图如下:
效果图4

平铺模式

与上面的场景相同,只不过不再拉伸,改为平铺的方式,来尝试以下四种情况:

  • 1:capInsets参数为UIEdgeInsetsMake(0, 0, 0, 0)
  • 2:capInsets参数为UIEdgeInsetsMake(42, 0, 0, 0)
  • 3:capInsets参数为UIEdgeInsetsMake(0, 20, 0, 0)
  • 4:capInsets参数为UIEdgeInsetsMake(42, 20, 42, 20)

在一个180*384的窗口进行测试图像,对于实践的结果,可以在这个地址中看到。

结论就是:

  • 1: 按比例平铺
  • 2: 我们对图片上面的区域进行了保护,其他区域按比例平铺,保护区域在Y轴保持了原比例,但是X轴方向进行了平铺填充
  • 3: 我们对图片的左侧区域进行了保护,其他区域按比例平铺,保护区域在X轴保持了原比例,但是在Y轴方向进行了平铺填充
  • 4: 我们对除了中心区域的位置进行了保护,中心区域按比例平铺,四个角进行了双层保护,其余被保护区域在X、Y轴的平铺与第2、3种情况下相同,效果图如下:
效果5

注: 以上的代码测试来自SketchK七爷

Image Slicing 可视化缩放

何为Image Slicing呢?,其实就相当于一个可视化的resizableImageWithCapInsets,可以用于指定在图片缩放时用来填充的像素。我们可以在XcodeAssets.xcassets目录中选择要slicing的图片,点击图片界面右下方的Show Slicing按钮,在想要设定切片的图片上点击Start Slicing,将出现左中右(或者上中下)三条可以拖动的指示线,通过拖动它们来设定实际的缩放范围。

我们刚才说,他就是可视化的resizableImageWithCapInsets,那么它的capInsets在哪里呢?打开图片对应的.json文件,代码如下:

{
  "images" : [
    {
      "resizing" : {
        "mode" : "9-part",
        "center" : {
          "mode" : "tile",
          "width" : 42,
          "height" : 92
        },
        "cap-insets" : {
          "bottom" : 0,
          "top" : 95,
          "right" : 41,
          "left" : 0
        }
      },

从文件可以看出来topleftbottomright对应的就是上左下右的指示线,看到modetile,就知道Image Slicing默认为平铺缩放,对于widthHeight是做什么的呢?Width代表的是左侧线(或者上方线)和中间线之间的区域,Height代表的是上侧线和中间线之间的区域。

看一下刚才图片运行起来的效果

测试结果

很神奇呀!灰色区域都会被隐藏,我们发现灰色区域位于右侧线与中间线或者下方线与中间线之间。来分析一下各个数字的平铺:

  • 3位与右侧线的右侧,不会发生变化
  • 1位与左侧线与中间线之间,Y轴保持比例不变,X轴平铺
  • 6位与右侧线的右侧,但是也位与上方线与中间线之间,所以会保持X轴不变,Y轴平铺
  • 4位与左侧线与中间线之间,同时也位与上方线与中间线之间,会填充其他所有的空余区域。

好绕啊!还是可视化比较简单,只要手动调试一下,就可以比较直观的看到效果,希望可以帮到你,Demo可以进行下载。

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

推荐阅读更多精彩内容