关闭

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

547人阅读 评论(0) 收藏 举报
分类:

笔记点

  • 使用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>


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:141620次
    • 积分:3007
    • 等级:
    • 排名:第12059名
    • 原创:157篇
    • 转载:53篇
    • 译文:0篇
    • 评论:14条
    文章分类