(转载请注明出处,本文章内容仅用于学习)
这几天开发小程序有个新需求,需要在聊天群中实现发送图片。
之前做聊天时已经把框架搭好,心想应该只需要后端增加上传图片的一系操作。
当然最后做出来是没问题,但是不论用哪个小程序的图片自动缩放/截取,显示效果都差强人意,最后综合考虑(百度了一大圈都没有🙃),只能手写图片自适应算法
最终想要实现的效果
目前这种聊天群的图片显示,用户最习惯的还是微信跟QQ的显示模式,参考微信的图片最终样式大体上划分为缩放与截取。
一种是不管图片原来有多大,发送后都会缩放到正常比例显示给用户,另一种通常是图片的宽高比例相差极大,如果缩放到用户的能一眼看完的程度,通常很不美观,所以一般会截取多余长/宽的那一部分,只显示一部分,用户如果想看完整图片需点击查看。
最后要能对图片的样式进行控制跟原来的一样。
解决方案
简略:使用js获取图片宽高并使用算法得出合理的显示宽高,最后将宽高动态赋值给wxml的图片,截取则利用图片定义的视窗区域。
一张图片在聊天室发出后,怎么知道这张图片要不要缩放/裁剪?这里做法是相对于屏幕,定义一块图片最大能显示多少的视窗区域,如果图片宽高任意一边超出这个视窗区,就要进行缩放操作,至于怎么缩放以及缩放多少合适请看代码。
考虑使用场景在数据量很多的消息列表中,最终选择将整体代码样式封装进组件中使用,实测使用组件加载图片跟不使用加载基本无差别。
组件代码
这里是针对聊天场景调试优化的版本,下面有通用版,不会创建组件的搜别人贴子,这里不做演示直接贴代码
JS
Component({
lifetimes:{
detached: function() {
//console.log("组件实例被从页面节点树移除");
},
attached: function(){
//console.log("组件实例进入页面节点树");
var that = this;
wx.getImageInfo({
src: that.properties.imgUrl,
success: function (res) {
var imgWidth=res.width;
var imgHeight=res.height;
var maxPictureViewWidth = 280;//图片视窗最大宽度
var maxPictureViewHeight = 220;//图片视窗最大高度
var ratio = imgWidth/imgHeight;
if(ratio<0.25 || ratio>2.2){
//图片宽高比相差过大,可能需要截取
//判断图片是过高还是过宽
if(imgWidth>imgHeight){
//图片过宽
if(imgHeight>maxPictureViewHeight){
//同时判断图片高度有没有大于视窗最大高度
//图片过宽且图片高度大于视窗最大高度,依据高度缩减图片比例到视窗可见范围,宽度不管直接靠视窗截取多的部分不显示
var product = maxPictureViewHeight/imgHeight;
imgHeight=imgHeight*product
imgWidth=imgWidth*product
that.setData({
viewHeight:maxPictureViewHeight<imgHeight/2?maxPictureViewHeight:imgHeight/2,
viewWidth:maxPictureViewWidth<imgWidth/2?maxPictureViewWidth:imgWidth/2,
imgHeight:imgHeight/2,
imgWidth:imgWidth/2
})
}else{
//图片高度小于视窗最大高度
that.setData({
viewHeight:imgHeight/2,
viewWidth:maxPictureViewWidth,
imgHeight:imgHeight/2,
imgWidth:imgWidth/2
})
}
}else{
//图片过高
if(imgWidth>maxPictureViewWidth){
//图片过高且图片宽度大于视窗最大宽度,按照宽度缩减图片比例到视窗可见范围,高度不管直接靠视窗截取不显示
var product = maxPictureViewWidth/imgWidth;
imgHeight=imgHeight*product
imgWidth=imgWidth*product
that.setData({
viewHeight:maxPictureViewHeight,
viewWidth:maxPictureViewWidth,
imgHeight:imgHeight,
imgWidth:imgWidth
})
}else{
//图片宽度小于视窗最大宽度
that.setData({
viewHeight:maxPictureViewHeight,
viewWidth:imgWidth/2,
imgHeight:imgHeight/2,
imgWidth:imgWidth/2
})
}
}
}else{
//图片宽高比相差不大,