canvas绘图 贝塞尔三次方曲线 多点平滑连线

518 阅读2分钟
init(){
				
				let res = [];
	            let len = this.Data.length;
	            var bottomNameData = []
	            for (var i = 0; i < len; i++) {
	                res.push(this.Data[i].newbalances);
	                bottomNameData.push(this.Data[i].months)
	            }
				var can1 = document.getElementById("can1");
				
				var lineBox = document.getElementById("lineBox");
				
				//var width = lineBox.offsetWidth*2;
				
				var ctx = can1.getContext("2d");
				var nums = res;
				var max = Math.max.apply(null,res);//获取y轴最大值
                var mix = Math.min.apply(null,res);//获取y轴最小值
				var datas = bottomNameData;
				
				var width = can1.width,
         		height=can1.height;
		    if (window.devicePixelRatio) {//移动端锯齿解决方案
		        can1.style.width = width + "px";
		        can1.style.height = height + "px";
		        can1.height = height * window.devicePixelRatio;
		        can1.width = width * window.devicePixelRatio;
		      	ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
		    }
			//画出坐标线
			/*function drawBorder(){
				ctx.beginPath();
				ctx.moveTo(100,50);//起始坐标
				ctx.lineTo(100,550);//介绍坐标
				ctx.moveTo(100,550);
				ctx.lineTo(600,550);
				ctx.strokeStyle = 'green';
				//ctx.fill()
				ctx.closePath();
				ctx.stroke();
			}*/
			//画出折线
			function drawLine() {
                for (var i = 0; i < nums.length; i++) {
                    nums[i] = Number(nums[i])
                    //起始坐标
                    var numsY = 200 - nums[i] / max * 160;
                    var numsX = i * (width / nums.length + 1) + 20;
                    //终止坐标
                    var numsNY = 200 - nums[i + 1] / max * 160;
                    var numsNX = (i + 1) * (width / nums.length + 1) + 20;

                    ctx.beginPath();
                    ctx.moveTo(numsX,numsY);
                    ctx.lineTo(numsNX,numsNY);
                    ctx.lineWidth =1* window.devicePixelRatio;
                    ctx.strokeStyle = "red";

					if(i>=6){//后6个点 坐标样式
                        ctx.setLineDash([5,10]);
					}
					ctx.closePath();
                    ctx.stroke();
                }
            }
            /*贝塞尔曲线 关键步骤*/
            function  drawCurve() {
                var dataMax = 0,
                    dataMin = nums[0],
                    diffX = 0
                nums.forEach(function (obj, i) {
                    if (dataMax < obj) dataMax = obj
                    if (dataMin > obj) dataMin = obj
                })
                var drawHeight = height-50;//200
                diffX =width / nums.length+1
                ctx.beginPath()
               nums.forEach(function(item, index) { //找到前一个点到下一个点中间的控制点
                    var scale = 0.1
                    var last1X = diffX * (index - 1)+20,<!--加20表示x从20开始-->
                        last1Y = Math.floor(drawHeight - nums[index - 1]/dataMax*(drawHeight-40)),<!--y轴计算-->
                        last2X = diffX * (index - 2)+20,
                        last2Y = Math.floor(drawHeight - nums[index - 2]/dataMax*(drawHeight-40)),
                        nowX = diffX * (index)+20,
                        nowY = Math.floor(drawHeight - nums[index]/dataMax*(drawHeight-40)),
                        nextX = diffX * (index + 1)+20,
                        nextY = Math.floor(drawHeight - nums[index + 1]/dataMax*(drawHeight-40)),
                        cAx = last1X + (nowX - last2X) * scale,
                        cAy = last1Y + (nowY - last2Y) * scale,
                        cBx = nowX - (nextX - last1X) * scale,
                        cBy = nowY - (nextY - last1Y) * scale
                    if(index === 0) {
                       ctx.lineTo(nowX, nowY)
                        return
                    } else if(index ===1) {
                        cAx = last1X + (nowX - 0) * scale
                        cAy = last1Y + (nowY - drawHeight) * scale
                    } else if(index === nums.length - 1) {
                        cBx = nowX - (nowX - last1X) * scale
                        cBy = nowY - (nowY - last1Y) * scale
                    }
                    ctx.bezierCurveTo(cAx, cAy, cBx, cBy, nowX, nowY);
                })
               var lingrad = ctx.createLinearGradient(0,0,0,width);
               lingrad.addColorStop(0, 'rgb(255, 158, 68)');
               lingrad.addColorStop(1, 'rgb(255, 70, 131)');
               ctx.lineTo(width, drawHeight+20)
               ctx.lineTo(0, drawHeight+20)
                ctx.fillStyle = lingrad
                ctx.fill()
            }
			//绘制折线点的圆点和数值,横坐标值,纵坐标值
			function drawBlock(){
				for (var i = 0;i < nums.length;i ++){
					var numsY = 200-nums[i]/max*160;
					var numsX = i*(width/nums.length+1)+20;
					
					ctx.beginPath();
					// 画出折线上的圆

					ctx.arc(numsX,numsY,4,0,2*Math.PI);
					if(i==0){
						ctx.fillStyle = '#fff'
						ctx.strokeStyle = 'red'
						ctx.fill();
						ctx.stroke();
					}else{
						ctx.fillStyle = 'red'
						ctx.fill();
					}

					ctx.font = "12px Calibri";
					ctx.fillStyle = "#aaaaaa";
					//折线上的点值
					var text = ctx.measureText(nums[i]);
					ctx.fillText(nums[i],numsX-text.width/2,numsY-10);
					ctx.font ="14px Calibri"
					ctx.fillStyle = '#000000';
					//绘制纵坐标
					/*var colText = ctx.measureText((nums.length-i)*500);
					ctx.fillText((nums.length-i)*500,90-colText.width,i*100+55);*/
					//绘制横坐标并判断
					var rowText = ctx.measureText(datas[i]);
					ctx.fillText(datas[i],numsX-rowText.width/2,230);
					ctx.closePath();
					ctx.stroke();
				}
			}
			//drawBorder();
			drawBlock();
			drawLine();
			//drawCurve()
			},