弧度與sin及cos的關(guān)系
目的:
通過理解弧度與sin及cos的關(guān)系鸿竖,可以根據(jù)弧度及半徑求出旋轉(zhuǎn)指定弧度后所到達的dx,dy坐標
弧度(angle)與角度(degree)的關(guān)系:
- 360角度 = 2π
- 1角度 = π/180弧度
- 1弧度 = 180/π角度
即:30角度的弧度值 = 30 * (π/180) 沧竟,30弧度的角度值 = 30 * (180/π)
通過弧度與半徑求旋轉(zhuǎn)指定弧度后目標點的坐標:
- sin(angle) = y/r:y為角的對邊長度,即旋轉(zhuǎn)后坐標點的y坐標缚忧;r為半徑悟泵,為斜邊長
- cos(angle) = x/r:x為角的鄰邊長度,即旋轉(zhuǎn)后坐標點的x坐標闪水;r為半徑糕非,為斜邊長
故圍繞中心點(0,0)旋轉(zhuǎn)求值: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";
//設(shè)置字號鞠呈,字體
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可以通過此代碼打開網(wǎng)頁查看
*/
/*dig為圓心-0房待,圓心-1形成的弧度*/
var dig = (2 * Math.PI / 5) * 2;
/*開始畫五角星圖*/
ctx.beginPath();
for (var i = 0; i < 5; i++) {
//正弧度順時針旋轉(zhuǎn)邢羔,負弧度逆時針旋轉(zhuǎn)
var angle = startAngle + dig * i;
/*獲取當(dāng)前角度下一個點的x軸坐標:Math.cos(angle) * size*/
//cos(弧度) = x坐標/r r為半徑 = 這里的size
var x = dx + Math.cos(angle) * size; //因弧度是以dx,dy為圓心旋轉(zhuǎn),所以需要加上dx,dy的坐標,以保持圖形的圓心仍為dx,dy
/*獲取當(dāng)前角度下一個點的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);
//給輸出文字設(shè)置顏色
ctx.strokeStyle = "#00f";
//輸出劃線先后順序
ctx.strokeText(i, x, y);
}
//這里必須寫,否則五角星會少stroke一條線(不影響fill)
//closePath桑孩,閉合圖形在非閉合狀態(tài)下拜鹤,會通過此方法從當(dāng)前點至起始點畫一條直線
ctx.closePath();
ctx.fillStyle = "rgba(255,255,0,0.5)";
//填充
ctx.fill();
//輸出文字的時候設(shè)置過,狀態(tài)已被ctx保存流椒,無須再設(shè)置敏簿。
//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個點)與圓心點構(gòu)成的弧度
var dig = (2 * Math.PI / 5) * 2;
ctx.beginPath();
/*根據(jù)角度連接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的作用相當(dāng)于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開發(fā)者文檔的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",/*原圖形之內(nèi)的新圖形醋寝,其他(原圖形&新圖形)都透明*/
/*3 chrome不支持*/"destination-in",/*新圖形之內(nèi)的原圖形搞挣,其他(原圖形&新圖形)都透明*/
/*4*/"source-out",/*原圖形之外的新圖形,其他(原圖形&新圖形)都透明*/
/*5 chrome不支持*/"destination-out",/*新圖形之外的原圖形音羞,其他(原圖形&新圖形)都透明*/
/*6 chrome不支持*/"source-atop",/*原圖形之上囱桨,新圖形只繪制原圖形范圍內(nèi)部分,其他部分正常顯示*/
/*7*/"destination-atop",/*新圖形之上嗅绰,原圖形只繪制新圖形范圍內(nèi)部分舍肠,其他部分正常顯示*/
/*8 chrome不支持*/"lighter",/*重疊部分加色,其他不變*/
/*9 chrome不支持*/"darker",/*重疊部分減色窘面,其他不變*/
/*10*/"xor",/*重疊部分透明翠语,其他不變*/
/*11*/"copy"/*只保留新圖形,其他清除*/
/*以上類型财边,詳情可參考:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Compositing*/
);
/*設(shè)置圖形疊加組合模式*/
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>
Canvas繪制陰影效果
功能:
為ctx設(shè)置陰影效果后肌括,在當(dāng)前ctx狀態(tài)下,canvas中繪制的圖像都將出現(xiàn)陰影酣难。
使用方法:
- shadowOffsetX:距離圖形當(dāng)前坐標軸x軸的偏移量谍夭,默認值為0
- shadowOffsetY:距離圖形當(dāng)前坐標軸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");
/*設(shè)置x坐標陰影偏移量*/
ctx.shadowOffsetX = -10;
/*設(shè)置y坐標陰影偏移量*/
ctx.shadowOffsetY = 10;
/*設(shè)置陰影顏色*/
ctx.shadowColor = "#ccc";
/*設(shè)置陰影模糊程度馋嗜,默認是0*/
ctx.shadowBlur = 20;
/*繪制圖形*/
ctx.fillStyle = "#ff0";
ctx.fillRect(100,100,50,50);
/*這個圖形一樣會有陰影效果齐板,ctx的狀態(tài)不斷被更新*/
ctx.fillStyle = "#ff0";
ctx.fillRect(200,100,50,50);
}
</script>
<canvas id="canvas" width="500" height="500">您的瀏覽器不支持</canvas>
</body>
Canvas的圖像繪制:drawImage
功能:
通過canvas的drawImage方法 ,將指定圖片繪制到canvas畫布上葛菇。
繪制流程:
- 創(chuàng)建一個圖片對象甘磨,用來承載圖像
var img = new Image();
- 設(shè)置圖像源
img.src = "xxx.jpg;"
- 監(jiān)聽圖像對象的onload事件,圖像加載完成后會執(zhí)行該事件指定的函數(shù)
img.onload = draw
- 在onload制定的draw函數(shù)中通過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");
/*創(chuàng)建一個圖片對象*/
var img = new Image();
/*監(jiān)聽圖片加載冒掌,加載成功結(jié)束后執(zhí)行*/
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基礎(chǔ)應(yīng)用
EaselJs是什么?
EaselJs:一個javascript庫醇蝴,方便更快速的處理canvas宣肚。
EaselJs如何使用?
- 引入easeljs的js文件
<script src="https://code.createjs.com/easeljs-0.8.2.min.js"></script>
- 在body元素中創(chuàng)建一個canvas元素
<canvas id="demoCanvas" width="500" height="300"></canvas>
- 基于canvas元素創(chuàng)建一個createjs的舞臺
var stage = new createjs.Stage("demoCanvas");
- 創(chuàng)建需要被添加到舞臺的對象悠栓,如創(chuàng)建一個圖形對象
var circle = new createjs.Shape();
- 對圖形對象進行處理霉涨,如畫一個圓
circle.graphics.beginFill("DeepSkyBlue").drawCircle(0, 0, 50);
- 將圖形對象添加到舞臺中去
stage.addChild(circle);
- 更新舞臺
stage.update();
如果需要根據(jù)指定的幀頻率變化舞臺按价,繼續(xù)看下方:
8.設(shè)置幀頻率計時模式createjs.Ticker.timingMode = createjs.Ticker.RAF;
9.設(shè)置刷新頻率fsp值createjs.Ticker.framerate = 10;
即10fsp,1/10秒的速度刷新笙瑟。
10.設(shè)置Ticker的tick事件監(jiān)聽createjs.Ticker.addEventListener("tick", func);
11.定義func楼镐;通過tick事件,會根據(jù)指定的頻率執(zhí)行該func函數(shù)往枷;所有對舞臺的操作在這里處理即可鸠蚪,記得更新舞臺stage.update();
*注意點:
1.默認的計時模式為createjs.Ticker.TIMEOUT,
2.RAF計時模式下师溅,framerate無效茅信,
3.RAF模式下動畫效果更流暢,
4.不需要按指定幀頻率時墓臭,可使用RAF計時模式
基礎(chǔ)使用的示例代碼:
<head>
<meta charset="UTF-8">
<title>easeljs的使用流程</title>
<!--將js引入到文檔中-->
<script src="js/easeljs-0.8.2.min.js"></script>
<script>
function init() {
/*基于canvas創(chuàng)建一個Stage對象*/
var stage = new createjs.Stage("demoCanvas");
/*創(chuàng)建一個圖形對象*/
var shape = new createjs.Shape();
/*fill一個顏色為黃色蘸鲸,半徑為50,圓心在100,100坐標的圓*/
shape.graphics.beginFill("#ff0").drawCircle(100, 100, 50);
/*設(shè)置圓的起始坐標點x,y窿锉,故圓心位于200,200*/
shape.x = 100;
shape.y = 100;
/*將shape對象加入到stage中*/
stage.addChild(shape);
/*更新stage*/
stage.update();
/* 在shape對象中再畫一個圓酌摇,圓心100,100,原因與shape
* 的起始位置x,y相關(guān)
* 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發(fā)生變化后需要更新舞臺才能顯示最新的變化*/
stage.update();
/*設(shè)置Ticker的計時模式 RAF更流暢窑多,缺點是
忽略幀速率(即忽略createjs.Ticker.framerate)*/
//createjs.Ticker.timingMode = createjs.Ticker.RAF;
/* 設(shè)置幀速率,默認是30FSP洼滚,即1/30秒執(zhí)行一次update
* 如果Ticker計時模式設(shè)置為createjs.Ticker.RAF埂息,那么此值無效;*/
createjs.Ticker.framerate = 5;
/* 添加一個tick監(jiān)聽事件,tick事件會根據(jù)指定的幀速率執(zhí)行
* 對應(yīng)的函數(shù)遥巴,如這里的update*/
createjs.Ticker.addEventListener("tick", update);
/* 計時模式為TIMEOUT的情況下千康,framerate=5,
* 故該函數(shù)會每隔1/5秒的頻率被調(diào)用*/
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>