• 【uniapp 开发】智能温控开关 (环状图)


    • 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,
    				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
    		},
    		{
    			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;
    		 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;
    	 750upx;
    	overflow-x: hidden;
    }
    
    .qiun-padding {
    	padding: 2%;
    	 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 {
    	 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;
    	 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 {
    	 750upx;
    	height: 500upx;
    	background-color: #FFFFFF;
    }
    
    .charts {
    	 750upx;
    	height: 500upx;
    	background-color: #FFFFFF;
    }
    
    /* 横屏样式 */
    .qiun-charts-rotate {
    	 700upx;
    	height: 1100upx;
    	background-color: #FFFFFF;
    	padding: 25upx;
    }
    
    .charts-rotate {
    	 700upx;
    	height: 1100upx;
    	background-color: #FFFFFF;
    }
    
    /* 圆弧进度样式 */
    .qiun-charts3 {
    	 750upx;
    	height: 250upx;
    	background-color: #FFFFFF;
    	position: relative;
    }
    
    .charts3 {
    	position: absolute;
    	 250upx;
    	height: 250upx;
    	background-color: #FFFFFF;
    }
    
    
    
  • 相关阅读:
    java面向接口编程之适配器模式
    java面向接口编程之制定标准和简单工厂模式
    java接口的使用
    java接口(interface)
    java抽象类的体现-模板模式
    java 抽象类
    java final 关键字
    Singleton模式(单例模式) 饿汉式和懒汉式
    java构造方法的私有化
    java代码块
  • 原文地址:https://www.cnblogs.com/neo-java/p/11536062.html
Copyright © 2020-2023  润新知