• index.vue
<template>
<view>
<view class="qiun-columns">
<uCharts id="ucharts"
:val="opts.val"
:min="opts.min"
:max="opts.max"
:step="opts.step"
:width="opts.width"
:height="opts.height"
:border="opts.border"
:title="opts.title"
:showUnit="opts.showUnit"
:unit="opts.unit"
:showDecimal="opts.showDecimal"
:colorSatrt="opts.colorSatrt"
:colorEnd="opts.colorEnd"
:colorButton="opts.colorButton"
:pageBg="opts.pageBg"
:circleBg="opts.circleBg"
:pointBg="opts.pointBg"
:setUpUrl="opts.setUpUrl"
@change="change"
ref="ucharts" />
</view>
<button class="qiun-button" @tap="changeData()">更新图表</button>
<!-- 下面是简单调用的例子,除了id和val其他的都可以不给 -->
<view class="qiun-columns">
<uCharts id="ucharts2" :val="simple" title="PM2.5" colorSatrt="#5ACECE" :showUnit="showUnit" colorEnd="#8CCE42"/>
</view>
</view>
</template> <script>
import uCharts from '@/components/u-charts/bar.vue';
var _self; export default {
data() {
return {
simple:18,
showUnit:false,
opts:{
val:15.8,
min:10,
max:40,
step:1,
width:220,
height:220,
border:35,
title:'室内温度',//传null为不显示最上面标题
showUnit:true,//是否显示单位
unit:'℃',
showDecimal:true,//是否小数
colorSatrt:'#FFC2B3',
colorEnd:'#FF3B1D',
colorButton:'#565656',//底部按钮颜色
pageBg:'#F4F5F6',//组件页面背景色,如果父组件像本示例设置了padding,你懂的哈
circleBg:'#FFFFFF',//中间圆心文字块的背景色
pointBg:'#FFFFFF'//控制点背景色
// setUpUrl:'../../page/testurl'//设置那个按钮跳转的地方
}
};
},
components: {
uCharts
},
onLoad() {
_self = this;
this.getServerData();
},
methods: {
change(val){
console.log(val)
},
getServerData() {
},
changeData() {
//作为调用组件内方法的示例,您自由想象发挥哈
this.$refs.ucharts.changeData(28.35);
}
}
};
</script> <style>
.qiun-columns {
display: flex;
flex-direction: column !important;
padding: 40upx;
}
</style>
  • bar.vue

<template>
<view class="progress_box" :style="{'background-color': pageBg}">
<canvas :canvas-id="id" :style="{'width':width+'px','height':height+'px'}" disable-scroll=true @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd"></canvas>
<view class="progress_txt" :style="{'width':centerRadius+'px','height':centerRadius+'px','background-color': circleBg}">
<view class="progress_info_top" v-if="title">{{title}}</view>
<view class="progress_info_center">
<view class="progress_info_center_a">
{{ integer }}
</view>
<view class="progress_info_center_c">
<view class="progress_info_center_c1"><text class="c1_text" v-if="showUnit">{{unit}}</text></view>
<view class="progress_info_center_c2"><text class="c1_text" v-if="showDecimal">.{{ decimal }}</text></view>
</view>
</view>
<view class="progress_info_bottom" @tap="goSetUp">设置</view>
</view>
</view>
</template> <script>
function isInAngleRange(angle, startAngle, endAngle) {
function adjust(angle) {
while (angle < 0) {
angle += 2 * Math.PI;
}
while (angle > 2 * Math.PI) {
angle -= 2 * Math.PI;
}
return angle;
}
angle = adjust(angle);
startAngle = adjust(startAngle);
endAngle = adjust(endAngle);
if (startAngle > endAngle) {
endAngle += 2 * Math.PI;
if (angle < startAngle) {
angle += 2 * Math.PI;
}
}
return angle >= startAngle && angle <= endAngle;
}
function isInArea(e, r) {
return Math.pow(e.x - r.x, 2) + Math.pow(e.y - r.y, 2) <= Math.pow(r.r, 2);
}
function isInUp(e,r) {
if(isInArea(e,r)){
let angle = Math.atan2(r.y - e.y, e.x - r.x);
angle = -angle;
if (isInAngleRange(angle, 0.5*Math.PI, 0.75*Math.PI)) {
return true;
}else{
return false;
}
}else{
return false;
}
}
function isInDown(e,r) {
if(isInArea(e,r)){
let angle = Math.atan2(r.y - e.y, e.x - r.x);
angle = -angle;
if (isInAngleRange(angle, 0.25*Math.PI, 0.5*Math.PI)) {
return true;
}else{
return false;
}
}else{
return false;
}
}
function isInCtrl(e,r) {
if(isInArea(e,r)){
return true;
}else{
return false;
}
}
export default {
props:{
id:{
default:'ucharts'
},
val:{
default:0
},
min:{
default:-10
},
max:{
default:30
},
step:{
default:1
},
width:{
default:220
},
height:{
default:220
},
border:{
default:35
},
title:{
default:null
},
unit:{
default:'℃'
},
showUnit:{
default:'true'
},
showDecimal:{
default:'true'
},
colorSatrt:{
default:'#FFC2B3'
},
colorEnd:{
default:'#FF3B1D'
},
colorButton:{
default:'#565656'
},
pageBg:{
default:'#F4F5F6'
},
circleBg:{
default:'#FFFFFF'
},
pointBg:{
default:'#FFFFFF'
},
setUpUrl:{
default:'../../page/initUrl'
}
},
data() {
return {
valData:0,
valPoint:{},
centerPoint:{},
insideRadius:{},
startPoint:{},
endPoint:{},
isMove:false
}
},
computed: {
integer:function() {
if(this.valData<this.min){ return this.min };
if(this.valData>this.max){ return this.max };
return parseInt(this.valData);
},
decimal:function() {
if(this.valData<this.min){ return 0 };
if(this.valData>this.max){ return 0 };
return Math.abs(parseInt(this.valData*10)-parseInt(this.valData)*10);
},
centerRadius:function() {
return Math.min(this.width/2-this.border,this.height/2-this.border)*2 * 0.9;
}
},
mounted: function() {
this.valData=this.val;
this.drawCircle(this.val,this.min,this.max,this.width,this.height,this.border,this.colorSatrt,this.colorEnd,this.colorButton,this.pointBg);
},
methods: {
drawCircle:function(val,min,max,width,height,border,colorSatrt,colorEnd,colorButton,pointBg) {
let radius=Math.min(width/2-border/2,height/2-border/2);
let centerPoint={
x:width/2,
y:height/2,
r:radius+border/2
};
this.centerPoint=centerPoint;
this.insideRadius={
x:width/2,
y:height/2,
r:radius-border/2
}
let ctx = uni.createCanvasContext(this.id, this);
ctx.setLineWidth(border);
ctx.setStrokeStyle(colorButton);
ctx.setLineCap('butt');
//画按钮背景
ctx.beginPath();
ctx.arc(centerPoint.x, centerPoint.y, radius , 0.25 * Math.PI, 0.75 * Math.PI, false);
ctx.stroke();
//画按钮
ctx.setLineWidth(1);
ctx.setStrokeStyle("#FFFFFF");
ctx.beginPath();
ctx.moveTo(centerPoint.x, height);
ctx.lineTo(centerPoint.x, height-border);
ctx.stroke();
ctx.setLineWidth(3);
ctx.beginPath();
let upPoint={
x:centerPoint.x+(radius)*Math.cos(0.625* Math.PI),
y:centerPoint.x+(radius)*Math.sin(0.625* Math.PI)
};
let downPoint={
x:centerPoint.x+(radius)*Math.cos(0.375* Math.PI),
y:centerPoint.x+(radius)*Math.sin(0.375* Math.PI)
};
let xLength=border*0.6/2;
ctx.moveTo(upPoint.x-xLength, upPoint.y);
ctx.lineTo(upPoint.x+xLength, upPoint.y);
ctx.moveTo(upPoint.x, upPoint.y-xLength);
ctx.lineTo(upPoint.x, upPoint.y+xLength);
ctx.moveTo(downPoint.x-xLength, downPoint.y);
ctx.lineTo(downPoint.x+xLength, downPoint.y);
ctx.stroke();
//变色背景条
ctx.setLineWidth(border);
let gradient = ctx.createLinearGradient(centerPoint.x-radius-border, centerPoint.y, centerPoint.x+radius+border, centerPoint.y);
gradient.addColorStop('0', colorSatrt);
gradient.addColorStop('1.0', colorEnd);
ctx.setStrokeStyle(gradient);
ctx.beginPath();
ctx.arc(centerPoint.x, centerPoint.y, radius , 0.75 * Math.PI, 0.25 * Math.PI, false);
ctx.stroke();
//画控制点
ctx.beginPath();
ctx.setFillStyle(pointBg);
//控制点阴影效果,不需要可以删掉
ctx.setShadow(2, 2, 2, '#888888')
if(val<min) val=min;
if(val>max) val=max;
let progress = (val- min) / (max - min) ;
//控制点半径
let valRadius=border * 0.45;
//控制点弧度
let valRadian= valRadius / (Math.PI * radius);
progress = (1.5-2*valRadian) * progress + 0.75+valRadian;
if (progress >= 2) {
progress = progress % 2;
}
let valPoint={
x:centerPoint.x+(radius)*Math.cos(progress* Math.PI),
y:centerPoint.x+(radius)*Math.sin(progress* Math.PI),
r:valRadius,
v:val,
s:0.75+valRadian,
e:2.25-valRadian,
t:1.5-2*valRadian,
n:progress,
};
this.valPoint=valPoint;
ctx.arc(valPoint.x, valPoint.y, valPoint.r, 0, 2 * Math.PI, false);
ctx.closePath();
ctx.fill();
ctx.draw();
},
touchStart:function(e) {
let touches = e.mp.changedTouches[0] || e.changedTouches[0];
if(isInCtrl(touches,this.valPoint)){
this.isMove=true;
touches.val=this.valPoint;
this.startPoint=touches;
}
},
touchMove:function(e) {
let touches = e.mp.changedTouches[0] || e.changedTouches[0];
if(this.isMove === true){
//这两句是判断是否在进度条内,加上体验不好,你可以试一下&& isInArea(touches,this.insideRadius) === false && isInArea(touches,this.centerPoint) === true
let angle = Math.atan2(this.centerPoint.y - touches.y, touches.x - this.centerPoint.x);
angle = -angle;
let newRadian = angle/Math.PI;
if(newRadian<0){
newRadian = 2 + newRadian;
}
if(newRadian < this.startPoint.val.e - 1.7){
newRadian += 2;
}
let progress = (newRadian - this.startPoint.val.s)/this.startPoint.val.t;
progress = (this.max - this.min)*progress;
let nweVal = this.min + progress;
if(nweVal>this.max) nweVal = this.max;
if(nweVal<this.min) nweVal = this.min;
nweVal=(parseInt(nweVal*10)*0.1).toFixed(1);
this.valData = nweVal;
this.drawCircle(nweVal,this.min,this.max,this.width,this.height,this.border,this.colorSatrt,this.colorEnd,this.colorButton,this.pointBg);
}
},
touchEnd:function(e) {
let touches = e.mp.changedTouches[0] || e.changedTouches[0];
if(isInUp(touches,this.centerPoint) === true && this.isMove === false){
this.valData+=this.step;
if(this.valData>this.max) this.valData = this.max;
this.drawCircle(this.valData,this.min,this.max,this.width,this.height,this.border,this.colorSatrt,this.colorEnd,this.colorButton,this.pointBg);
}
if(isInDown(touches,this.centerPoint) === true && this.isMove === false){
this.valData-=this.step;
if(this.valData<this.min) this.valData = this.min;
this.drawCircle(this.valData,this.min,this.max,this.width,this.height,this.border,this.colorSatrt,this.colorEnd,this.colorButton,this.pointBg);
}
if(this.isMove){
this.$emit('change',this.valData)
// let _this=this;
// uni.request({
// url: 'https://www.ucharts.cn/data.json',
// data:{
// val:this.valData
// },
// success: function(res) {
// console.log("发送新数据["+_this.valData+"]成功!")
// },
// fail: () => {
// _self.tips="网络错误,小程序端请检查合法域名";
// },
// });
// this.isMove = false;
}
},
goSetUp:function() {
console.log(this.setUpUrl);
uni.showToast({
title: '跳转界面',
duration: 2000
});
},
changeData:function(val) {
this.valData=val;
this.drawCircle(val,this.min,this.max,this.width,this.height,this.border,this.colorSatrt,this.colorEnd,this.colorButton,this.pointBg);
},
}
};
</script> <style>
.progress_box {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.progress_txt {
position: absolute;
font-size: 28upx;
border-radius: 50%;
flex-direction: column !important;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
box-shadow:0 0 6upx 4upx #DEDEDE;
}
.progress_info_top {
font-size: 32upx;
letter-spacing: 2upx;
color: #000000;
}
.progress_info_center {
display: flex;
flex-direction: row !important;
color: #000000;
}
.progress_info_center_a {
font-size: 80upx;
height: 100upx;
line-height: 100upx;
font-weight: bold;
letter-spacing: 2upx;
}
.progress_info_center_c {
position: relative;
height: 100upx;
display: flex;
flex-direction: column !important;
align-items: center;
justify-content: center;
}
.progress_info_center_c1 {
display: flex;
height: 50upx;
align-items: center ;
}
.c1_text{
height: 28upx;
font-size: 28upx;
letter-spacing: 2upx;
}
.progress_info_center_c2 {
display: flex;
height: 50upx;
align-items:flex-start;
}
.c2_text{
height: 50upx;
font-size: 28upx;
letter-spacing: 2upx;
}
.progress_info_bottom {
font-size: 32upx;
letter-spacing: 2upx;
color: #666666;
}
</style>
  • qiun.css

page {
background: #F4F5F6;
width: 750upx;
overflow-x: hidden;
} .qiun-padding {
padding: 2%;
width: 96%;
} .qiun-wrap {
display: flex;
flex-wrap: wrap;
} .qiun-rows {
display: flex;
flex-direction: row !important;
} .qiun-columns {
display: flex;
flex-direction: column !important;
} .qiun-common-mt {
margin-top: 10upx;
} .qiun-common-border-bottom {
border-bottom: 1px solid #E9E9E9;
} .qiun-bg-white {
background: #FFFFFF;
} .qiun-title-bar {
width: 96%;
padding: 10upx 2%;
flex-wrap: nowrap;
} .qiun-title-dot-light {
border-left: 10upx solid #0ea391;
padding-left: 10upx;
font-size: 32upx;
color: #000000
} .qiun-textarea {
height: 400upx;
font-size: 34upx;
box-sizing: border-box;
line-height: 50upx;
width: 100%;
background-color: #FFFFFF;
} .qiun-text-tips {
font-size: 28upx;
color: #dc2626;
line-height: 40upx;
padding: 6upx;
} .qiun-button {
background: #2fc25b;
color: #FFFFFF;
margin: 20upx;
} /* 通用样式 */
.qiun-charts {
width: 750upx;
height: 500upx;
background-color: #FFFFFF;
} .charts {
width: 750upx;
height: 500upx;
background-color: #FFFFFF;
} /* 横屏样式 */
.qiun-charts-rotate {
width: 700upx;
height: 1100upx;
background-color: #FFFFFF;
padding: 25upx;
} .charts-rotate {
width: 700upx;
height: 1100upx;
background-color: #FFFFFF;
} /* 圆弧进度样式 */
.qiun-charts3 {
width: 750upx;
height: 250upx;
background-color: #FFFFFF;
position: relative;
} .charts3 {
position: absolute;
width: 250upx;
height: 250upx;
background-color: #FFFFFF;
}

【uniapp 开发】智能温控开关 (环状图)的更多相关文章

  1. Android开发—智能家居系列】(二):用手机对WIFI模块进行配置

    在实际开发中,我开发的这款APP是用来连接温控器,并对温控器进行控制的.有图为证,哈哈. 上一篇文章[Android开发—智能家居系列](一):智能家居原理的文末总结中写到: 手机APP控制智能温控器 ...

  2. 使用uni-app开发微信小程序

    uni-app 开发微信小程序 前言 9月份,开始开发微信小程序,也曾调研过wepy/mpvue,考虑到后期跨端的需求,最终选择使用了uni-app,本文主要介绍如何使用uni-app搭建小程序项目, ...

  3. CozyRSS开发记录1-原型图与Grid

    CozyRSS开发记录1-原型图与Grid 1.使用MockPlus画出最简陋的原型图 这个界面参考了目前我最常使用的RSS阅读-傲游浏览器的内置RSS阅读器.主体框架划分为上.左下.右下三块,分别是 ...

  4. 基于Laravel+Swoole开发智能家居后端

    基于Laravel+Swoole开发智能家居后端 在上一篇<Laravel如何优雅的使用Swoole>中我已经大概谈到了Laravel结合Swoole的用法. 今天,我参与的智能家居项目基 ...

  5. jqPlot图表插件学习之饼状图和环状图

    一.准备工作 官网下载(笔者选择的是jquery.jqplot.1.0.8r1250.zip这个版本) 然后读者需要根据自己的情况新建一个项目并且按照如下的方式加载对应的js和css(因为笔者在VS2 ...

  6. 用C#开发的双色球走势图(二)

    昨晚由于时间的原因只写了一部分内容,今天将这一部分内容补充完毕,多谢各位园友的支持. 这是用C#开发的双色球走势图(一)新的园友可以看昨晚写的内容,以免脱节.首先回复园友的评论,有说好的有说不好的,本 ...

  7. [Aaronyang] 写给自己的WPF4.5 笔记15[AyArc诞生-WPF版本绚丽的环状图,Ay制作,AyWindow强势预览]

    原文:[Aaronyang] 写给自己的WPF4.5 笔记15[AyArc诞生-WPF版本绚丽的环状图,Ay制作,AyWindow强势预览]  我的文章一定要做到对读者负责,否则就是失败的文章  -- ...

  8. SNF快速开发平台WinForm-CS甘特图

    我们在做项目当中会经常用到按时间进度查看任务,其通过条状图来显示项目,进度,和其他时间相关的系统进展的内在关系随着时间进展的情况. 甘特图包含以下三个含义: 1.以图形或表格的形式显示活动: 2.通用 ...

  9. APP开发项目思维导图

    APP开发项目思维导图 下载思维导图:APP开发项目.xmind.zip --------------------------------------- APP开发项目 app项目标记: 未启动 功能 ...

  10. 用C#开发的双色球走势图(原创)值得园友拥有(二)接上一篇

    昨晚由于时间的原因只写了一部分内容,今天将这一部分内容补充完毕,多谢各位园友的支持. 这是用C#开发的双色球走势图(原创)值得园友拥有 新的园友可以看昨晚写的内容,以免脱节.首先回复园友的评论,有说好 ...

随机推荐

  1. JZ-045-扑克牌顺子

    扑克牌顺子 题目描述 LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的 ...

  2. Python 列表的(元素的删除)

    del:根据索引值删除元素 del 可以删除列表中的单个元素,格式为: del listname[index] 其中,listname 表示列表名称,index 表示元素的索引值.del 也可以删除中 ...

  3. 矩池云上安装yolov5并测试教程

    官方仓库:https://github.com/ultralytics/yolov5 官方文档:https://docs.ultralytics.com/quick-start/ 此案例我是租用了k8 ...

  4. python安装各种插件

    http://www.lfd.uci.edu/~gohlke/pythonlibs/#pip 感受:如果编辑pip真的一直出问题,考虑降成32位的进行安装.毕竟合理搭配比木桶突出有用.

  5. RhaPHP 微信公众号管理系统

    框架网址https://www.rhaphp.com/ 开发手册网址:: https://www.kancloud.cn/langleigelang/rhaphp/588488 git 克隆,如果克隆 ...

  6. laravel7 h-ui点改

    html: <td> @if($item->fang_status == 0) <span onclick="changeFangStatus(this,{{$ite ...

  7. CF772D题解

    什么阴间十进制状压 题意:给定 $ n $ 数字,求定义函数 $ G(x) $ 能够表示 满足"十进制按位与为 $ x $"的集合的平方和之和乘上 \(x\),求 \(\bigop ...

  8. web自动化之selenium(六)利用坐标点定位

    这是通过第三发库实现对元素的定位,因为在无法定位元素的时候,只能通过外部来定位,此时就可以使用pyautogui模块,操作鼠标,模拟人进行操作 # 使用注意事项,不要过于的依赖它 1.使用时需要在通过 ...

  9. kafka 第一次小整理(草稿篇)————整理一下自己的认知

    前言 简单整理一些自己使用kafka的一些感受. 正文 一切都要回到真实的世界上, 计算机世界只是真实事件的一个缩影. 计算机世界有一个重要的东西,那就是数据库. 数据库记录着真实世界发生了什么,准确 ...

  10. 5分钟了解Redis的内部实现快速列表(quicklist)

    快速列表简介 在Redis3 .2版本之前,存储列表(list)数据结构使用的是压缩列表(ziplist)和链表(linkedlist),当列表元素个数比较少并且每个元素占用空间比较小的时候,使用压缩 ...