写本文的目的是为了记录笔者在小程序开发学习过程中发现的问题并尝试解决问题的方法和所做的尝试,方便在之后的学习中更加熟悉代码逻辑与原理算法等等。
具体问题描述
笔者在学习Canvas控件时,想到:
如何让Canvas组件中绘制的图片最大化填充与其父级元素View之中
首先我的文件代码如下:
(注: 笔者在写本文时,使用的微信开发者工具是v1.02.18.10250版本,并且模拟器机型是水果6)
/*wxss文件代码*/
.page{
border: solid 1px brown;
width:320px;
height:540px;
}
.borderCss{
text-decoration: none;
}
/*.js文件代码*/
/*创建 一个canvas 组件的绘图上下文 CanvasContext 对象*/
const canvasContextEntity = wx.createCanvasContext("testCanvas");
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
//按钮绑定的点击事件
openFunc: function (e) {
wx.chooseImage({//选择一张图片
sizeType: ['original', 'compressed'],//设置选中图片的尺寸
success: function (res) {//函数执行成功后执行回调函数
//将回调函数返回值中图片的临时路径作为canvas组件绘制图片的路径
canvasContextEntity.drawImage(res.tempFilePaths[0], 0, 0);
//在canvas组件上画出选中的图片
canvasContextEntity.draw();
},
});
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
/*wxml文件代码*/
<view class="page">
<button bindtap="openFunc" type="primary" size="mini">打 开</button>
<canvas class="borderCss" canvas-id="testCanvas" disable-scroll="true"/>
</view>
运行在模拟器中显示Canvas控件的 width 与 height 是 300px × 150px
注: 截止笔者写本文的时间,小程序官方文档还是没有将文档内容更正,文档内容如下:
(可能尚未更新)
回归正题,已知Canvas组件的默认样式是 300px×150px ,那么要将Canvas组件中绘制的图片最大化填充于父元素view中(即样式类为"page"的view之中),就是要将canvas组件的width与height最大化。
如何解决?
傻瓜式 的做法就很简单了,直接在Canvas的组件的样式类"borderCss"中添加样式
width:320px;//参照上方代码样式类为"page"的view组件的width为"320px",height为"540px"
height:500px;//设置为500px是减去button组件的宽度和组件间默认的外间距,这里减去40
运行于模拟器,预览效果:
预览效果达到需求。
但是问题也来了
canvas 组件的样式属性 width 与 height 的值是直接 ctrl+c 和 ctrl+v 过去的,参数写死的话,当样式类为" page "的样式一改,canvas 组件的样式类也要跟着改,当这种情况同时出现多次的话,改样式也是一项烦人的工作,因此参数写死是一个优雅的程序员必须杜绝的不良习惯,同时这种行为也会增加代码维护人员的工作量 。
既然参数写死的 “傻瓜式” 方法是不能做的,那么只有用数据绑定来动态的加载数据才是最好的方法。
较为好的方法:
也就是说,若要实现最大化填充,就是要获取样式类为 “page” 的 view 组件样式属性中的 width 和 height 的值,然后将属性动态加载至canvas组件的样式之中。
那么首先我们就需要获取样式类为 " page "的view的事件源对象。
在.js文件中添加以下代码:
/*定义全局变量*/
var canvasStyleStr="";
/*在Page的data中定义一个样式数据*/
data{
canvasLineStyle:"",
}
/*在Page函数的onload函数中添加以下代码*/
/*调用createSelectorQuery函数,将返回的SelectorQuery对象复制给queryEntity*/
var queryEntity = wx.createSelectorQuery();
/*在当前页面选择类选择器".page"的节点,并分析该函数返回的NodesRef对象实例,
将该实例中的width与height拼接成一个字符串*/
queryEntity.select(".page").boundingClientRect(function (rect) {
console.log("Total rect: ",rect);//调试打印rect
//height减去36px是除去按钮所占的宽度大小
canvasStyleStr+="width:"+rect.width+"px;height:"+(rect.height-36)+"px;";
console.log("After style: ",canvasStyleStr);//调试打印输出拼接后的样式字符串
}).exec();
在 wxml 文件中为canvas组件增加 style 属性并将值设为 "{{canvasLineStyle}}"
运行效果:
未设置style样式时
设置行内样式后:
注: (已知其父级元素view的width为:320px; height为:540px;)
506+36>540
也就是当我们改变canvas的行内属性style后,canvas最大化的填充至其父元素的view之中,并且减少的36px的height值也可以通过执行wx.createSelectorQuery()函数返回的SelectorQuery实例来获取button控件的宽度,实现不写死参数来改变canvas画布的width与height值。
另一种方法:
但是:这里获取样式类为page的view实例对象的width和height依旧是写死的参数,那么改变这一窘状的方式就是动态改变canvas父级view的样式。
这里笔者决定通过模拟器可用的最大的width与height作为样式类为page的view的style属性的值。
/*js文件添加以下代码,以下代码写在Page函数外*/
var screenWidth=0;
var screenHeight=0;
//获取系统信息
wx.getSystemInfo({
success: function(res) {
screenWidth=res.windowWidth;//可用最大长度
screenHeight=res.windowHeight;//可用最大宽度
},
});
/*Page的data中添加以下代码*/
Page{
data{
pageViewLineStyle:"",//行内样式字符串初始化
}
}
/*接着在页面生命周期函数中改变canvas画布的父级元素view的样式*/
onLoad: function (options) {
/*注意若联合上一案例,
则必须将改变view样式的setData函数在调用wx.createSelectorQuery函数之前执行该setData函数,
否则canvas画布获取不到样式类为page的view更改后的width与height值*/
this.setData({
pageViewLineStyle: "width:" + screenWidth + "px;height:" + screenHeight + "px;",
});
}
在wxml文件中添加以下代码:
已知可用的最大width与height是:
运行效果:
同样,我们在水果5和水果6+的模拟器上运行下最终效果。
水果5:
水果6+:
注: 实际上样式类为 “page” 的view的长宽应为可用最大长宽*该view组件预计所占的区域比例,例如:view的长宽为 = 可用最大长宽 × 50% 。
并且,以上通过获取屏幕可用最大长宽来作为view的样式,也可用 CSS3 引入的 “vw” 与 “vh” 来决定view的长宽(vw: view width,vh: view height)也就是按照屏幕的大小来决定view视图站屏幕可用区域的比例。
综上,笔者在学习过程中遇到的这一问题,并且尝试去解决这些问题,若本文中出现错误或者误导欢迎评论区指出该错误,亦或你对于本文有何建议也可于下方评论区评论或站内私信于我。
本文参考的文档和博客如下:
注: 顺序排名随机。
1. W3School 中关于 style 的说明:
2. 站内博主kerryqpw 的 微信小程序如何获取屏幕宽度 一文。(对于 vw,vh和小程序获取屏幕可用区域大小的说明)
3. 小程序官方API文档 对于 wx.createSelectorQuery 函数和 wx.getSystemInfo 函数的详细说明
https://developers.weixin.qq.com/miniprogram/dev/api/system/system-info/wx.getSystemInfo.html
https://developers.weixin.qq.com/miniprogram/dev/api/wxml/SelectorQuery.html
4. 其他参考的文档或者博客若笔者遗漏,笔者将在后续补充说明。