Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
柿饼_PersimmonUI
【PersimmonUI柿饼学习营】基于柿饼UI仪表盘的制作--二牛哥
发布于 2018-09-17 00:03:54 浏览:3906
订阅该版
* 本帖最后由 二牛哥 于 2018-9-17 00:34 编辑 * **基于柿饼UI仪表盘的制作** 前言: 本次的工作将完成两个目标,1 制作仪表盘APP, 2 接续上次帖子的内容将平板电脑UI增加一点新鲜元素,然后将仪表APP“装入”其中。为突出主题本文档分上、下篇分别描述。 **上篇------制作仪表盘APP** **一 目标:**** ** 通过PersimmonUI制作两个仪表盘,本例中可理解为汽车速度计和流量表(或电量表),仪表具有开关背光和指针控制功能。 **二、方法:** 1、 工具 设计好仪表效果图,通过PersimmonUI的画图控件------Canvas作为载体,采用系统API函数分别绘制仪盘盘面、指针、数字、环形渐变圆等元素将效果图中的各部件逐一呈现。 2、 算法 首先确定“盘面”所占弧度数量,然后确定弧度的始、终位置,接着根据刻度数量确定盘面弧度等分切割数量,最后根据三角函数结合笛卡尔直角坐标系可计算出指针的指向。 **三、步骤:****1 建立工程并建立一个页面---page1(分辨率为800x480),分别拖动Canvas、Button控件****到页面按下图方式放置**** **![1.png](/uploads/201809/16/235045xzxj7qf96jvoqyfl.png) 设置Canvas控件属性------背景颜色为白色。分别设置4个按键的bindtap属性为onButtonA/B/C/D,控件字体hz16,文本为“开灯”、“关灯”、“加速”、“减速”。2 根据仪表效果图分别绘制弧段、刻度弧、指针、背光灯、背光弧,如下图所示(具体方法详见程序): ![2.png](/uploads/201809/16/235142ceux67qfvn58588x.png) 3 如法炮制,再绘制一个小仪表,如下图所示: ![3.png](/uploads/201809/16/235317xps78zp7bp8z8juu.png) 4 将大小仪表进行组合,如下图所示:![4.png](/uploads/201809/16/235349nx2zkrxa9lm9lxv9.png) 6 编写按键功能函数,分别完成开灯、关灯、加速、减速功能,然后再将各种的功能函数与绘图代码填入各自的事件驱动函数中。 7 运行程序,验证功能 (1) 开关灯动画效果图 ![swLight.gif](/uploads/201809/16/235517tnsdxs54g948pszs.gif) (2) 加、减速效果图:GIF动画2(我制作动画的过程中出现了异常,未制作成功,稍后再贴) 8 关键代码:```var value1 = 0; var value2 = 0; var lightFlag = 0; function OpenLight() { lightFlag = 1; }; function CloseLight(){ lightFlag = 0; }; function IncMeter1(){ if(value1<=178) value1+=2; }; function DecMeter1(){ if(value1>= 2) value1-=2; }; function IncMeter2(){ if(value2<=97.5) value2+=2.5; }; function DecMeter2(){ if(value2>= 2.5) value2-=2.5; }; function ResetValue(){ value1 = 0; value2 = 0; }; function SetValue2() { value2 = 100; }; var page = { onLoad : function(e) { //==========================================big meter============================================= DecMeter1(); // CloseLight(); var context = pm.createCanvasContext('Canvas1', this) //获取画布对象 if (context) { var point = { x: 200, y: 200 }; //圆心坐标,相对于画布 var radius = 130; //半径 var start = -1.5 * Math.PI; //起始弧度 context.setLineWidth(30) context.setStrokeStyle('#91C7AE') context.setFillStyle('#91C7AE'); for( var i = 0; i <=9; i++ ) { var stop = start + 0.15 * Math.PI ; //结束弧度 var x = Math.floor(110 * Math.cos(start)) + 200; var y = Math.floor(110 * Math.sin(start)) + 200; var v = 20 * i; if (i >= 7) context.fillText(v.toString(), x - 10, y); else context.fillText(v.toString(), x, y-3); if (i == 9) break; context.beginPath(); //开始新的路径 context.arc( point.x, point.y, radius, start, stop - 0.003 * Math.PI, false); //画一段圆弧 context.stroke(); //填充路径 context.closePath(); //关闭路径 start = stop; if (i == 2) { context.setStrokeStyle('rgba(255, 128, 0, 1)')//('#63869E') context.setFillStyle('#63869E'); } else if (i == 6) { context.setStrokeStyle('#C23531') context.setFillStyle('#C23531'); } } //----------------------------------------------------// //画背光弧 context.beginPath() //开始路径 context.setLineWidth(10) if( lightFlag>0 ) context.setStrokeStyle( 'rgba(255, 0, 0, 1)'); else context.setStrokeStyle( 'rgba(0, 0, 0, 1)'); context.arc( point.x, point.y, 175, -1.5 * Math.PI, -0.15 * Math.PI, false); context.stroke() context.closePath(); //---------------------------------------------------- //画背光灯 // Create circular gradient var grd = context.createCircularGradient(200, 200, 70) if( lightFlag>0 ) grd.addColorStop(0, 'blue') else grd.addColorStop(0, 'black') grd.addColorStop(1, 'white') context.beginPath() // Fill with gradient context.setFillStyle(grd) context.fillRect(120,130, 150,150) context.closePath(); //----------------------------------------------------\\ radius = 150; start = -1.5 * Math.PI; context.setLineWidth(22) context.setStrokeStyle('#91C7AE') for( var i = 0; i < 90; i++ ) // 画50个刻度,即共10个大格,每个小格中画5个刻度 { var stop = start + 0.015 * Math.PI ; context.beginPath(); context.arc( point.x, point.y, radius, start, stop - 0.003 * Math.PI, false); context.stroke(); context.closePath(); start = stop; if (i == 29) { context.setStrokeStyle('rgba(255, 128, 0, 1)') } else if (i == 69) { context.setStrokeStyle('#C23531') } } { //画指针 //var value1 = 77; //表盘当前值 var radius = 115; var x = Math.floor(radius * Math.cos((-1.5 * Math.PI + value1/2 * 1.5 * Math.PI / 100))) + point.x; var y = Math.floor(radius * Math.sin((-1.5 * Math.PI + value1/2 * 1.5 * Math.PI / 100))) + point.y; context.beginPath(); //context.setFillStyle('rgba(255, 0, 123, 0.3)'); context.setFillStyle('rgba(20, 50, 120, 1)'); context.moveTo(x, y) radius = 15; x = Math.floor(radius * Math.cos((-1 * Math.PI + value1/2 * 1.5 * Math.PI / 100))) + point.x; y = Math.floor(radius * Math.sin((-1 * Math.PI + value1/2 * 1.5 * Math.PI / 100))) + point.y; context.lineTo(x, y); radius = 20; x = Math.floor(radius * Math.cos((-0.5 * Math.PI + value1/2 * 1.5 * Math.PI / 100))) + point.x; y = Math.floor(radius * Math.sin((-0.5 * Math.PI + value1/2 * 1.5 * Math.PI / 100))) + point.y; context.lineTo(x, y); radius = 15; x = Math.floor(radius * Math.cos((0 * Math.PI + value1/2 * 1.5 * Math.PI / 100))) + point.x; y = Math.floor(radius * Math.sin((0 * Math.PI + value1/2 * 1.5 * Math.PI / 100))) + point.y; context.lineTo(x, y); context.fill(); context.setTextAlign('center') context.fillText(value1.toString(), 200, 250) context.closePath(); } //context.draw(); } //========================================= small meter ===================================================== IncMeter2(); //var context = pm.createCanvasContext('Canvas1', this) //获取画布对象 if (context) { var point = { x: 350, y: 330 }; //圆心坐标,相对于画布 var radius = 75; //半径 var start = -0.8 * Math.PI; //起始弧度 context.setLineWidth(30) context.setStrokeStyle('#91C7AE') context.setFillStyle('#91C7AE'); for( var i = 0; i <= 4; i++ ) { var stop = start + 0.15 * Math.PI ; //结束弧度 var x = Math.floor(108 * Math.cos(start)) + point.x; var y = Math.floor(108 * Math.sin(start)) + point.y; var v = 25 * i; if (i >= 2) context.fillText(v.toString(), x-10 , y); else context.fillText(v.toString(), x, y); if (i == 4) break; switch(i){ case 0: context.setStrokeStyle('#ff0000'); break; case 1: context.setStrokeStyle('#ff7f00'); break; case 2: context.setStrokeStyle('#91C7AE'); break; case 3: context.setStrokeStyle('#00ff00'); break; default: break; } context.beginPath(); //开始新的路径 context.arc( point.x, point.y, radius, start, stop - 0.006 * Math.PI, false); //画一段圆弧 context.stroke(); //填充路径 context.closePath(); //关闭路径 start = stop; if (i == 1) { context.setStrokeStyle('#63869E') context.setFillStyle('#63869E'); } else if (i == 7) { context.setStrokeStyle('#C23531') context.setFillStyle('#C23531'); } } //----------------------------------------------------// //画背光弧 context.beginPath() //开始路径 context.setLineWidth(10) if( lightFlag>0 ) context.setStrokeStyle( 'rgba(255, 0, 0, 1)'); else context.setStrokeStyle( 'rgba(0, 0, 0, 1)'); context.arc( point.x, point.y, 120, -0.8 * Math.PI, -0.2 * Math.PI, false); context.stroke() context.closePath(); //---------------------------------------------------- { //画指针 //var value = value2; //表盘当前值 var radius = 65; var x = Math.floor(radius * Math.cos((-0.8 * Math.PI + value2/2.5 * 1.5 * Math.PI / 100))) + point.x; var y = Math.floor(radius * Math.sin((-0.8 * Math.PI + value2/2.5 * 1.5 * Math.PI / 100))) + point.y; context.beginPath(); //context.setFillStyle('rgba(0, 0, 255, 0.7)'); context.setFillStyle('rgba(20, 50, 120, 1)'); context.moveTo(x, y) radius = 8; x = Math.floor(radius * Math.cos((-0.3 * Math.PI + value2/2.5 * 1.5 * Math.PI / 100))) + point.x; y = Math.floor(radius * Math.sin((-0.3 * Math.PI + value2/2.5 * 1.5 * Math.PI / 100))) + point.y; context.lineTo(x, y); radius = 10; x = Math.floor(radius * Math.cos((0.20 * Math.PI + value2/2.5 * 1.5 * Math.PI / 100))) + point.x; y = Math.floor(radius * Math.sin((0.20 * Math.PI + value2/2.5 * 1.5 * Math.PI / 100))) + point.y; context.lineTo(x, y); radius = 8; x = Math.floor(radius * Math.cos((0.65 * Math.PI + value2/2.5 * 1.5 * Math.PI / 100))) + point.x; y = Math.floor(radius * Math.sin((0.65 * Math.PI + value2/2.5 * 1.5 * Math.PI / 100))) + point.y; context.lineTo(x, y); context.fill(); context.setTextAlign('center') //context.fillText(value.toString(), 200, 250) context.fillText(value2.toString(), point.x, 345) context.closePath(); } //context.draw(); } context.draw(); //=================================================== end ========================================================// },``` 经验证,功能正常,至此,目标达成。 ** 下篇------完善平板电脑UI系统功能**** **** **一 目标: 1 将仪表APP加入系统中,面板切换时具有“滑入”效果; 2 加入滑动解锁功能; 二、方法: 1 滑动解锁,通过判断Slider控件的值判断滑动的位置,当满足预定要求时触发跳转函数实现解锁; 2 本次采用新建页面,设置页面“移动”属性,照搬代码的方式实现APP移植。 三、步骤: 1 打开“PhotoBrowser”工程,新建页面------page3,按照“上篇------制作仪表盘APP”的方法添加空间并设置对应属性(注意,先前为横屏,现在改为竖屏),如下图所示(特别注意:页面属性的设置中添加了“移动”选择): ![11.png](/uploads/201809/16/235803bgytoygh0pothzqh.png) 2 将上篇已经编辑好的代码复制到page3.js中 3 在page1中添加一个按钮控件---仪表盘,设置其属性并将事件驱动方法编写如下: onButton2 : function(e) { console.dir(e); pm.navigateTo({url:"page3/page3"}); }, 4 运行程序,触摸“仪表盘”按钮即可跳转到“仪表盘”页面,如下图所示: ![14.png](/uploads/201809/17/003352qo15d338t11ol1p8.png) ![12.png](/uploads/201809/16/235852jsarasrqo2q7aorp.png) 5 调整仪表的坐标,使其适配页面。 6 并编写“返回”按键的驱动方法,代码如下: onButtonE : function(e) { console.dir(e); pm.navigateBack(); }, 7 运行程序效果如下 此为静态图,稍后再贴GIF动图 ![13.png](/uploads/201809/17/000040rqwhf27xqivqlxxf.png) 至此,仪表APP加入成功,并成功实现了“滑动”“登台”的表演。下面将为滑动解锁内容。 PS: 突然发现如果要增加滑动解锁功能需要增加一个页面,且页面的顺序要做“大规模调整”,有没有简便快捷的方法,我目前还未想好,也就暂且打住,留在下次发帖时再作补充吧。 下载附件 [Photo_Meter.rar](https://oss-club.rt-thread.org/uploads/201809/17/002646zfpy0kezsa3fk30a.rar)
查看更多
1
个回答
默认排序
按发布时间排序
bernard
2018-09-18
这家伙很懒,什么也没写!
中间的渐变圆是点睛之笔啊
撰写答案
登录
注册新账号
关注者
0
被浏览
3.9k
关于作者
二牛哥
这家伙很懒,什么也没写!
提问
10
回答
4
被采纳
0
关注TA
发私信
相关问题
1
【PersimmonUI柿饼学习营】+ A Byte of China + 环境搭建&20W年薪广告
2
【柿饼学习营】+werrysuzhen+20W年薪作业
3
【PersimmonUI柿饼学习营】+ meetwit + 20W年薪广告&lesson01
4
【PersimmonUI柿饼学习营】+ DaZhou + 20W年薪作业+视频有彩蛋
5
【PersimmonUI柿饼学习营】+ DMY+ lesson01 20W年薪广告
6
【PersimmonUI柿饼学习营】+ Bigmagic+20W年薪广告&day01
7
【PersimmonUI柿饼学习营】+ chowguohua+年薪广告
8
【柿饼学习营】+werrysuzhen+脚本及事件学习
9
【PersimmonUI柿饼学习营】+ DaZhou+ 手把手教你做计算器
10
【PersimmonUI柿饼学习营】+ A Byte of China + 2048游戏
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
在用clangd开发RTT吗,快来试试如何简单获得清晰干净的工作区
2
GD32F450 片内 flash驱动适配
3
STM32H7R7运行CherryUSB
4
RT-Smart首次线下培训,锁定2024 RT-Thread开发者大会!
5
使用RC522软件包驱动FM1722
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
6
次点赞
YZRD
2
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部