4.5 image组件的4种缩放模式与9种裁剪模式
4种缩放模式和9种裁剪模式如果从理论上完全精确理解,还是有稍许的难度的。但这里笔者建议各位开发者,没有必要完全从理论上搞清楚这些模式。当遇到具体问题时,尝试多去更换几个属性,找到最适合自己需求的属性即可。
来看看上个小节中雪糕图片的显示问题,很明显整个图片被压缩变形了。这并不是我们想要的结果。
post-image这个元素的高宽分别被设置成340rpx和100%(iPhone 6下就是750rpx),而雪糕图片素材原始高宽分别为600px和750px。
在现实的项目中,我们经常要面对原始图片的尺寸和设计图里的尺寸不一样的情况(尤其是原始图片高宽是未知和不固定的情况,比如动态从网络获取图片)。在这种情况下,我们必须要有所舍弃,或放弃等比例,或裁剪掉图片的一部分。接受不完美,也是编程中很重要的心态,如何选择,需要看业务上的需求。具体到文章列表图片,我们需要的是保持宽高比,接受部分裁剪(现实项目中,绝大多数情况下,图片保持比例、允许裁切是最普遍的需求)。
小程序的image组件提供了4种缩放模式和9种裁剪模式,来支持我们的选择。
4种缩放模式
• scaleToFill 不保持纵横比缩放图片,使图片的宽高完全拉伸至填满image元素。
• aspectFit 保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。
• aspectFill 保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
• widthFix 宽度不变,高度自动变化,保持原图宽高比不变(0.11.122100版本新增)。
9种裁剪模式
• top 不缩放图片,只显示图片的顶部区域。
• bottom 不缩放图片,只显示图片的底部区域。
• center 不缩放图片,只显示图片的中间区域。
• left 不缩放图片,只显示图片的左边区域。
• right 不缩放图片,只显示图片的右边区域。
• top left 不缩放图片,只显示图片的左上边区域。
• top right 不缩放图片,只显示图片的右上边区域。
• bottom left 不缩放图片,只显示图片的左下边区域。
• bottom right 不缩放图片,只显示图片的右下边区域。
每种模式的字面意思都很好理解。要更改图片的裁剪或缩放模式,只需要给image组件加上一个mode属性值。
我们来看一下这13种不同属性值的实际效果。
4.5.1 scaleToFill
给代码清单4-6中class="post-image"的image组件加上一个mode属性值。如代码清单4-9所示。
保存预览一下,文章图片好像并没有发生任何变化。
这是因为scaleToFill模式是缩放的默认模式,如果缺省了mode,则小程序也会以scaleToFill的模式来缩放图片。scaleToFill模式将改变图片的高宽比,强行让图片更改为样式指定的尺寸,使图片变形(如果原始图片的宽高比例和要缩放的目标宽高比例相同,则不会变形,只是整体上放大或者缩小了)。
4.5.2 aspectFit
再来看看mode=aspectFit的情况,如图4-8所示。
图4-8 mode=aspectFit的效果
同样不是我们要的效果。官方文档的解释:aspectFit模式保持纵横比缩放图片,使图片的长边能完全显示出来。这个解释从字面上来看,并不是很容易理解,我们可以这样理解这种模式。
假想有一个容器,这个容器的高宽等同于image将要被缩放的目标尺寸。比如在当前的事例中,这个容器的高宽就是样式post-image所设置的高320rpx,宽100% (iPhone 6下为750rpx)。aspectFit的特点就是保持图片不变形,且容器要“刚好”将这个图片装进去。注意,是“刚好”。如果原始图片比容器大,就要被等比例缩小;而原始图片如果比容器小,则要被等比例放大。一直放大或者缩小到图片的某一条边刚好和容器的一条边重合,而另一条边不能超出容器,也不能小于容器太多。
再回头看看图4-8,宽刚好和容器相贴合,而高则刚好能被容器装进去,既没有超出容器,也没有比容器矮太多。同时整个图片保持了原始图片的宽高比,没有变形。
所以官方文档的解释,没有把这种模式的特点完全描述出来。
事例里用到的图片是大于容器的,所以图片会被缩小;开发者们可以尝试着用一张小于容器的图片替换这张雪糕图,试试aspectFit的效果。
效果如图4-9和图4-10所示。
图4-9 aspectFit效果,“刚好”贴合容器
图4-10 aspectFit不可能出现的情况,图片没有同容器贴合
4.5.3 aspectFill
再看看mode=aspectFill的效果,如图4-11所示。
图4-11 mode=aspectFill的效果
aspectFill同样保持图片的高宽比不会变形。但它有个特点,它会让图片完全填满整个容器,类似于scaleToFill这种模式。不同的是,scaleToFill会改变图片的高宽比,而aspectFill不会。
用我们上面提到的“容器”的观点来理解aspectFill。既然aspectFill一定要填满整个容器,那么首先要让这张图片的整体尺寸是大于这个容器的,不能留下任何的空白。对于原始尺寸小于容器的,就等比例放大图片(任意一边小于容器都需要放大,否则就会留下空白),让图片的某一边刚好接触容器的一边,同时另外一边又不会小于容器(可以超出,因为这一边会被截取)。
如果原始尺寸大于容器,则需要等比例缩小,缩小的要求同样是一边刚好接触容器,另外一边要等于或者超出容器。这样就保证了图片可以完全填满整个容器,但某一边要发生截取。那么问题来了,如何截取?在超出容器的这一边上,是保留图片的上部、中部还是下部?答案是:中部。
注意观察图中的雪糕和原始图片,发现正中间部分被保留了下来。开发者可以自行多换几张素材图看看截取的效果。
4.5.4 widthFix
widthFix属性是小程序0.11.122100版本中新增的属性。这个属性的最大特点是,图片将不会按照设定的尺寸呈现,比如设置image宽度为750rpx,高度为340rpx,如果设置mode=widthFix,则图片最终不会按照750rpx和340rpx呈现,除非原始图片恰好是这个尺寸。
这个属性让宽缩放至指定尺寸,再动态计算高度,如图4-12所示。
图4-12 widthFix的效果
虽然宽度按照我们设定的尺寸呈现,但高度突破了340rpx。
4.5.5 9种裁剪模式
9种裁剪模式非常容易理解,我们举例看看其中的几种。同样建议开发者参考上一小节中,我们想象的一个容器,这个容器用来裁剪图片的不同部位。
将post-image的mode属性设置为top,效果如图4-13所示。
top模式只保留图片的上部,裁剪掉了剩余部分。注意,这种模式不会缩放图片。我们可以仔细地再观察一下图中的图片,不仅仅是裁剪掉了图片的下部,上部水平方向也发生了裁剪。因为图片不会缩放,我们所设置的容器不能够在水平方向上完全把图片装进去,所以水平方向也发生了裁剪。这点是大家要注意的。
不同于4种缩放模式,裁剪模式是不会缩放图片的。用一张小图片来替换上面的大图,比如用avatar头像图片,替换后的效果如图4-14所示。
明显可以看到,由于图片的原始尺寸小于容器的尺寸,裁剪模式也不会使图片发生缩放,所以结果就是不会裁剪图片。
接着我们再将mode设置为bottom right,效果如图4-15所示。
图片只被保留了右下角部分,其余部分全部被裁剪掉了。
其他几种裁剪类型从字面意思上都非常好理解,就不在这里一一列举了,开发者可以自行替换mode的属性值,看看裁剪效果。
图4-13 mode=top
图4-14 一张小图没有发生任何裁剪行为
图4-15 mode=bottom right时的效果