仿微信小程序 aspectFitImg 算法,完美适配全尺寸公司Logo的处理

微信小程序的image组件中,有一个mode属性,其设置如下:

mode 有 13 种模式,其中 4 种是缩放模式,9 种是裁剪模式。

模式 说明
缩放 scaleToFill. 不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素
缩放 aspectFit 保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。
缩放 aspectFill 保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。
缩放 widthFix 宽度不变,高度自动变化,保持原图宽高比不变
裁剪 top 不缩放图片,只显示图片的顶部区域
裁剪 bottom 不缩放图片,只显示图片的底部区域
裁剪 center 不缩放图片,只显示图片的中间区域
裁剪 left 不缩放图片,只显示图片的左边区域
裁剪 right 不缩放图片,只显示图片的右边区域
裁剪 top left 不缩放图片,只显示图片的左上边区域
裁剪 top right 不缩放图片,只显示图片的右上边区域
裁剪 bottom left 不缩放图片,只显示图片的左下边区域
裁剪 bottom right 不缩放图片,只显示图片的右下边区域
原图
0.jpg

scaleToFill

不保持纵横比缩放图片,使图片完全适应

1.png

aspectFit

保持纵横比缩放图片,使图片的长边能完全显示出来(图片可完整显示,背景区域有留空)

2.png

aspectFill

保持纵横比缩放图片,只保证图片的短边能完全显示出来(图片被剪裁,丢失部分内容)

3.png

为什么要仿造一个微信小程序的aspectFitImg算法?

在微信小程序页面开发时,以绘制公司logo为例,

我希望得到的显示效果如下:

(Logo和公司名称在视觉上完美左对齐)

对于公司Logo这样的图案,是必须完整显示并保持比例的,任何对内容的剪裁或比例失调都是无法令人接受的。

WeChatb80f558533af46c67164f35ad22c27a2.png

为实现这个效果,我们通常的做法是:直接指定图片元素的显示模式为aspectFit模式,然后将公司Logo和公司名称左对齐。

但是这样会产生排版上的瑕疵,例如:

假设图片的缺省占位宽高为:100px * 40px;
但是从网络加载的图片实际只有40px * 40px

那么实际图片的水平中心点将在占位宽度(100px)的水平正中间对齐显示,看起来就好像实际图片左边被留出了30px的宽度,即:(100-40)/2,而这种情况不是我们想要的,因为我们想要的是从视觉上看,图片和底下的元素应该可以左对齐,而不是仅从CSS的视角来看两个元素是左对齐的;

此时,肉眼看见的效果如下:

logo图片占位和公司名称在CSS的层面左对齐,但是从视觉上来看,logo和公司名称并没有左对齐;


WeChatd22b342f3426ec9f68f88235fc6f6463.png

在微信小程序中,我解决这个问题的方法是:

(1)首先,在CSS中使用默认的占位宽高来设定图片的显示属性,打比方:{100px,40px},并设置数据绑定属性;
(2)从网络下载图片,然后根据{100,40}这个初始限定来计算将实际图片(可能是400px * 400px)缩放到刚好能塞进这个占位框中时图片应该被显示的尺寸,即(40px * 40px);
(3)使用微信小程序中css属性绑定的机制来修改占位框的宽度和高度;即将{100px * 40px}动态修改为 {40px * 40px};


在微信小程序中设置css属性绑定、下载图片并获取图片的宽高信息等都有现成的方法和完善的API说明文档,不再言表,仅列出那个aspectFitImg的方法。

/**
 * imgSourceWidth,imgSourceHeight : 图片的原始高度;
 * fitWidth,fitHeight: 图片保持比例缩放后,要能够塞进这个大小范围内;
 * 返回对象为适配处理后的图片尺寸,该尺寸是刚刚好可以装到fitWidth和fitHeight中的,不多一个像素,也不少一个像素,并且保持原始的图片宽高显示比例;
 * 返回示例:{width:100,height:100}
 * 如果计算失败,返回null
 */
function aspectFitImg(imgSourceWidth, imgSourceHeight, fitWidth, fitHeight) {
  if (isNull(imgSourceWidth) || isNull(imgSourceHeight) || isNull(fitWidth) || isNull(fitHeight)) {
    return null;
  }
  if (imgSourceWidth > fitWidth) {
    let d = imgSourceWidth / fitWidth;
    let th = imgSourceHeight / d;
    return this.aspectFitImg(fitWidth, th, fitWidth, fitHeight);
  } else if (imgSourceHeight > fitHeight) {
    let d = imgSourceHeight / fitHeight;
    let tw = imgSourceWidth / d;
    return this.aspectFitImg(tw, fitHeight, fitWidth, fitHeight);
  } else if (imgSourceWidth <= fitWidth && imgSourceHeight <= fitHeight) {
    return { width: imgSourceWidth, height: imgSourceHeight };
  } else {
    return this.aspectFitImg(imgSourceWidth, imgSourceWidth, fitWidth, fitHeight);
  }
}

浪费了30分钟修改文章,午饭要加个鸡腿奖励一下自己..

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、属性选择器:id选择器 # 通过id 来选择类名选择器 . 通过类名来选择属性选择器 ...
    Yuann阅读 5,556评论 0 7
  • 一、CSS入门 1、css选择器 选择器的作用是“用于确定(选定)要进行样式设定的标签(元素)”。 有若干种形式的...
    宠辱不惊丶岁月静好阅读 5,539评论 0 6
  • 关键词: 微信小程序 图片真实大小 图片模式详解 这两天自己设计了两张微信广告横幅,电脑设计尺寸为750*300像...
    黄雨晴阅读 7,775评论 1 0
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    love2013阅读 6,820评论 0 11
  • 输液真是等于自杀吗?首先这个命题是完全荒唐的。难道不输液什么病都可以靠吃药、打针、或者其它方法治好吗?外国人不主张...
    正举阅读 2,701评论 0 0