(第五天)HTML5之弧度角度与sin&cos(五角星绘
弧度与sin及cos的关系
目的:
通过理解弧度与sin及cos的关系,可以根据弧度及半径求出旋转指定弧度后所到达的dx,dy坐标
弧度(angle)与角度(degree)的关系:
- 360角度 = 2π
- 1角度 = π/180弧度
- 1弧度 = 180/π角度
即:30角度的弧度值 = 30 * (π/180) ,30弧度的角度值 = 30 * (180/π)
通过弧度与半径求旋转指定弧度后目标点的坐标:
- sin(angle) = y/r:y为角的对边长度,即旋转后坐标点的y坐标;r为半径,为斜边长
- cos(angle) = x/r:x为角的邻边长度,即旋转后坐标点的x坐标;r为半径,为斜边长
故围绕中心点(0,0)旋转求值:dx = cos(angle) * r,dy = sin(angle) * r
注:若中心点为(10,20),则dx = 10 + cos(angle) * r,dy = 20 + sin(angle) * r
五角星代码示例1
<body>
<script>
window.onload = function() {
var canvas = document.getElementById("canvas");
if (canvas == null) {
return false;
}
var ctx = canvas.getContext("2d");
drawLine(ctx);
drawStar(ctx);
}
//画横竖线(田字格)
function drawLine(ctx) {
ctx.strokeStyle = "#ccc";
//划横线
for (var i = 0.5; i < 500; i++) {
ctx.beginPath();
ctx.moveTo(0, i * 10);
ctx.lineTo(500, i * 10);
ctx.stroke();
}
//划竖线
for (var i = 0.5; i < 500; i++) {
ctx.beginPath();
ctx.moveTo(i * 10, 0);
ctx.lineTo(i * 10, 500);
ctx.stroke();
}
}
// 画五角星、外边圆,并绘画出以圆心为圆点的坐标轴及各角到圆心的直线
function drawStar(ctx) {
//五角星圆心的坐标位置
var dx = 200;
var dy = 200;
//绘制出五角星外边圆圆心
ctx.beginPath();
ctx.arc(dx, dy, 5, 0, 2 * Math.PI, true);
ctx.fillStyle = "#f00";
ctx.strokeStyle = "#f00";
//设置字号,字体
ctx.font = "14px Verdana";
ctx.strokeText("圆心", dx, dy);
ctx.fill();
//五角星外边圆的半径,即圆心到各个角的距离
var size = 100;
ctx.beginPath();
/*定义一个起始弧度,从这个弧度开始画*/
var startAngle = -Math.PI * 0.5; //逆时针的一个直角弧度,位于y轴坐标正上方位置
/*
*1.五角星划线的角度:一个圆的弧度为2π,分为5个角即2π/5(任意两个点到圆心形成的角度)
*2.2π/5为蓝线圆心-0,圆心-3形成的角度,而五角星划线是从0-1,所以圆心-0,圆心-1的角度是它的两倍,故须*2
*3.圆心-0,圆心-3可以通过此代码打开网页查看
*/
/*dig为圆心-0,圆心-1形成的弧度*/
var dig = (2 * Math.PI / 5) * 2;
/*开始画五角星图*/
ctx.beginPath();
for (var i = 0; i < 5; i++) {
//正弧度顺时针旋转,负弧度逆时针旋转
var angle = startAngle + dig * i;
/*获取当前角度下一个点的x轴坐标:Math.cos(angle) * size*/
//cos(弧度) = x坐标/r r为半径 = 这里的size
var x = dx + Math.cos(angle) * size; //因弧度是以dx,dy为圆心旋转,所以需要加上dx,dy的坐标,以保持图形的圆心仍为dx,dy
/*获取当前角度下一个点的y轴坐标:Math.sin(angle) * size*/
//sin(弧度) = y坐标/r r为半径 = 这里的size
var y = dy + Math.sin(angle) * size;
console.log("x:" + x);
console.log("y:" + y);
ctx.lineTo(x, y);
//给输出文字设置颜色
ctx.strokeStyle = "#00f";
//输出划线先后顺序
ctx.strokeText(i, x, y);
}
//这里必须写,否则五角星会少stroke一条线(不影响fill)
//closePath,闭合图形在非闭合状态下,会通过此方法从当前点至起始点画一条直线
ctx.closePath();
ctx.fillStyle = "rgba(255,255,0,0.5)";
//填充
ctx.fill();
//输出文字的时候设置过,状态已被ctx保存,无须再设置。
//ctx.strokeStyle = "#00f";
//划线
ctx.stroke();
/*划圆心到各角的线*/
ctx.beginPath();
var startAngle = -Math.PI * 0.5;
for (var i = 0; i < 5; i++) {
var angle = startAngle + dig * i;
var x = dx + Math.cos(angle) * size;
var y = dy + Math.sin(angle) * size;
console.log("x:" + x);
console.log("y:" + y);
ctx.moveTo(x, y);
ctx.lineTo(dx, dy);
}
//closePath这里可以不写,因为这里划的都是线,无需闭合
//ctx.closePath();
ctx.strokeStyle = "#f00";
ctx.stroke();
/*开始画五角星周边圆*/
ctx.beginPath();
ctx.arc(dx, dy, size, 0, 2 * Math.PI, true);
ctx.strokeStyle = "#f00";
ctx.stroke();
/*以圆心为起点开始画坐标轴*/
/*坐标轴颜色*/
ctx.strokeStyle = "#000";
//横坐标
ctx.beginPath();
ctx.moveTo(0, dy);
ctx.lineTo(500, dy);
ctx.stroke();
//纵坐标
ctx.beginPath();
ctx.moveTo(dx, 0);
ctx.lineTo(dx, 500);
ctx.stroke();
}
</script>
<canvas id="canvas" height="500" width="500"></canvas>
</body>
上述代码效果图
五角星代码示例2
<script>
function strokeFiveStar() {
var canvas = document.getElementById("canvas");
if (canvas == null) {
return false;
}
var ctx = canvas.getContext("2d");
/*圆心坐标*/
var cx = 200;
var cy = 200;
/*绘制圆心*/
ctx.arc(cx, cy, 5, 0, 2 * Math.PI, false);
ctx.fillStyle = "#f00";
ctx.fill();
/*定义起始绘制点弧度 -90角度,y轴正上方*/
var startAngle = -Math.PI / 2;
//定义半径
var r = 100;
//绘制线条两点(如第1个点与第2个点)与圆心点构成的弧度
var dig = (2 * Math.PI / 5) * 2;
ctx.beginPath();
/*根据角度连接5个点*/
for (var i = 0; i < 5; i++) {
var dx = cx + Math.cos(startAngle + dig * i) * r;
var dy = cy + Math.sin(startAngle + dig * i) * r;
/*i=0时,因没有子路径,故lineTo的作用相当于moveTo*/
ctx.lineTo(dx, dy);
ctx.strokeText("第" + (i + 1) + "个点", dx, dy);
}
/*将最后一个点连接到第一个点*/
ctx.closePath();
ctx.stroke();
}
</script>
上述代码示例效果图
Canvas图形综合操作globalCompositeOperation
使用方法:
ctx.globalCompositeOperation = type
12种type值的介绍:
- source-over:新图形覆盖原图形,其他部分正常显示
- destination-over:原图形覆盖新图形,其他部分正常显示
- source-in:只显示在原图形里面的新图形,其他部分透明
- destination-in:只显示在新图形里面的原图形,其他部分透明
- source-out:只显示在原图形之外的新图形,其他部分透明
- destination-out:只显示在新图形之外的原图形,其他部分透明
- source-atop:新图形只绘制在原图形之上,原图形其他部分正常显示
- destination-atop:原图形只绘制在新图形之上,原图形其他部分正常显示
- lighter:重叠部分变亮,其他部分正常显示
- darker:重叠部分变暗,其他部分正常显示
- xor:重叠部分透明,其他部分正常显示
- copy:只保留新图形,其他部分透明
以上类型的比较可参考Mozilla开发者文档的globalCompositeOperation属性
<!-- globalCompositeOperation demo-->
<head>
<meta charset="UTF-8">
<title>globalCompostionOperation</title>
<script>
function draw(id) {
var canvas = document.getElementById(id);
if(canvas == null) {
return false;
}
var ctx = canvas.getContext("2d");
var types = new Array(
/*0*/"source-over", /*覆盖原图形,其他部分正常显示*/
/*1*/"destination-over",/*覆盖新图形,其他部分正常显示*/
/*2 chrome不支持*/"source-in",/*原图形之内的新图形,其他(原图形&新图形)都透明*/
/*3 chrome不支持*/"destination-in",/*新图形之内的原图形,其他(原图形&新图形)都透明*/
/*4*/"source-out",/*原图形之外的新图形,其他(原图形&新图形)都透明*/
/*5 chrome不支持*/"destination-out",/*新图形之外的原图形,其他(原图形&新图形)都透明*/
/*6 chrome不支持*/"source-atop",/*原图形之上,新图形只绘制原图形范围内部分,其他部分正常显示*/
/*7*/"destination-atop",/*新图形之上,原图形只绘制新图形范围内部分,其他部分正常显示*/
/*8 chrome不支持*/"lighter",/*重叠部分加色,其他不变*/
/*9 chrome不支持*/"darker",/*重叠部分减色,其他不变*/
/*10*/"xor",/*重叠部分透明,其他不变*/
/*11*/"copy"/*只保留新图形,其他清除*/
/*以上类型,详情可参考:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Compositing*/
);
/*设置图形叠加组合模式*/
ctx.globalCompositeOperation = types[10];
ctx.fillStyle = "#f00";
ctx.fillRect(100,100,200,200);
ctx.fillStyle = "#ff0";
ctx.fillRect(150,150,200,200);
}
</script>
</head>
<body onload="draw('canvas')">
<canvas id="canvas" height="500" width="500"></canvas>
</body>
type为xor的效果图
Canvas绘制阴影效果
功能:
为ctx设置阴影效果后,在当前ctx状态下,canvas中绘制的图像都将出现阴影。
使用方法:
- shadowOffsetX:距离图形当前坐标轴x轴的偏移量,默认值为0
- shadowOffsetY:距离图形当前坐标轴y轴的偏移量,默认值为0
- shadowColor:阴影的颜色,默认值为fully-transparent black,即透明
- shadowBlur:阴影的模糊程度,默认值为0
代码示例:
<body>
<script>
window.onload = function () {
var canvas = document.getElementById("canvas");
if (canvas == null) {
return false;
}
var ctx = canvas.getContext("2d");
/*设置x坐标阴影偏移量*/
ctx.shadowOffsetX = -10;
/*设置y坐标阴影偏移量*/
ctx.shadowOffsetY = 10;
/*设置阴影颜色*/
ctx.shadowColor = "#ccc";
/*设置阴影模糊程度,默认是0*/
ctx.shadowBlur = 20;
/*绘制图形*/
ctx.fillStyle = "#ff0";
ctx.fillRect(100,100,50,50);
/*这个图形一样会有阴影效果,ctx的状态不断被更新*/
ctx.fillStyle = "#ff0";
ctx.fillRect(200,100,50,50);
}
</script>
<canvas id="canvas" width="500" height="500">您的浏览器不支持</canvas>
</body>
上述代码效果图
Canvas的图像绘制:drawImage
功能:
通过canvas的drawImage方法 ,将指定图片绘制到canvas画布上。
绘制流程:
- 创建一个图片对象,用来承载图像
var img = new Image();
- 设置图像源
img.src = "xxx.jpg;"
- 监听图像对象的onload事件,图像加载完成后会执行该事件指定的函数
img.onload = draw
- 在onload制定的draw函数中通过drawImage方法将img对象中的图像绘制到canvas画布中
drawImage的3种方法:
-
drawImage(img,destX,destY):以画布的destX、destY作为图像显示起始点,将整个img图像按图像原始像素绘制到画布中,超出画布不绘制;
-
drawImage(img,destX,destY,destWidth,destHeight):将整个img图像绘制到画布中,以画布的destX、destY作为显示图像的起始点,destWidth、destHeight作为图像的显示大小;若destWidth、destHeight大于图像原始像素,则图像会放大(会模糊);反之则缩小。
-
drawImage(img,sourceX,sourceY,sourceWidth,sourceHeight,destX,destY,destWidth,destHeight):从img的sourceX、sourceY起始点,获取sourceWidth、sourceHeight大小的图像,并将获取到的图像draw到画布中,从画布的destX、destY起始点开始绘制,将获取到的图像绘制成destWidth、destHeight大小(destWidth、destHeight若大于sourceWidth、sourceHeight,图像会放大即模糊;反之则缩小)
示例代码:
<script>
window.onload = function () {
var canvas = document.getElementById("canvas");
if (canvas == null) {
return false;
}
var ctx = canvas.getContext("2d");
/*创建一个图片对象*/
var img = new Image();
/*监听图片加载,加载成功结束后执行*/
img.onload = function () {
/*将原图draw到画布上,超出画布部分,不绘制*/
ctx.drawImage(img, 0, 0);
/*将整个img绘制到画布上,画布上的img起始点为100,100,宽高为300*300*/
ctx.drawImage(img, 100, 100, 200, 200);
/*以img的200,200为起始点,在img上获取宽高位150*150范围的图片,
并将获取到的图片粘贴到画布坐标300,300的位置上,图片大小为200*200*/
/*图片会变模糊,因为source的大小是150*150,而dest的大小为200*200*/
ctx.drawImage(img, 200, 200, 150, 150, 300, 300, 200, 200);
}
img.src = "../raw/1.jpg";
};
</script>
上述代码示例效果图
CreateJs之EaselJs基础应用
EaselJs是什么?
EaselJs:一个javascript库,方便更快速的处理canvas。
EaselJs如何使用?
- 引入easeljs的js文件
<script src="https://code.createjs.com/easeljs-0.8.2.min.js"></script>
- 在body元素中创建一个canvas元素
<canvas id="demoCanvas" width="500" height="300"></canvas>
- 基于canvas元素创建一个createjs的舞台
var stage = new createjs.Stage("demoCanvas");
- 创建需要被添加到舞台的对象,如创建一个图形对象
var circle = new createjs.Shape();
- 对图形对象进行处理,如画一个圆
circle.graphics.beginFill("DeepSkyBlue").drawCircle(0, 0, 50);
- 将图形对象添加到舞台中去
stage.addChild(circle);
- 更新舞台
stage.update();
如果需要根据指定的帧频率变化舞台,继续看下方:
8.设置帧频率计时模式createjs.Ticker.timingMode = createjs.Ticker.RAF;
9.设置刷新频率fsp值createjs.Ticker.framerate = 10;
即10fsp,1/10秒的速度刷新。
10.设置Ticker的tick事件监听createjs.Ticker.addEventListener("tick", func);
11.定义func;通过tick事件,会根据指定的频率执行该func函数;所有对舞台的操作在这里处理即可,记得更新舞台stage.update();
*注意点:
1.默认的计时模式为createjs.Ticker.TIMEOUT,
2.RAF计时模式下,framerate无效,
3.RAF模式下动画效果更流畅,
4.不需要按指定帧频率时,可使用RAF计时模式
基础使用的示例代码:
<head>
<meta charset="UTF-8">
<title>easeljs的使用流程</title>
<!--将js引入到文档中-->
<script src="js/easeljs-0.8.2.min.js"></script>
<script>
function init() {
/*基于canvas创建一个Stage对象*/
var stage = new createjs.Stage("demoCanvas");
/*创建一个图形对象*/
var shape = new createjs.Shape();
/*fill一个颜色为黄色,半径为50,圆心在100,100坐标的圆*/
shape.graphics.beginFill("#ff0").drawCircle(100, 100, 50);
/*设置圆的起始坐标点x,y,故圆心位于200,200*/
shape.x = 100;
shape.y = 100;
/*将shape对象加入到stage中*/
stage.addChild(shape);
/*更新stage*/
stage.update();
/* 在shape对象中再画一个圆,圆心100,100,原因与shape
* 的起始位置x,y相关
* f是beginFill的Tiny写法,dc是drawCircle的Tiny写法
* 更多Tiny写法可参考http://www.createjs.com/docs/easeljs/classes/Graphics.html*/
shape.graphics.f("#f00").dc(0, 0, 50);
/*shape发生变化后需要更新舞台才能显示最新的变化*/
stage.update();
/*设置Ticker的计时模式 RAF更流畅,缺点是
忽略帧速率(即忽略createjs.Ticker.framerate)*/
//createjs.Ticker.timingMode = createjs.Ticker.RAF;
/* 设置帧速率,默认是30FSP,即1/30秒执行一次update
* 如果Ticker计时模式设置为createjs.Ticker.RAF,那么此值无效;*/
createjs.Ticker.framerate = 5;
/* 添加一个tick监听事件,tick事件会根据指定的帧速率执行
* 对应的函数,如这里的update*/
createjs.Ticker.addEventListener("tick", update);
/* 计时模式为TIMEOUT的情况下,framerate=5,
* 故该函数会每隔1/5秒的频率被调用*/
function update(event) {
shape.x += Math.random() * 300;
shape.y += Math.random() * 300;
/* 这个500是canvas的宽度,可以通过获得canvas对象.width获得
* 如果shape的起始点x坐标大于canvas宽度,则初始化shape.x=0*/
if (shape.x > 500) {
shape.x = 0;
}
/*如果shape的起始点y坐标大于canvas高度,则初始化shape.y=0*/
if (shape.y > 500) {
shape.y = 0;
}
/*每一次变化都需要通过update()来更新舞台即stage*/
stage.update();
}
}
</script>
</head>
<body onload="init()">
<!--emment写法:canvas#demoCanvas[width=500,height=500]{您的浏览器不支持}-->
<canvas id="demoCanvas" width="500" height="500">您的浏览器不支持</canvas>
</body>
上述代码示例效果图