| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 | <template>	<view		class="u-circle-progress"		:style="{			width: widthPx + 'px',			height: widthPx + 'px',			backgroundColor: bgColor		}"	>				<canvas			class="u-canvas-bg"			:canvas-id="elBgId"			:id="elBgId"			:style="{				width: widthPx + 'px',				height: widthPx + 'px'			}"		></canvas>		<canvas			class="u-canvas"			:canvas-id="elId"			:id="elId"			:style="{				width: widthPx + 'px',				height: widthPx + 'px'			}"		></canvas>		<slot></slot>	</view></template><script>export default {	name: 'u-circle-progress',	props: {				percent: {			type: Number,			default: 0,						validator: val => {				return val >= 0 && val <= 100;			}		},				inactiveColor: {			type: String,			default: '#ececec'		},				activeColor: {			type: String,			default: '#19be6b'		},				borderWidth: {			type: [Number, String],			default: 14		},				width: {			type: [Number, String],			default: 200		},				duration: {			type: [Number, String],			default: 1500		},				type: {			type: String,			default: ''		},				bgColor: {			type: String,			default: '#ffffff'		}	},	data() {		return {						elBgId: 'uCircleProgressBgId', 			elId: 'uCircleProgressElId',									elBgId: this.$u.guid(), 			elId: this.$u.guid(),						widthPx: uni.upx2px(this.width), 			borderWidthPx: uni.upx2px(this.borderWidth), 			startAngle: -Math.PI / 2, 			progressContext: null, 			newPercent: 0, 			oldPercent: 0 		};	},	watch: {		percent(nVal, oVal = 0) {			if (nVal > 100) nVal = 100;			if (nVal < 0) oVal = 0;						this.newPercent = nVal;			this.oldPercent = oVal;			setTimeout(() => {												this.drawCircleByProgress(oVal);			}, 50);		}	},	created() {				this.newPercent = this.percent;		this.oldPercent = 0;	},	computed: {				circleColor() {			if (['success', 'error', 'info', 'primary', 'warning'].indexOf(this.type) >= 0) return this.$u.color[this.type];			else return this.activeColor;		}	},	mounted() {				setTimeout(() => {			this.drawProgressBg();			this.drawCircleByProgress(this.oldPercent);		}, 50);	},	methods: {		drawProgressBg() {			let ctx = uni.createCanvasContext(this.elBgId, this);			ctx.setLineWidth(this.borderWidthPx); 			ctx.setStrokeStyle(this.inactiveColor); 			ctx.beginPath(); 						let radius = this.widthPx / 2;			ctx.arc(radius, radius, radius - this.borderWidthPx, 0, 2 * Math.PI, false);			ctx.stroke(); 			ctx.draw();		},		drawCircleByProgress(progress) {						let ctx = this.progressContext;			if (!ctx) {				ctx = uni.createCanvasContext(this.elId, this);				this.progressContext = ctx;			}						ctx.setLineCap('round');						ctx.setLineWidth(this.borderWidthPx);			ctx.setStrokeStyle(this.circleColor);						let time = Math.floor(this.duration / 100);									let endAngle = ((2 * Math.PI) / 100) * progress + this.startAngle;			ctx.beginPath();						let radius = this.widthPx / 2;			ctx.arc(radius, radius, radius - this.borderWidthPx, this.startAngle, endAngle, false);			ctx.stroke();			ctx.draw();						if (this.newPercent > this.oldPercent) {								progress++;								if (progress > this.newPercent) return;			} else {								progress--;				if (progress < this.newPercent) return;			}			setTimeout(() => {								this.drawCircleByProgress(progress);			}, time);		}	}};</script><style lang="scss" scoped>@import "../../libs/css/style.components.scss";.u-circle-progress {	position: relative;		display: inline-flex;				align-items: center;	justify-content: center;}.u-canvas-bg {	position: absolute;}.u-canvas {	position: absolute;}</style>
 |