现在的 canvas 不能像 h5的 canvas 一样把 画布大小 和 显示大小分别设置,且 canvas 不能 `display:none`。
分享下我的处理方法:
把 canvas 包裹在一个 view 中, 然后把这个 view 高度变成 0,`overflow: hidden` 掉, 也可以把它定位出去。总之就是利用类似的方法把 canvas 隐藏。然后在绘制 canvas 结束后把 canvas 导出到 tempfile,用 img src 去加载。这样可以设置一个较大的画布,但展示成想要的尺寸。 缺点是不能实时渲染展示,导出操作比较消耗性能。 另外还有一个坑: context.draw 的 callback 虽然执行了,但在 android 下不能直接导出 tempfile, 可以 setTimeout 下再导出。直接导出将会导致画布的内容不稳定出错。 另外注意画布的内容大小,和内存占用。
适配全尺寸公司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 | 不缩放图片,只显示图片的右下边区域 |
原图
scaleToFill
不保持纵横比缩放图片,使图片完全适应
aspectFit
保持纵横比缩放图片,使图片的长边能完全显示出来(图片可完整显示,背景区域有留空)
aspectFill
保持纵横比缩放图片,只保证图片的短边能完全显示出来(图片被剪裁,丢失部分内容)
为什么要仿造一个微信小程序的aspectFitImg算法?
在微信小程序页面开发时,以绘制公司logo为例,
我希望得到的显示效果如下:
(Logo和公司名称在视觉上完美左对齐)
对于公司Logo这样的图案,是必须完整显示并保持比例的,任何对内容的剪裁或比例失调都是无法令人接受的。
为实现这个效果,我们通常的做法是:直接指定图片元素的显示模式为aspectFit模式,然后将公司Logo和公司名称左对齐。
但是这样会产生排版上的瑕疵,例如:
假设图片的缺省占位宽高为:100px * 40px;
但是从网络加载的图片实际只有40px * 40px
那么实际图片的水平中心点将在占位宽度(100px)的水平正中间对齐显示,看起来就好像实际图片左边被留出了30px的宽度,即:(100-40)/2,而这种情况不是我们想要的,因为我们想要的是从视觉上看,图片和底下的元素应该可以左对齐,而不是仅从CSS的视角来看两个元素是左对齐的;
此时,肉眼看见的效果如下:
logo图片占位和公司名称在CSS的层面左对齐,但是从视觉上来看,logo和公司名称并没有左对齐;
在微信小程序中,我解决这个问题的方法是:
(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);
}
}
作者:zhangyin
以上内容来自于:
链接:https://www.jianshu.com/p/a6014e968598/