HTML5游戏开发(一)
一、Canvas元素
HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像。
画布是一个矩形区域,您可以控制其每一像素。
canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。
1、一个简单的示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>H5Canvas</title>
<style>
body{
background:#4F4B43;
}
#canvas{
margin: 10px;
padding: 10px;
background: #82A36F;
/*thin定义细的边框 inset将外部阴影 (outset) 改为内部阴影*/
border: thin inset #EDE176;
}
</style>
</head>
<body>
<canvas id='canvas' width="600" height="300"></canvas>
<script type="text/javascript" src="js/canvas.js" ></script>
</body>
</html>
//获取Canvas对象
var canvas=document.querySelector("#canvas");
context=canvas.getContext('2d');
context.font='38pt Arial';
//填充色
context.fillStyle='#EDE176';
//设置字符轮廓线颜色
context.strokeStyle='#C2A84A';
//字符填充,并使文字内容居中
context.fillText("一个Canvas示例", canvas.width/2 - 200,
canvas.height/2 + 15);
//字符轮廓
context.strokeText("一个Canvas示例", canvas.width/2 - 200,
canvas.height/2 + 15 );
查看效果:
注意:
在设置canvas的宽度与高度时,不能使用px后缀。
默认的canvas元素大小是300x500个屏幕像素。
如果是通过CSS来设定canvas元素的大小,那么只会改变元素本身的大小,而不会影响到绘图表面。当canvas元素的大小不符合其绘图表面的大小时,浏览器就会对绘衅表面进行缩放,使其符合元素的大小。
尽量使用属性来设置元素大小,而不使用CSS。
二、时钟绘制
(一)绘制外圆
//定义多个变量
var canvas=document.querySelector("#canvas"),
context=canvas.getContext('2d'),
FONT_HEIGHT = 15, //字体高度
MARGIN = 35, //外边距
RADIUS = canvas.width/2 - MARGIN; //半径
//绘制圆形
function drawCircle() {
context.beginPath();
//路径颜色
context.strokeStyle="#A66085";
//参数分别为:x,y 圆的中心坐标 半径 起始角 结束角 逆时还是顺时true为逆时
context.arc(canvas.width/2, canvas.height/2,
RADIUS, 0, Math.PI*2, true);
context.stroke();
}
function drawClock() {
//清除画布
context.clearRect(0,0,canvas.width,canvas.height);
//绘制外圆
drawCircle();
}
//函数调用
drawClock();
(二)绘制钟表时间数字
var NUMERAL_SPACING = -10, //数字与圆之间的间隔
HAND_RADIUS = RADIUS + NUMERAL_SPACING; //数字半径
//绘制时间数据
function drawNumerals() {
//定义12个小时的数组
var numerals = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ],
angle = 0,
numeralWidth = 0;
//通过循环进行绘制
numerals.forEach(function(numeral) {
//角度
angle = Math.PI/6 * (numeral-3);
numeralWidth = context.measureText(numeral).width;
//填充文字,参数 文本,坐标x,y
context.fillText(numeral,
canvas.width/2 + Math.cos(angle)*(HAND_RADIUS) - numeralWidth/2,
canvas.height/2 + Math.sin(angle)*(HAND_RADIUS) + FONT_HEIGHT/3);
});
}
function drawClock() {
//清除画布
context.clearRect(0,0,canvas.width,canvas.height);
//绘制外圆
drawCircle();
//绘制时间
drawNumerals() ;
}
//函数调用
drawClock();
(三)绘制中心点
//绘制中心点
function drawCenter() {
context.beginPath();
//填充颜色
context.fillStyle="#585E6B";
//绘制位置:参数:坐标x,y 半径,起始角,结束角,方向
context.arc(canvas.width/2, canvas.height/2, 5, 0, Math.PI*2, true);
//填充
context.fill();
}
function drawClock() {
//清除画布
context.clearRect(0,0,canvas.width,canvas.height);
//绘制外圆
drawCircle();
//绘制时间
drawNumerals() ;
//绘制中心点
drawCenter()
}
//函数调用
drawClock();
(三)绘制时分秒针
//时针长短差
var HAND_TRUNCATION = canvas.width/25,
//分针短差
MIN_HAND_TRUNCATION = canvas.width/20,
//时针长度差
HOUR_HAND_TRUNCATION = canvas.width/10;
/**
* 绘制时分秒针通用函数
* @param {Object} loc
* @param {Object} isHour 是否是小时
*/
function drawHand(loc, isType) {
//计算角度
var angle = (Math.PI*2) * (loc/60) - Math.PI/2;
//console.log(isType)
//计算半径
if(isType=='hour'){
handRadius =RADIUS - HAND_TRUNCATION-HOUR_HAND_TRUNCATION;
}else if(isType=='min'){
handRadius =RADIUS - HAND_TRUNCATION-HOUR_HAND_TRUNCATION-MIN_HAND_TRUNCATION;
}else if(isType=='sec'){
handRadius=RADIUS - HAND_TRUNCATION;
}
//起始点为中心点
context.moveTo(canvas.width/2, canvas.height/2);
//结束点,通过向量计算
context.lineTo(canvas.width/2 + Math.cos(angle)*handRadius,
canvas.height/2 + Math.sin(angle)*handRadius);
context.stroke();
}
//绘制时分秒
function drawHands() {
//获取当前小时数
var date = new Date,
hour = date.getHours();
//进行12时计算
hour = hour > 12 ? hour - 12 : hour;
//绘制时针
drawHand(hour*5 + (date.getMinutes()/60)*5, 'hour');
//绘制分针
drawHand(date.getMinutes(), 'min');
//绘制秒针
drawHand(date.getSeconds(), 'sec');
}
function drawClock() {
//清除画布
context.clearRect(0,0,canvas.width,canvas.height);
//绘制外圆
drawCircle();
//绘制时间
drawNumerals() ;
//绘制中心点
drawCenter();
//绘制时分秒针
drawHands();
}
drawClock();
(四)动态显示
//每秒调用一次
setInterval(drawClock,1000);
显示结果:
二、事件处理
HTML5应用程序是以事件来驱动的。可以在HTML元素上注册事件监听器,并编写用一应这些事件的实现代码。
分别有:鼠标事件、键盘事件、触摸事件
(一)鼠标事件
将鼠标坐标转换为Canvas坐标
浏览器通过事件对象传递给监听器的鼠标坐标,是窗口坐标,而不是相对于canvas自身的坐标。
大部分情况下,开发者需要知道的是发生鼠标事件的点相对于canvas的位置,而不是整个窗口中的位置,所以必须进行坐标转换。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>H5Canvas</title>
<style>
body{
background:#4F4B43;
}
#canvas{
margin: 10px;
padding: 10px;
background: #82A36F;
/*thin定义细的边框 inset将外部阴影 (outset) 改为内部阴影*/
border: thin inset #EDE176;
}
</style>
</head>
<body>
<div id='readout'></div>
<canvas id='canvas' width="500" height="250"></canvas>
<script type="text/javascript" src="js/canvasmouse.js" ></script>
</body>
</html>
1、绘制背景
var canvas = document.querySelector('#canvas'),
//用于读取转换后的坐标值
readout = document.querySelector('#readout'),
context = canvas.getContext('2d'),
//创建一个精灵对象
spritesheet = new Image();
//绘制带行分隔线的背景
function drawBackground() {
//定义12个像素的间隔
var VERTICAL_LINE_SPACING = 12,
//获取画布的高度
i = context.canvas.height;
//清空画布
context.clearRect(0,0,canvas.width,canvas.height);
//设定路径颜色
context.strokeStyle = '#61665C';
//线的粗细为0.5
context.lineWidth = 0.5;
//绘制水平分隔线 间隔为12 ,第一行为VERTICAL_LINE_SPACING*4
while(i > VERTICAL_LINE_SPACING*4) {
context.beginPath();
context.moveTo(0, i);
//到画布的宽度
context.lineTo(context.canvas.width, i);
context.stroke();
//一次减去12
i -= VERTICAL_LINE_SPACING;
}
}
drawBackground();
2、绘制精灵
//绘制精灵
function drawSpritesheet() {
context.drawImage(spritesheet, 0, 0);
}
spritesheet.src = 'img/running-sprite-sheet.png';
//通过图像加载事件进行绘制
spritesheet.onload = function(e) {
drawSpritesheet();
};
3、绘制参考线,并读取画布坐标值
//绘制水平线
function drawHorizontalLine (y) {
context.beginPath();
context.moveTo(0,y + 0.5);
context.lineTo(context.canvas.width, y + 0.5);
context.stroke();
}
//绘制垂直线
function drawVerticalLine (x) {
context.beginPath();
context.moveTo(x + 0.5, 0);
context.lineTo(x + 0.5, context.canvas.height);
context.stroke();
}
//绘制引导线
function drawGuidelines(x, y) {
//设置线的颜色
context.strokeStyle = 'rgba(0,0,230,0.8)';
context.lineWidth = 0.5;
//绘制水平线
drawVerticalLine(x);
//绘制垂直线
drawHorizontalLine(y);
}
//更新读取的值
function updateReadout(x, y) {
readout.innerHTML = '(' + x.toFixed(0) + ', ' + y.toFixed(0) + ')';
}
//坐标转换 将window的坐标转换为Canvas的坐标
function windowToCanvas(canvas, x, y) {
//返回canvas的大小与位置
var bbox = canvas.getBoundingClientRect();
//返回x,y值
return { x: x - bbox.left * (canvas.width / bbox.width),
y: y - bbox.top * (canvas.height / bbox.height)
};
}
/**
* 添加鼠标移动事件
* @param {Object} e
*/
canvas.onmousemove = function (e) {
//将window坐标转换为画布坐标
var loc = windowToCanvas(canvas, e.clientX, e.clientY);
//当鼠标移动时,重绘精灵与背景
drawBackground();
drawSpritesheet();
//绘制参考线
drawGuidelines(loc.x, loc.y);
//读取坐标值
updateReadout(loc.x, loc.y);
};
显示效果: