前言
今天我的小伙伴硬是怼出了一个坦克大战秀给我看,让我亚历山大,更加坚定了发愤图强的决心。。。TI6在即,然而也没有多少时间看胖头鱼吹牛了。
关于曲线的绘制
arc(x, y, radius, startAngle, endAngle, anticlockwise =false)
用于绘制一个圆弧,参数依次表示:x坐标 y坐标 半径 圆弧开始位置 圆弧结束位置 最后一个参数默认表示顺时针方向,如果为true 则为逆时针
画一个圆角矩形
在CSS中,可以用border-radius属性来让矩形的四个角变成圆角。其实也可以用canvas实现。
通过简单分析,可以知道绘制这样一个圆角矩形需要的参数是:
宽度,高度,小圆的半径,以及绘制的位置和context。
实现方法,从右下角开始(也可以从左上角),找到右下角圆心,顺时针绘制一个四分之一圆弧,再绘制一条直线到左下角,再绘制一个四分之一圆弧,再绘制一条直线到左上角……以此类推;
代码:
function drawRoundRect(cxt, x, y, width, height, radius,/*option*/linewidth, /*option*/linecolor){
cxt.save();
cxt.translate(x, y);
pathRoundRect(cxt, width, height, radius);
cxt.lineWidth = linewidth || 1;
cxt.strokeStyle = linecolor ||"black";
cxt.stroke();
cxt.restore();
}
function pathRoundRect(cxt, width, height, radius){
cxt.beginPath();
cxt.arc(width - radius, height - radius, radius, 0, Math.PI/2);
cxt.lineTo(width - radius, height);
cxt.arc(radius, height - radius, radius, Math.PI/2, Math.PI);
cxt.lineTo(0, radius);
cxt.arc(radius, radius, radius, Math.PI, Math.PI/2 * 3);
cxt.lineTo(width - radius, 0);
cxt.arc(width - radius, radius, radius, Math.PI/2 * 3, Math.PI * 2);
cxt.closePath();
}
流程:
先平移坐标轴到指定位置,再开始绘制路径。绘制路径函数为pathRoundRect();
主要为这两个函数,稍微修改一下,就可以绘制2048游戏的矩形图。
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>绘制圆角矩形</title>
</head>
<body>
<canvas id="canvas" width="" height="">
您的浏览器不支持canvas
</canvas>
</body>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 800;
//drawRoundRect(context, 100, 100, 600, 500, 50);
fillRoundRect(context, 150, 150, 500, 500, 10, "#bbada0");
for(var i = 0; i < 4; i ++){
for(var j = 0; j < 4; j ++){
fillRoundRect(context, 170 + i * 120, 170 + j * 120, 100, 100, 6, "#ccc0b3");
}
}
function drawRoundRect(cxt, x, y, width, height, radius,/*option*/linewidth, /*option*/linecolor){
cxt.save();
cxt.translate(x, y);
pathRoundRect(cxt, width, height, radius);
cxt.lineWidth = linewidth || 1;
cxt.strokeStyle = linecolor ||"black";
cxt.stroke();
cxt.restore();
}
function fillRoundRect(cxt, x, y, width, height, radius, /*option*/fillcolor){
cxt.save();
cxt.translate(x, y);
pathRoundRect(cxt, width, height, radius);
cxt.fillStyle = fillcolor || "black";
cxt.fill();
cxt.restore();
}
function pathRoundRect(cxt, width, height, radius){
cxt.beginPath();
cxt.arc(width - radius, height - radius, radius, 0, Math.PI/2);
cxt.lineTo(width - radius, height);
cxt.arc(radius, height - radius, radius, Math.PI/2, Math.PI);
cxt.lineTo(0, radius);
cxt.arc(radius, radius, radius, Math.PI, Math.PI/2 * 3);
cxt.lineTo(width - radius, 0);
cxt.arc(width - radius, radius, radius, Math.PI/2 * 3, Math.PI * 2);
cxt.closePath();
}
</script>
</html>
效果:
其中小方块的位置需要计算一下,也不复杂。注意间隔为20个像素,小方块长宽为100,圆角半径为6. 知道这些参数以后就可以轻易计算出每个的位置。
一个不好用的函数 arcTo
同样的是用来绘制一段弧,与arc不同的是,所需要的参数不一样,绘制原理也不一样。简单来说,这玩意就是
以当前的点为初始值,以参数中的第一个点连接,第一个点与第二个点连接。
绘制一条半径为radius的与这两条线段相切的弧
有点晕?
来看代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>arcTo--一个不怎么好用的函数。。</title>
</head>
<body>
<canvas id="canvas" width="" height=""></canvas>
</body>
<script type="text/javascript">
//arcTo(x1, y1, x2, y2, radius)
//以当前的点为初始值,以参数中的第一个点连接,第一个点与第二个点连接。
//绘制一条半径为radius的与这两条线段相切的弧
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.width = 800;
canvas.height = 800;
context.save();
context.beginPath();
context.moveTo(150, 150);
context.arcTo(650, 150, 650, 650, 300);
context.lineWidth = 6;
context.strokeStyle = "red";
context.stroke();
context.closePath();
context.restore();
context.beginPath();
context.moveTo(150, 150);
context.lineTo(650, 150);
context.lineTo(650, 650);
context.stroke();
context.closePath();
</script>
</html>
效果:
就是这样,会以这两条线段为切线,作一段半径为radius的弧。
起始位置是当前的画笔位置,而不是切线位置。
当然,如果起始位置过劲,则会反向寻找切点。所以线段的长度并不重要。
重头戏-贝塞尔曲线
贝塞尔曲线是一种应用广泛的曲线。能够绘制出任意的、不规则的弧。
函数:
context.quadraticCurveTo(x1, y1, x2, y2);
与arcTo不同的是,他不需要指定弧的半径,而且起始点与终止点就是弧的起始点与终止点。
与arcTo相同的是,他的起始点都是当前画笔所在的点。
例:
context.beginPath();
context.moveTo(100, 100);
context.quadraticCurveTo(400, 400, 100, 500);
context.stroke();
效果:
附上视频中推荐的贝塞尔曲线的交互式网址 http://tinvurl.com/html5quadratic
反正我是打不开。
贝塞尔三次曲线
与二次曲线的区别是,三次曲线拥有两个控制点,而二次曲线只有一个控制点。
这使得贝塞尔三次曲线可以更加灵活的绘制弧。
context.beginPath();
context.moveTo(100, 100);
context.bezierCurveTo(150, 50, 200, 150, 250, 100);
效果:
至于具体的计算。。学过图形学的应该会,反正我不会,到时候慢慢调试就好。
以上~
PS:陆陆续续终于把曲线的部分结束了,接下来就是文字的渲染和高级内容了,加油~