6 分钟
Canvas绘图(二)
二、更多接口(续)
6、绘制曲线
(1)绘制圆弧
context.arc() //略 context.arcTo(x1,y1,x2,y2,radius) //起始点为x0,y0
<canvas id="canvas" style="border: 1px solid #aaa;display: block;margin: 50px auto;">
</canvas>
<script>
window.onload=function () {
var canvas = document.getElementById('canvas');
canvas.width = 400;
canvas.height = 400;
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(75,75); //辅助点
context.arcTo(325,75,325,325,150); //绘制的圆弧
//绘制路径为: 辅助点 -> 辅助线的切点 -> 圆弧 -> 切点
context.lineWidth = 6;
context.strokeStyle = "red";
context.stroke();
//以下为辅助线
context.beginPath();
context.moveTo(75,75);
context.lineTo(325,75);
context.lineTo(325,325);
context.lineWidth = 2;
context.strokeStyle = "gray";
context.stroke();
}
</script>
效果如下
(2)绘制二次贝塞尔曲线
context.quadraticCurveTo(x1,y1,x2,y2);
参见:http://blogs.sitepointstatic.com/examples/tech/canvas-curves/quadratic-curve.html
(3)绘制三次贝塞尔曲线
ctx.bezierCurveTo(x1, y1, x2, y2, x3, y3);
参见http://blogs.sitepointstatic.com/examples/tech/canvas-curves/bezier-curve.html
7、渲染文字
context.font = “20px sans-serif”; //此为默认字体样式,css字体设置 context.textAlign = “left|center|right”; //文本水平对齐 默认left context.textBaseline = “top|middle|bottom”; //垂直对齐 默认alphabetic context.measureText(string).width; //返回文本的宽度px context.fillText(“我是文本绘制!”,40,100); context.strokeText(“我是文本绘制!”,40,100);
<canvas id="canvas1" style="border: 1px solid #aaa;display: block;margin: 50px auto;">
</canvas>
<script type="text/javascript">
var canvas=document.getElementById('canvas1');
canvas.width = 400;
canvas.height = 400;
var context=canvas.getContext('2d');
context.font = "20px Georgia";
context.fillText("渲染文字",40,20);
context.lineWidth=1;
context.strokeStyle='#058'
context.strokeText("我是文本描边!",40,60);
context.fillText("我被强制收缩",40,100,80);
context.strokeText("我被强制收缩",40,140,80);
// Create gradient
var gradient=context.createLinearGradient(0,0,canvas.width,0);
gradient.addColorStop("0","magenta");
gradient.addColorStop("0.5","blue");
gradient.addColorStop("1.0","red");
// Fill with gradient
context.fillStyle=gradient;
context.fillText("文字背景色渐变",40,180);
var backgroundImage = new Image();
backgroundImage.src = "gravel.jpg";
backgroundImage.onload = function () {
var pattern = context.createPattern(backgroundImage,"repeat");
context.fillStyle =pattern;
context.font = "bold 100px Arial";
context.fillText("我还有描边效果!",40,650);
context.strokeText("我还有描边效果!",40,650);
}
</script>
效果如下
三、其他接口
1、绘制阴影
context.shadowColor = “#058”; //阴影颜色 context.shadowOffsetX = 10; //阴影偏移量 context.shadowOffsetY = 10; //阴影偏移量 context.shadowBlur = 5; //阴影模糊程度
<canvas id="canvas2" style="border: 1px solid #aaa;display: block;margin: 50px auto;">
</canvas>
<script type="text/javascript">
var canvas=document.getElementById('canvas2');
canvas.width = 400;
canvas.height = 400;
var context=canvas.getContext('2d');
context.fillStyle = "#580";
context.shadowColor = "gray";
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.shadowBlur = 5;
context.fillRect(100,100,200,200);
</script>
效果如下
2、状态变量
context.globalAlpha = 1 //默认为1,全局透明度 context.globalCompositeOperation = “source-over” //默认//重叠效果
<canvas id="canvas3" style="border: 1px solid #aaa;display: block;margin: 50px auto;">
</canvas>
<!--
source-over 默认。在目标图像上显示源图像。
source-atop 在目标图像顶部显示源图像。源图像位于目标图像之外的部分是不可见的。
source-in 在目标图像中显示源图像。只有目标图像内的源图像部分会显示,目标图像是透明的。
source-out 在目标图像之外显示源图像。只会显示目标图像之外源图像部分,目标图像是透明的。
destination-over 在源图像上方显示目标图像。
destination-atop 在源图像顶部显示目标图像。源图像之外的目标图像部分不会被显示。
destination-in 在源图像中显示目标图像。只有源图像内的目标图像部分会被显示,源图像是透明的。
destination-out 在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
lighter 显示源图像 + 目标图像。
copy 显示源图像。忽略目标图像。
xor 这个值与顺序无关,只绘制出不重叠的源与目标区域。所有重叠的部分都变成透明的
-->
<div id="buttons">
<a href="#">source-over</a>
<a href="#">source-atop</a>
<a href="#">source-in</a>
<a href="#">source-out</a>
<a href="#">destination-over</a>
<a href="#">destination-atop</a>
<a href="#">destination-in</a>
<a href="#">destination-out</a>
<a href="#">lighter</a>
<a href="#">copy</a>
<a href="#">xor</a>
</div>
<script>
window.onload=function () {
draw("source-over");
var buttons = document.getElementById("buttons").getElementsByTagName("a");
for (var i = 0; i < buttons.length; i++) {
buttons[i].onclick = function () {
draw(this.text);
return false;
}
}
};
function draw(compositeStyle) {
var canvas = document.getElementById('canvas3');
canvas.width = 1200;
canvas.height = 800;
var context = canvas.getContext('2d');
context.clearRect(0,0,canvas.width,canvas.height);
context.font = "bold 40px Arial";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillStyle = "#058";
context.fillText("globalCompositeOperation = "+ compositeStyle,canvas.width/2,60);
context.fillStyle = "blue";
context.fillRect(300,150,500,500);
context.globalCompositeOperation = compositeStyle;
context.fillStyle = "red";
context.beginPath();
context.moveTo(700,250);
context.lineTo(1000,750);
context.lineTo(400,750);
context.closePath();
context.fill();
}
</script>
演示程序
3、剪辑区域
context.beginPath(); //规划路径 context.clip() //将这个路径围城的区域作为需要渲染的环境,以下渲染将在这个区域内,超出隐藏
探照灯效果
<canvas id="canvas4" width="600" height="600">
当前浏览器不支持Canvas
</canvas>
<script type="text/javascript">
window.onload=function(){
var canvas = document.getElementById('canvas4');
var context=canvas.getContext('2d');
var w =canvas.width;
var h =canvas.height
//探照灯
var ball={
x:w/2,
y:h/2,
r:150,
vx:Math.random()*5+10,
vy:Math.random()*5+10
}
var rot = 0;
setInterval(function(){
draw();
update();
},40);
function draw(){
context.clearRect(0,0,w,h);
context.save();
context.beginPath();
context.fillStyle='black'
context.fillRect(0,0,w,h);
/* 圆形探照灯
context.beginPath();
context.arc(ball.x,ball.y,ball.r,0,2*Math.PI);
context.fillStyle='white';
context.fill();
context.clip();
*/
context.save();
context.translate(ball.x,ball.y);
context.rotate(rot /180 *Math.PI );
context.scale(ball.r,ball.r);
drawStar(context);
context.fillStyle="#fff";
context.fill();
context.restore();
context.clip();
context.beginPath();
context.font='bold 120px Arial';
context.textAlign='center';
context.fillStyle='#ff55cc';
context.fillText('Canvas',w/2,h/3);
context.fillText('Canvas',w/2,h/4*3);
context.restore();
}
function drawStar(ctx) {
ctx.beginPath();
for(var i=0;i<5;i++){
ctx.lineTo(Math.cos((18+i*72)/180*Math.PI),-Math.sin((18+i*72)/180*Math.PI));
ctx.lineTo(Math.cos((54+i*72)/180*Math.PI),-Math.sin((54+i*72)/180*Math.PI));
}
ctx.closePath();
}
function update(){
rot+=1;
ball.x+=ball.vx;
ball.y+=ball.vy;
if(ball.x<=ball.r){
ball.x=ball.r;
ball.vx=-ball.vx;
}
if(ball.x>=w-ball.r){
ball.x=w-ball.r;
ball.vx=-ball.vx;
}
if(ball.y<=ball.r){
ball.y=ball.r;
ball.vy=-ball.vy;
}
if(ball.y>=h-ball.r){
ball.y=h-ball.r;
ball.vy=-ball.vy;
}
}
}
</script>
效果如下
4、镜像方向和剪纸效果
对于复杂图形判读所围成区域是否在区域外部的方法:非零环绕原则
<canvas id="canvas5" width="800" height="800"></canvas>
<!-- 非零环绕原则:取一点,向外画一条射线,如果该线经过了这个图形的边,一个方向为正,一个方向为负,如果非零,则为内部,如果只有一条,则是内部 -->
<script type="text/javascript">
window.onload=function(){
var c = document.getElementById('canvas5');
var context=c.getContext('2d');
context.beginPath();
context.arc(400,400,300,0,2*Math.PI,false)
context.arc(400,400,150,0,2*Math.PI,true);
context.closePath();
context.fillStyle = "#058";
context.shadowColor='#ccc';
context.shadowOffsetX=10;
context.shadowOffsetY=10;
context.shadowBlur=10;
context.fill();
}
</script>
效果如下
5、交互
context.clearRect(x,y,width,height); //清空绘制区域 context.isPointInPath(x,y);
<canvas id="canvas6" style="border: 1px solid #aaa;display: block;margin:50px auto;"></canvas>
<script>
var balls =[];
var canvas = document.getElementById('canvas6');
var context = canvas.getContext('2d');
window.onload=function () {
canvas.width = 800;
canvas.height = 800;
//随机生成小球
for (var i = 0; i < 10; i++) {
var aball = {
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
r: Math.random() * 50 + 20
};
balls[i] = aball;
}
draw();
canvas.addEventListener("mousemove", detect); //添加鼠标事件
}
function draw(x, y) {
context.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < balls.length; i++) {
context.beginPath();
context.arc(balls[i].x, balls[i].y, balls[i].r, 0, Math.PI * 2);
if (context.isPointInPath(x, y))
context.fillStyle = "red";
else
context.fillStyle = "#058";
context.fill();
}
}
function detect(event) {
//鼠标位于获取画布位置
var x = event.clientX - canvas.getBoundingClientRect().left;
var y = event.clientY - canvas.getBoundingClientRect().top;
draw(x,y);
}
</script>
效果如下
6、使用html标签控制canvas
使用css将html控件定位在canvas之上
7、Canvas标准
http://www.w3.org/TR/2dcontext/
8、扩展context2d对象
CanvasRenderingContext2D.prototype.扩展函数名 = function(){ //函数体,可以使用this调用其他context方法 }