《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>
在线演示
相关文章推荐
- html5离线缓存--manifest
- HTML5 随手记(4)
- web socket and web worker 基础原理及使用
- HTML5 cavans的使用
- html5 history解析
- html5+css3(二)
- 有关html5的特性(一)
- HTML5 LocalStorage 本地存储
- HTML5游戏实战之20行代码实现打地鼠
- HTML5新api即pushState和replaceState实现无刷新修改url
- Html5文件
- HTML5新标签
- atitit.js 与c# java交互html5化的原理与总结.doc
- atitit.js 与c# java交互html5化的原理与总结.doc
- atitit.js 与c# java交互html5化的原理与总结.doc
- Java开发人员必须重视HTML5的五点理由
- 如何在HTML5页面播放加密视频
- HTML5框架、背景和实体
- html5学习之路_001
- 详解HTML5中的<aside>元素与<article>元素