目錄
0x00 在Canvas中使用其他HMTL 元素
canvas本身並不是透明的,默認背景色爲白色。
如果將一個html標籤,放在了canvas標籤之前,即便是我們對該標籤進行了絕對定位,那麼該標籤也有可能被canvas遮擋住
建議將浮動在canvas之上的標籤放在canvas之後。
同時也可以通過z-index屬性來調整不同的div在z軸方向的先後順序
案例:
效果:
代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet">
<style>
#canvas-wrapper{
position: absolute;;
top:50%;
left:50%;
transform: translate(-50%,-50%);
width:1024px;
height:650px;
}
#controller{
position:absolute;
top:30px;
left:30px;
width:200px;
border-radius:10px;
padding:15px;
background: rgba(0,85,116,0.7);
color:#fff;
}
.btn-black{
background:black;
}
.btn-white{
background:white;
}
</style>
</head>
<body>
<div id='canvas-wrapper'>
<canvas id='canvas'></canvas>
<div id="controller">
<h4>Canvas 控制面板</h4>
<a href="javascript:;" id='canvas-btn' class='btn btn-danger'>停止運動</a>
<a href="javascript:;" id='black-color-btn' class='btn btn-black'> </a>
<a href="javascript:;" id='white-color-btn' class='btn btn-white'> </a>
</div>
</div>
</body>
<script>
var themeColor = 'white';
var isMoving = true;
window.onload = function(){
var canvas = document.getElementById('canvas');
canvas.width=1024;
canvas.height=650;
var ctx = canvas.getContext('2d');
ctx.globalAlpha = 1;
ctx.globalCompositeOperation='xor';
balls = [];
for(var i=0;i<100;i++){
var R = Math.floor(Math.random()*255);
var G = Math.floor(Math.random()*255);
var B = Math.floor(Math.random()*255);
var color = "rgba("+R+","+G+","+B+")";
var ball = {
x:Math.random()*canvas.width,
y:Math.random()*canvas.height,
r:Math.random()*100,
vx:Math.random()*20,
vy:Math.random()*20,
c:color
}
balls.push(ball);
}
setInterval(function(){
render(ctx);
if(isMoving){
update(ctx);
}
},50)
document.getElementById('canvas-btn').onclick = function(){
if(isMoving){
isMoving = false;
this.text = "開始運動";
}else{
isMoving = true;
this.text = "停止運動";
}
return false;
}
document.getElementById('white-color-btn').onclick = function(){
themeColor = "white";
return false;
}
document.getElementById('black-color-btn').onclick = function(){
themeColor = "black";
return false;
}
}
function render(ctx){
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
// console.log(ctx.canvas.height);
if(themeColor == "black"){
ctx.fillStyle = "black";
ctx.fillRect(0,0,canvas.width,canvas.height);
}
for(var i=0;i<balls.length;i++){
ctx.beginPath();
ctx.fillStyle = balls[i].c;
ctx.arc(balls[i].x,balls[i].y,balls[i].r,0,Math.PI * 2);
ctx.closePath();
ctx.fill();
}
}
function update(ctx){
for(var i =0;i<balls.length;i++){
balls[i].x += balls[i].vx;
balls[i].y += balls[i].vy;
// 碰撞檢測
// 下邊緣碰撞檢測
if(balls[i].y >= ctx.canvas.height - balls[i].r){
balls[i].y = ctx.canvas.height - balls[i].r;
balls[i].vy = -balls[i].vy*0.5;//每次反彈都會損失能量
}
if(balls[i].y <= 0 +balls[i].r){
balls[i].y = 0+balls[i].r;
balls[i].vy = -balls[i].vy;
}
if(balls[i].x <= 0+balls[i].r){
balls[i].x = 0+balls[i].r;
balls[i].vx = -balls[i].vx;
}
if(balls[i].x >= ctx.canvas.width-balls[i].r){
balls[i].x = ctx.canvas.width-balls[i].r;
balls[i].vx = - balls[i].vx;
}
}
}
</script>
</html>
0x01 擴展Canvas的context對象
我們可以將我們自己寫的函數添加給
CanvasRenderingContext.prototype,使之成爲ctx的一個接口
CanvasRenderingContext 就是我們獲取的context對象,所以我們需要將函數中的ctx 全部修改爲this
代碼:
window.onload=function(){
var canvas = document.getElementById('canvas');
canvas.width = document.body.clientWidth;
canvas.height =document.body.clientHeight;
var ctx = canvas.getContext('2d');
/**
* 規劃彎月的路徑
*
*/
CanvasRenderingContext2D.prototype.pathMoon=function(d){
this.beginPath();
this.arc(0,0,1,0.5*Math.PI,1.5*Math.PI,true);
this.moveTo(0,-1);
this.quadraticCurveTo(1.2,0,0,1);
this.closePath();
}
/**
* 繪製一輪填充的彎月
* @ d 控制點座標的橫座標值
* @ x,y 彎月的位置
* @ R 彎月的半徑
* @ rot 旋轉角度 角度值
* @ fillColor 可選
*/
CanvasRenderingContext2D.prototype.fillMoon = function(d,x,y,R,rot,fillColor){
this.save();
this.translate(x,y);
this.rotate(rot * Math.PI / 180);
this.scale(R,R);
this.pathMoon(d);
this.fillStyle = fillColor || "#fb5";
this.fill();
this.restore();
}
//黑夜
var skyStyle = ctx.createLinearGradient(0,0,0,canvas.height);
skyStyle.addColorStop(0.0,'black');
skyStyle.addColorStop(1.0,'#035');
ctx.fillStyle = skyStyle;
ctx.fillRect(0,0,canvas.width,canvas.height);
//200個星星
for(var i=0;i<40;i++){
var r = Math.random() * 5 + 2; //2 - 7之間的隨機值
var x = Math.random() * canvas.width;
var y = Math.random() * canvas.height / 3;
var rot = Math.random() * 360;
drawStar(ctx,r,x,y,rot);
}
//繪製月亮
ctx.fillMoon(2,900,200,100,30);
//繪製綠地
drawLand(ctx);
}
/**
* 產生一個標準星星的路徑
* 一個位於(0,0)點 外圓半徑爲1,內圓半徑爲0.5的星星
*
*/
function starPath(ctx){
var R = 1;
var r = 0.5 * R;
var rot =0;
var x = 0;
var y =0;
ctx.beginPath();
for(var i=0;i<5;i++){
// 大圓半徑爲300 ,平移400px
ctx.lineTo(
Math.cos((18 +i*72 - rot)*Math.PI/180)*R + x,
-Math.sin((18 +i*72 - rot )*Math.PI/180)*R + y
);
//小圓半徑爲150,平移400px;
ctx.lineTo(
Math.cos((54 +i*72 - rot)*Math.PI/180)*r +x,
-Math.sin((54 +i*72 - rot)*Math.PI/180)*r +y
);
}
ctx.closePath();
}
/**
* 繪製一個五角星
* ctx 上下文
* r 小圓半徑
* x x軸方向上的平移
* y y軸方向上的平移
* rot 順時針旋轉角度
*/
function drawStar( ctx,r,x,y,rot){
ctx.save();
//因爲 我們左上角座標是0,0,所以scale不會改變左上角的座標
ctx.translate(x,y);
ctx.rotate(rot * Math.PI/180);
ctx.scale(r,r);
starPath(ctx);
ctx.lineJoin = 'round';
ctx.fillStyle = '#fb3';
ctx.strokeStyle = '#fd5';
ctx.fill();
ctx.restore();
}
// 計算兩點間的距離
function dis(x1,y1,x2,y2){
return Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
}
function drawLand(ctx){
ctx.save();
ctx.beginPath();
ctx.moveTo(0,600);
ctx.bezierCurveTo(540,400,660,800,document.body.clientWidth,600);
ctx.lineTo(document.body.clientWidth,document.body.clientHeight);
ctx.lineTo(0,document.body.clientHeight);
ctx.closePath();
var landStyle = ctx.createLinearGradient(0,800,0,0);
landStyle.addColorStop(0.0,'#030');
landStyle.addColorStop(1.0,'#580');
ctx.fillStyle=landStyle;
ctx.fill();
ctx.restore();
}
0x02 Canvas與瀏覽器兼容性
通過if(ctx.函數名) 可以判斷瀏覽器是否支持該函數