您的位置:首页 > Web前端 > HTML5

《HTML5 Canvas核心技术——图形、动画与游戏开发》第三章要点汇总

2015-08-19 08:35 846 查看

笔记点

使用context.measure("W").width可以获取当前context下W的绘制在canvas上的宽度
通过指定fillText、strokeText中的最后一个参数就可以实现插入canvas的字段指定宽度
使用context.createLinearGradient来实现绘制文本的颜色渐变
使用context.createPattern来实现绘制文本用image来填充在线演示
对context.font的设置是需要按照如下顺序的
1、font-style(normal/italic/oblique)(实测中Firefox对此属性貌似不支持)

2、font-variant(normal/small-caps)
3、font-weight(normal/bold/bolder/lighter/100/200...)字符的笔画粗细
4、font-size(xx-small/x-small/medium/large/x-large/xx-large)字型的大小
5、line-height:(书中)浏览器会将该属性强制设定为其默认值,如果你设置了该值,浏览器会忽略你所制定的值(那为什么还要指定)
6、font-family

使用textAlign来实现文本的左右对齐,使用textBaseline来实现文本的上下对齐

在canvas中实现对文本的输入

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
#canvas {
border: thin solid red;
}
</style>
</head>

<body>
<div id="controls">
<select name="fontSelect" id="fontSelect">
<option value="幼圆">幼圆</option>
<option value="宋体">宋体</option>
<option value="黑体">黑体</option>
</select>
<select name="sizeSelect" id="sizeSelect">
<option value="24">24</option>
<option value="48">48</option>
<option value="96">96</option>
<option value="192">192</option>
</select>
<select name="strokeStyleSelect" id="strokeStyleSelect">
<option value="lightred">lightred</option>
<option value="lightgreen">lightgreen</option>
<option value="lightblue">lightblue</option>
<option value="lightgray">lightgray</option>
</select>
<select name="fillStyleSelect" id="fillStyleSelect">
<option value="lightred">lightred</option>
<option value="lightgreen">lightgreen</option>
<option value="lightblue">lightblue</option>
<option value="lightgray">lightgray</option>
</select>
</div>
<canvas id="canvas" width="800" height="600"></canvas>
</body>
<script type="text/javascript">
/* 这是书中代码自带的一个TextCursor对象的代码
* Copyright (C) 2012 David Geary. This code is from the book
* Core HTML5 Canvas, published by Prentice-Hall in 2012.
*
* License:
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* The Software may not be used to create training material of any sort,
* including courses, books, instructional videos, presentations, etc.
* without the express written consent of David Geary.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
// Cursor.........................................................
TextCursor = function(fillStyle, width) {
this.fillStyle = fillStyle || 'rgba(0, 0, 0, 0.7)';
this.width = width || 2;
this.left = 0;
this.top = 0;
};
TextCursor.prototype = {
getHeight: function(context) {
var h = context.measureText('M').width;
return h + h / 6;
},
createPath: function(context) {
context.beginPath();
context.rect(this.left, this.top,
this.width, this.getHeight(context));
},
draw: function(context, left, bottom) {
context.save();
this.left = left;
this.top = bottom - this.getHeight(context);
this.createPath(context);
context.fillStyle = this.fillStyle;
context.fill();
context.restore();
},
erase: function(context, imageData) {
context.putImageData(imageData, 0, 0,
this.left, this.top,
this.width, this.getHeight(context));
}
};
// Text lines.....................................................
TextLine = function(x, y) {
this.text = '';
this.left = x;
this.bottom = y;
this.caret = 0;
};
TextLine.prototype = {
insert: function(text) {
this.text = this.text.substr(0, this.caret) + text +
this.text.substr(this.caret);
this.caret += text.length;
},
removeCharacterBeforeCaret: function() {
if (this.caret === 0)
return;
//此处this.caret-1意思就是把最后一个字符给去掉
this.text = this.text.substring(0, this.caret - 1) +
this.text.substring(this.caret);
this.caret--;
},
getWidth: function(context) {
return context.measureText(this.text).width;
},
getHeight: function(context) {
var h = context.measureText('W').width;
return h + h / 6;
},
draw: function(context) {
context.save();
context.textAlign = 'start';
context.textBaseline = 'bottom';
context.strokeText(this.text, this.left, this.bottom);
context.fillText(this.text, this.left, this.bottom);
context.restore();
},
erase: function(context, imageData) {
context.putImageData(imageData, 0, 0);
}
};
</script>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var fontSelect = document.getElementById("fontSelect");
var sizeSelect = document.getElementById("sizeSelect");
var strokeStyleSelect = document.getElementById("strokeStyleSelect");
var fillStyleSelect = document.getElementById("fillStyleSelect");
var cursor = new TextCursor();
var line;
var blinkingInterval;
var BLINK_TIME = 1000;
var BLINK_OFF = 300;

function drawBackground() {
var STEP_Y = 12,
TOP_MARGIN = STEP_Y * 4,
LEFT_MARGIN = 35,
i = context.canvas.height;
context.save();
context.strokeStyle = 'lightgray';
context.lineWidth = 0.5;
while (i > TOP_MARGIN) { // Draw horizontal lines from bottom up
context.beginPath();
context.moveTo(0, i);
context.lineTo(context.canvas.width, i);
context.stroke();
i -= STEP_Y;
}
// Draw vertical line
context.strokeStyle = 'rgba(100,0,0,0.3)';
context.lineWidth = 1;
context.beginPath();
context.moveTo(LEFT_MARGIN, 0);
context.lineTo(LEFT_MARGIN, context.canvas.height);
context.stroke();
context.restore();
}

function windowToCanvas(x, y) {
var bbox = canvas.getBoundingClientRect();
return {
x: x - bbox.left * (canvas.width / bbox.width),
y: y - bbox.top * (canvas.height / bbox.height)
};
}

function saveDrawingSurface() {
drawingSurfaceImageData = context.getImageData(0, 0, canvas.width, canvas.height);
}

function setFont() {
//易错点:px左边有一个空格键,在font中设置的时候是在字号和字体之间有一个空格键的
context.font = sizeSelect.value + "px " + fontSelect.value;
}

function blinkCursor(x, y) {
clearInterval(blinkingInterval);
blinkingInterval = setInterval(function(e) {
cursor.erase(context, drawingSurfaceImageData);
setTimeout(function(e) {
//当光标需要闪动的时候触发
//我们在输入的状态下是不会触发这个if中的内容的
//我还不懂为什么在输入的状态下不会触发if中的内容
//这个if中的条件到底是用来做什么的-->应该是判定是否要闪动的,但是为什么是这样写呢?
if (cursor.left == x && cursor.top + cursor.getHeight(context) == y) {
cursor.draw(context, x, y);
}
}, 300);
}, 1000);
}

function moveCursor(x, y) {
cursor.erase(context, drawingSurfaceImageData);
saveDrawingSurface();
context.putImageData(drawingSurfaceImageData, 0, 0);
cursor.draw(context, x, y);
blinkCursor(x, y);
}
canvas.onmousedown = function(e) {
var loc = windowToCanvas(e.clientX, e.clientY);
var fontHeight = context.measureText("W").width;
fontHeight += fontHeight / 6;
line = new TextLine(loc.x, loc.y);
moveCursor(loc.x, loc.y);
};
fillStyleSelect.onchange = function(e) {
//此处为什么还要对cursor的style进行设置
//因为光标也要跟着变颜色的,你选了lightblue,那么当前的光标的颜色就是lightblue
cursor.fillStyle = fillStyleSelect.value;
context.fillStyle = fillStyleSelect.value;
}
strokeStyleSelect.onchange = function(e) {
cursor.strokeStyleSelect = strokeStyleSelect.value;
context.strokeStyle = strokeStyleSelect.value;
}
//按下任意键触发
document.onkeydown = function(e) {
//8是BackSpace,13是Enter
//这里的作用何在?~本来他也会触发默认的情况的嘛~
if (e.keyCode === 8 || e.keyCode === 13) {
e.preventDefault();
}
if (e.keyCode === 8) {
context.save();
line.erase(context, drawingSurfaceImageData);
//删去最后一个字符
line.removeCharacterBeforeCaret();
//光标移动
moveCursor(line.left + line.getWidth(context), line.bottom);
line.draw(context);
context.restore();
}
};
//按下字母数字键是触发
document.onkeypress = function(e) {
var key = String.fromCharCode(e.which);
//e.ctrlKey是判断Ctrl键是否被按下了
//e.metaKay是判断meta键是否被按下,这个键现代的键盘上已经很少了---by2015年
if (e.keyCode !== 8 && !e.ctrlKey && !e.metaKey) {
e.preventDefault();
context.save();
line.erase(context, drawingSurfaceImageData);
line.insert(key);
moveCursor(line.left + line.getWidth(context), line.bottom);
context.shadowColor = "rgba(0, 0, 0, 0.5)";
context.shadowOffsetX = 1;
context.shadowOffsetY = 1;
context.shadowBlur = 2;
line.draw(context);
context.restore();
}
};
fontSelect.onchange = setFont;
sizeSelect.onchange = setFont;
cursor.fillStyle = fillStyleSelect.value;
cursor.strokeStyle = strokeStyleSelect.value;
context.fillStyle = fillStyleSelect.value;
context.strokeStyle = strokeStyleSelect.value;
context.lineWidth = 2.0;
setFont();
drawBackground();
saveDrawingSurface();
</script>
</html>


在线演示
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: