[Canvas绘图] 第12节 帅哥降临

本文介绍了如何利用贝塞尔曲线在Canvas上绘制肖像,通过详细的步骤展示了作者根据自身形象创作的一幅肖像画,包括大耳朵、明亮眼睛、整齐眉毛和瘦削脸颊等特征。代码实现将另行包装分享。
摘要由CSDN通过智能技术生成
本节目标:

(1) 用贝塞尔曲线绘制肖像


实现步骤:

上一节使用了几张美女图片,有美女就必须要有帅哥,这就让我想为自己画张肖像,于是结果是这样的:


张肖像完全是依照我自己的样子来画的,大大的耳朵,明亮的眼睛,整齐秀丽的眉毛,略廋的脸颊,见图如见我。在这里就算和大家见过面了。

这个图当然是用代码画的,代码如下,包装以后再做。

/**
* @usage   贝塞尔曲线绘图
* @author  mw
* @date    2015年12月04日  星期五  10:52:42 
* @param
* @return
*
*/
function myplot() {
		plot.init();
		setPreference();
		
		setSector(1,1,1,1);
		//axis(0, 0, 180);
				
		var h = -80;
		//头发
		hair(0, h, 115);

		//左眉
		eyebow(-20, h+100, 50, 0);
		//右眉
		eyebow(20, h+100, 50, 1);		
		//左眼
		eye(-50, h+110, 50, 0, -Math.PI/24);
		//右眼
		eye(50, h+110, 50, 1, Math.PI/24);		
		
		face(-5, h+70, 220);		
		nose(0, h+110, 85);		
		
		mouth(0, h+210 , 50);
				
		//左耳
		ear(-118, h+80, 120, 0);
		//右耳
		ear(108, h+80, 120, 1);
		
		plot.fillText("帅哥降临 真mw肖像", 100, 150, 300);
		plot.fillText("Hello 大家好,我是mw", 100, -150, 300);
		
}

/**
* @usage   绘制耳朵
* @author  mw
* @date    2015年12月04日  星期五  15:50:18 
* @param
* @return
*
*/

function ear(x, y, r, left) {
	r = Math.abs(r);
	
	plot.save();
	
	left = left ? left : 0;
	if (left == 1) {
	plot.translate(x, y)
		.rotate(Math.PI/ 8)			
		.moveTo(0,0.3 * r)
		.bezierCurveTo(r * 0.2, 0, r *0.4, r * 0.3, r *0.15, r * 0.75)
		.quadraticCurveTo(r * 0.2,  0.98 * r, 0.02 * r, r)	
		.stroke();
		
		//内圈耳
	plot.moveTo(0.05*r,0.3 * r)
		.bezierCurveTo(r * 0.15, 0.2 * r, r *0.3, r * 0.2, r *0.078, r * 0.85)
		.stroke();
		
		plot.restore();
		
	}
	else {
	plot.translate(x, y)
		.rotate(-Math.PI/ 8)	
		.moveTo(0,0.3 * r)
		.bezierCurveTo(-r * 0.2, 0, -r *0.4, r * 0.3, -r *0.15, r * 0.75)
		.quadraticCurveTo(-r * 0.2,  0.98 * r, -0.02 * r, r)	
		.stroke();
		
		//内圈耳
	plot.moveTo(-0.05*r,0.3 * r)
		.bezierCurveTo(-r * 0.15, 0.2 * r, -r *0.3, r * 0.2, -r *0.078, r * 0.85)
		.stroke();
		
		plot.restore();
	}
	


}

/**
* @usage   绘制嘴
* @author  mw
* @date    2015年12月04日  星期五  15:05:52 
* @param
* @return
*
*/

function mouth(x, y, r) {
	plot.save()
		.translate(x-.5 * r, y-r / 6)
		.beginPath()
		.moveTo(0, 0)
		.bezierCurveTo(r / 3, r/16, r * 2 / 3, r/ 16, r, 0)
		.bezierCurveTo(r * 2 / 3, r/3, r/3, r/3, 0, 0)
		.closePath()
		.stroke()
		.restore();
}


/**
* @usage   绘制鼻子
* @author  mw
* @date    2015年12月04日  星期五  14:46:42 
* @param
* @return
*
*/

 function nose(x, y, r) {
	var x0 = 0;
	var y0 = 0;
	
	plot.save()
		.translate(x, y)
		.moveTo(-2, 0)
		.quadraticCurveTo(-0.1 * r, 0.8 * r,
						  -0.16 * r, 0.9 * r)
		.bezierCurveTo(-0.15* r, 0.9 * r,
					  -0.08 * r, 0.8 * r,
					  0, 0.95 * r)
		.stroke();
		
		plot
		.moveTo(2, 0)
		.quadraticCurveTo(0.08 * r, 0.8 * r,
						  0.16 * r, 0.9 * r)
		.bezierCurveTo(0.15* r, 0.9 * r,
					  0.08 * r, 0.8 * r,
					  0, 0.95 * r)
		.stroke();
		
		plot.restore();
 }




/**
* @usage  绘制脸
* @author  mw
* @date    2015年12月04日  星期五  14:31:37 
* @param
* @return
*
*/

	function face(x, y, r) {
		var x0 = x - r / 2;
		var y0 = y;
		var xstep = r / 3;
		var ystep = xstep * 1.8;
		
		plot.moveTo(x0, y0)
			.bezierCurveTo(x0 + xstep, y0 + 2 * ystep,
						   x0 + 2 * xstep, y0 + 2 * ystep,
						   x0 + 3 * xstep, y0)			
			.stroke();
	}



/**
* @usage  绘制眼睛
* @author  mw
* @date    2015年12月04日  星期五  13:55:12 
* @param
* @return
*
*/

	function eye(x, y, r, left, angle) {
		plot.save();
		
		left = left ? left : 0;
		angle = angle ? angle : 0;
		var x0 =  -r / 2;
		var y0 = 0;
		var xstep = r / 3;
		var ystep = xstep / 1.5;
		
		plot.translate(x, y)
			.rotate(-angle)	
			.setFillStyle('black')
			.beginPath()
			.moveTo(x0, y0)
			.bezierCurveTo(x0 + xstep, y0 + ystep, x0 + 2 * xstep, y0 + ystep, 
				x0 + 3 * xstep, y0)
			.bezierCurveTo(x0 + 2 * xstep, y0-ystep, x0 + xstep, y0-ystep, x0, y0)
			.closePath()
			.stroke();
	
			
		fillCircle(x0 + 1.5 * xstep, y0, ystep*0.68);
		plot.setFillStyle('white');
		//这个值取0是左眼,取1是右眼
		if (left == 0) {
			fillCircle(x0 + 1.5 * xstep - 0.28 * xstep, y0- ystep*0.2, ystep*0.2);
		}
		else {
			fillCircle(x0 + 1.5 * xstep + 0.28 * xstep, y0- ystep*0.2, ystep*0.2);
		}
		plot.restore();

	
	}
/**
* @usage   绘制眉毛
* @author  mw
* @date    2015年12月04日  星期五  12:40:57 
* @param
* @return
*
*/

//眉毛
function eyebow(x, y, r, left, thick, angle) {
	
		plot.save()
			.setLineWidth(1);		

		r = Math.abs(r);
		left = left ? left : 0;
		//从x轴逆时针偏移角度
		angle = angle ? -angle : (left ? -Math.PI/12 : -Math.PI/16);
		//粗细
		thick = thick ? thick : 30;
		var xstep = r / 3;
		var ystep = -r/10;		
		var thick = 30;
		var x0 =  x  ;
		var y0 = y;
		
		//左眉
		if (left == 0) { 
			
			xstep = -xstep;
			angle = -angle;
		}
		
		for (var i = 0; i < thick; i++) {
			plot.moveTo(x0, y0)
				.bezierCurveTo(x0 + xstep, 
				   y0 + ystep * (2.2 + Math.random()) + xstep * Math.sin(angle), 
				   x0 + 2 * xstep, 
				   y0 + ystep * (1.2 + Math.random()) + 2 * xstep * Math.sin(angle),
				   x0 + 3 * xstep + 0.5 * xstep * Math.random(), 
				   y0 + 0.2* thick * Math.random() + 3 * xstep * Math.sin(angle));
			
			x0 += Math.random()-0.5;
			y0 += 0.05 * thick * (Math.random()-0.5);
			
			
		}
		
		plot.stroke();
		
		plot.restore();

}

/**
* @usage   绘制头发
* @author  mw
* @date    2015年12月04日  星期五  12:40:57 
* @param
* @return
*
*/

//头发
	function hair(xCenter, yCenter, r) {
		plot.save()
			.setLineWidth(1);	
			
		var x = 0;
		var y = 0;
		var len = r;
		
		var arr = new Array();
		
		var thick = r / 2;
		for (var i = -thick; i < thick; i+= 2 ) {
			arr.push(i, (i * i) / (0.6 * thick));
		}
		
		var xstep = r / 10;
		var ystep = -r / 6;
		while (arr.length > 0) {
			x = xCenter + r/thick * arr.shift();
			y = yCenter + arr.shift();
			
			for (var i = 0; i < 10; i++) {
				plot.moveTo(x - xstep * (Math.random()-0.5), y)
				.bezierCurveTo(x + xstep * (Math.random()-0.5), 
								y + ystep,
								x - 2 * (Math.random()-0.6) * xstep , 
								y + (2 + 2 * (Math.random()-0.5)) * ystep,
								x - 20 * xstep * (Math.random()-0.3), 
								y + (4 + 2 * (Math.random()-0.5)) * ystep);
			}
		}
		plot.stroke();
		plot.restore();
	
	
	
	}
本节就到这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值