<template>
	<view class="tui-circular-container" :style="{ width: diam + 'px', height: (height || diam) + 'px' }">
		<canvas
			:start="percent"
			:change:start="parse.initDraw"
			:data-width="diam"
			:data-height="height"
			:data-lineWidth="lineWidth"
			:data-lineCap="lineCap"
			:data-fontSize="fontSize"
			:data-fontColor="fontColor"
			:data-fontShow="fontShow"
			:data-percentText="percentText"
			:data-defaultShow="defaultShow"
			:data-defaultColor="defaultColor"
			:data-progressColor="progressColor"
			:data-gradualColor="gradualColor"
			:data-sAngle="sAngle"
			:data-counterclockwise="counterclockwise"
			:data-multiple="multiple"
			:data-speed="speed"
			:data-activeMode="activeMode"
			:data-cid="progressCanvasId"
			:canvas-id="progressCanvasId"
			:class="[progressCanvasId]"
			:style="{ width: diam + 'px', height: (height || diam) + 'px' }"
		></canvas>
		<slot></slot>
	</view>
</template>
<script module="parse" lang="renderjs">
 export default {
	methods:{
		format(str){
			if(!str) return str;
			return str.replace(/\"/g, "");
		},
		bool(str){
			return str==='true' || str==true ? true:false
		},
		//初始化绘制
		  initDraw(percentage, oldPercentage, owner, ins) {
			 let state=ins.getState();
			 let res=ins.getDataset();
			 const activeMode=this.format(res.activemode);
			 let start = activeMode === 'backwards' ? 0 : (state.startPercentage || 0);
			 if(!state.progressContext || !state.canvas){
				const width = res.width;
				const height = res.height==0?res.width:res.height;
				let ele=`.${res.cid}>canvas`
				const canvas = document.querySelectorAll(this.format(ele))[0];
				const ctx = canvas.getContext('2d');
				// const dpr =uni.getSystemInfoSync().pixelRatio;
				// canvas.style.width=width+'px';
				// canvas.style.height=height+'px';
				// canvas.width = width * dpr;
				// canvas.height = height * dpr;
				// ctx.scale(dpr, dpr);
				state.progressContext=ctx;
				state.canvas=canvas;
				this.drawProgressCircular(start, ctx, canvas,percentage,res,state,owner);
			 }else{
		         this.drawProgressCircular(start, state.progressContext, state.canvas,percentage,res,state,owner);
			 }
		  },
		  //默认(背景)圆环
		  drawDefaultCircular(ctx, canvas,res) {
		    //终止弧度
			let sangle=Number(res.sangle) * Math.PI
		    let eAngle = Math.PI * (res.height!=0 ? 1 : 2) + sangle;
		    this.drawArc(ctx, eAngle,this.format(res.defaultcolor),res);
		  },
		  drawPercentage(ctx, percentage,res) {
		    ctx.save(); //save和restore可以保证样式属性只运用于该段canvas元素
		    ctx.beginPath();
		    ctx.fillStyle = this.format(res.fontcolor);
		    ctx.font = res.fontsize + "px Arial"; //设置字体大小和字体
		    ctx.textAlign = "center";
		    ctx.textBaseline = "middle";
		    let radius = res.width / 2;
			let percenttext=this.format(res.percenttext)
		    if (!percenttext) {
			  let multiple=Number(res.multiple)
		      percentage = this.bool(res.counterclockwise) ? 100 - percentage * multiple : percentage * multiple;
		      percentage = percentage.toFixed(0) + "%"
		    } else {
		      percentage = percenttext
		    }
		    ctx.fillText(percentage, radius, radius);
		    ctx.stroke();
		    ctx.restore();
		  },
		  //进度圆环
		  drawProgressCircular(startPercentage, ctx, canvas,percentage,res,state,owner) {
		    if (!ctx || !canvas) return;
			let that=this
		    let gradient = ctx.createLinearGradient(0, 0, Number(res.width), 0);
		    gradient.addColorStop(0, this.format(res.progresscolor));
			let gradualColor=this.format(res.gradualcolor)
		    if (gradualColor) {
		      gradient.addColorStop('1', gradualColor);
		    }
		    let requestId = null
		    let renderLoop = () => {
		      drawFrame((res) => {
		        if (res) {
		          requestId = requestAnimationFrame(renderLoop)
		        } else {
		          cancelAnimationFrame(requestId)
		          requestId = null;
		          renderLoop = null;
		        }
		      })
		    }
		    requestId = requestAnimationFrame(renderLoop)

		    function drawFrame(callback) {
		      ctx.clearRect(0, 0, canvas.width, canvas.height);
		      if (that.bool(res.defaultshow)) {
		        that.drawDefaultCircular(ctx, canvas,res)
		      }
		      if (that.bool(res.fontshow)) {
		        that.drawPercentage(ctx, startPercentage,res);
		      }
		      if (percentage === 0 || (that.bool(res.counterclockwise) && startPercentage === 100)) return;
		      let sangle=Number(res.sangle) * Math.PI
			  let eAngle = ((2 * Math.PI) / 100) * startPercentage + sangle;
			 that.drawArc(ctx, eAngle, gradient,res);
			  owner.callMethod('change', {
				percentage:startPercentage
			 })
		      if (startPercentage >= percentage) {
				state.startPercentage=startPercentage;
				owner.callMethod('end', {
					canvasId: that.format(res.canvasid)
				})
		        cancelAnimationFrame(requestId)
		        callback && callback(false)
		        return;
		      }
		      let num = startPercentage + Number(res.speed)
		      startPercentage = num > percentage ? percentage : num;
		      callback && callback(true)
		    }

		  },
		  //创建弧线
		  drawArc(ctx, eAngle, strokeStyle,res) {
		    ctx.save();
		    ctx.beginPath();
		    ctx.lineCap = this.format(res.linecap);
		    ctx.lineWidth =Number(res.linewidth);
		    ctx.strokeStyle = strokeStyle;
		    let radius = res.width / 2; //x=y
			let sangle=Number(res.sangle) * Math.PI
		    ctx.arc(radius, radius, radius - res.linewidth, sangle, eAngle,this.bool(res.counterclockwise));
		    ctx.stroke();
		    ctx.closePath();
		    ctx.restore();
		  }
	}
}
</script>
<script>
export default {
	name: 'tuiRoundProgress',
	props: {
		/*
		  传值需使用rpx进行转换保证各终端兼容
		  px = rpx / 750 * wx.getSystemInfoSync().windowWidth
		  圆形进度条(画布)宽度，直径 [px]
		*/
		diam: {
			type: Number,
			default: 60
		},
		//圆形进度条(画布)高度，默认取diam值[当画半弧时传值，height有值时则取height]
		height: {
			type: Number,
			default: 0
		},
		//进度条线条宽度[px]
		lineWidth: {
			type: Number,
			default: 4
		},
		/*
			 线条的端点样式
			 butt：向线条的每个末端添加平直的边缘
			 round	向线条的每个末端添加圆形线帽
			 square	向线条的每个末端添加正方形线帽
			*/
		lineCap: {
			type: String,
			default: 'round'
		},
		//圆环进度字体大小 [px]
		fontSize: {
			type: Number,
			default: 12
		},
		//圆环进度字体颜色
		fontColor: {
			type: String,
			default: '#C74547'
		},
		//是否显示进度文字
		fontShow: {
			type: Boolean,
			default: true
		},
		/*
			 自定义显示文字[默认为空，显示百分比，fontShow=true时生效]
			 可以使用 slot自定义显示内容
			*/
		percentText: {
			type: String,
			default: ''
		},
		//是否显示默认(背景)进度条
		defaultShow: {
			type: Boolean,
			default: true
		},
		//默认进度条颜色
		defaultColor: {
			type: String,
			default: '#CCC'
		},
		//进度条颜色
		progressColor: {
			type: String,
			default: '#C74547'
		},
		//进度条渐变颜色[结合progressColor使用，默认为空]
		gradualColor: {
			type: String,
			default: ''
		},
		//起始弧度，单位弧度 实际  Math.PI * sAngle
		sAngle: {
			type: Number,
			default: -0.5
		},
		//指定弧度的方向是逆时针还是顺时针。默认是false，即顺时针
		counterclockwise: {
			type: Boolean,
			default: false
		},
		//进度百分比 [10% 传值 10]
		percentage: {
			type: Number,
			default: 0
		},
		//进度百分比缩放倍数[使用半弧为100%时，则可传2]
		multiple: {
			type: Number,
			default: 1
		},
		//动画执行速度，值越大动画越快（0.1~100）
		speed: {
			type: [Number, String],
			default: 1
		},
		//backwards: 动画从头播；forwards：动画从上次结束点接着播
		activeMode: {
			type: String,
			default: 'backwards'
		}
	},
	watch: {
		percentage(val) {
			this.percent = val;
		}
	},
	mounted() {
		setTimeout(() => {
			this.percent = this.percentage;
		}, 50);
	},
	data() {
		return {
			percent: -1,
			progressCanvasId: this.getCanvasId()
		};
	},
	methods: {
		getCanvasId() {
			return 'tui' + new Date().getTime() + (Math.random() * 100000).toFixed(0);
		},
		change(e) {
			//绘制进度
			this.$emit('change', e);
		},
		end(e) {
			//绘制完成
			this.$emit('end', e);
		}
	}
};
</script>

<style scoped>
.tui-circular-container {
	position: relative;
}
</style>
