最近一段时间,公司打算拓展业务,要做智慧厕所项目,涉及到监控大屏、传感器;我这边负责进行大屏绘制、以及数据接收。目前该项目已完成一部分,趁此机会,做一下阶段总结。
本文主要讲解该项目的一些思路以及采用uniapp实现大屏的展示、适配。
采用的工具以及技术
- uniapp + 原生插件开发
- 安卓平板或TV
- AxureRP9
整体架构:
本次开发使用的是uniapp进行的,关于原生插件是对 TCP 服务进行了封装,具体插件开发流程可看 uniapp开发安卓原生插件,不属于本节重点。
1、根据厕所布局图绘制设计稿
用户提供要开发设计的布局图纸,然后通过 AxureRP9,绘制设计稿。
通过设计稿,在后边绘制大屏的时候我们可以准确的知道,每个元素对应的x、y,能帮助我们更快的进行大屏绘制。
例如:图纸
例如:最终效果
2、根据设计稿进行前端布局
2.1 canvas 绘制大屏页面
开发过程中针对中心的厕所布局采用的是canvas 进行绘制,这种都基本不会雷同,因此要定制开发。两边以及头部、顶部这些可以采用普通方式进行绘制,这样写起来也更快一些。
在开发过程中,针对每一个厕所都属于一个独立的页面。为了便于后续的开发,我们将 canvas 部分的逻辑单独提取出来。
主要使用的 canvas
api
// 获取 canvas画布
ctx = uni.createCanvasContext('toilet1Canvas');
/**
* 绘制 可以使用/正在使用图标
*/
async function drawUseIcon() {
let {
path: successImgUrl
} = await getImageInfo(successImg);
let {
path: errorImgUrl
} = await getImageInfo(errorImg);
ctx.drawImage(successImgUrl, 645, 25, 140, 30);
ctx.drawImage(errorImgUrl, 805, 25, 140, 30);
ctx.draw(true);
// 绘制文字
ctx.setFontSize(16);
ctx.setFillStyle('#ffffff');
ctx.fillText('可以使用', 710, 45);
ctx.fillText('正在使用', 870, 45);
ctx.draw(true);
}
// 绘制线条
ctx.beginPath();
ctx.setLineWidth(10);
ctx.strokeStyle = "#1e7bf2";
ctx.moveTo(0, 79);
ctx.lineTo(1035, 79);
ctx.closePath();
ctx.stroke();
2.2 大屏页面进行适配
其实在开发过程中,大屏页面绘制、canvas 画图,并不会造成太大阻碍,网上搜索查找一下 canvas api,根据自己的需求就可以完成绘制。
略微有些繁琐的是针对 开发设计的页面进行适配:
- 最终项目要运用到 安卓 TV 中,具体型号未定
- 当前设计稿的尺寸比例 与 TV 不一定一致
- 在开发的过程中采用的是浏览器、平板进行的测试,怎样让完成适配的页面,无论什么环境设备下都能合理的展示呢
我所经历过与适配相关的也就是 rem、rpx 或者 通过一些三方适配插件进行,但是这些都不适合当下的场景,因为它不仅仅有文字还有 canvas。
最终,我想到了 —— scale
,直接对当前页面W、H 进行缩放不就可以了吗。
针对问题三:如果当前设备的比例与设计稿的比例不一致,那么按设计稿比例进行缩放,根据设备W、H 与 设计稿进行比较,等比占满其中的一项;然后使用一个合适的背景图,那不就满足了嘛!!
备注:
- 在后续的实际开发中,还发现了个问题:我们需要将适配后的页面,居于当前设备屏幕的中心,因此我们还需要设置一下原点
transformOrigin
; - 屏幕的分辨率与尺寸是没关系的,在实际测试中通过
uni.getSystemInfo
获取的windowWidth windowHeight
,在 TV 中并不一定会比你使用的 电脑显示器大。
以下适配方法的代码,大家可以进行参考:
页面的设计稿:1920 * 969;
/**
* 处理当前 页面视图的适配
* 用于适配 不同大小的 TV
*/
function viewAdaptive() {
// 获取当前视图大小
return new Promise((resolve, reject) => {
uni.getSystemInfo({
success: (res) => {
let {
windowWidth,
windowHeight
} = res;
// 设计稿的尺寸
let designWidth = 1920;
let designHeight = 969;
let designScale = designWidth / designHeight; // 约为 1.98
// 计算当前按设计比例 应有的大小
let width = designScale * windowHeight;
let height = windowWidth / designScale;
// 分别存储当前 X Y 的缩放比
let scaleX, scaleY;
let scaleWidth, scaleHeight;
if (!(width > windowWidth)) {
// 以宽度为基准,等比例缩放
scaleWidth = width;
scaleHeight = scaleWidth / designScale;
} else if (!(height > windowHeight)) {
// 以高度为基准等比例缩放
scaleHeight = height;
scaleWidth = scaleHeight * designScale;
}
scaleX = scaleWidth / designWidth;
scaleY = scaleHeight / designHeight;
let originX = 0, originY = 0;
originX = windowWidth - scaleWidth;
originY = windowHeight - scaleHeight;
resolve({
windowWidth,
windowHeight,
scaleX,
scaleY,
originX,
originY,
})
}
})
})
}
在之后的阶段中,可预见的问题有:
- TV 中怎样自启动应用App(因为大部分TV是在安卓做的二次封装,之前采用的自启动插件测试无效,目前暂无思路)
- 通过原生安卓插件启 TCP 服务与 硬件进行通讯(已封装完成,但是测试过程中还是有瑕疵)
- TV 连接wifi 将本地
SQLite
数据库数据上传到云(已测试 获取wifi状态、请求云端数据无误)
好了,到这里关于智慧厕所大屏阶段一的总结就结束了,大家有其他疑问或者更好的方法,可以及时在评论区中剔除;如有大佬针对目前我遇到的问题,有相关经验或者想法也请指导一下小弟。
前端路漫漫,即使环境很动荡,做好自己该做的,多学习,多总结就好,过度焦虑并不会起到任何正面作用!在求知的路上,愿与君共勉!!!