在你的浏览器中通过 HTML5 Canvas & JavaScript,命令控制台

分享于 

26分钟阅读

Web开发

  繁體

介绍

更新笔记 2016-04-28: 我修复了处理退格键并输入键的问题。 有一段时间,只有 Firefox 不工作,但 Chrome 停止工作。 现在已经修复了。你可以在最后一个代码示例中看到代码更改。

我一直在学习 HTML5 Canvas 元素的力量和你能做什么。 我想看看是否可以在浏览器中复制命令行控制台,以后可以使用玩具和玩笑。 我就是这么做的。

在图像 below 中,我在浏览器( 是后面的那个) 中拍摄了一个控制台快照,包括一个真正的控制台窗口( 用于比较)。 即使游标 blink --显示控制台窗口,我也能够捕获显示两个游标的图像。 我的版本闪烁 cursor 也

查看现场演示

你可以在浏览器中看到它的位置: http://raddev.us/console/console.htm ( 在新的选项卡/窗口中打开)

。与实际控制台窗口相比,浏览器中的控制台

Background

HTML5 Canvas 元素非常强大,易于上手,但是仍然有很多 Flash 在这里。 我认为这个小例子很简单,从画布元素开始就会激发你开始自己的项目。

further和 Jeff Fulton ( o'pub pub pub pub ( 在新窗口/标签中打开)。 这是一本伟大的书,将引导你进入技术,并带你。 写得很好并且有你需要的细节。

设置我们的HTML

第一步是设置HTML和画布工作,大部分工作是在JavaScript中完成的。 下面是简单HTML的完整清单

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><title>console</title><linkrel="stylesheet"href="css/main.css"/></head><body><canvasid="gamescreen">You're browser does not support HTML5.</canvas><scriptsrc="js/console.js"></script></body></html>

第一行包含预期的DOCTYPE定义。 这是给浏览器的消息,它应该期望它应该是 HTML。

我添加了自然语言标记,因为它将是英文。

链接 CSS

接下来要注意的是我将链接放到样式表中,我只是在名为的子文件夹中创建了一个 main.css

我喜欢把一切都分开,因为它应该是好的干净代码。 即使在这样的短程序中,这样也很重要,因为它可以更容易地。

下面是非常简单的CSS:

/* main.css */body,html {margin:0;padding:0;}

这个CSS除了删除浏览器自动分配的所有 padding 和 margin 距离之外,什么也不做。 如果可能,我不希望画布元素与浏览器工作区内部之间存在任何空间。

finally,在HTML中还有另外两行内容。

设置画布元素

第一个设置画布元素,并给它一个 gamescreen的id。 这使得我可以从我的JavaScript引用这个元素,我们将很快看到。

<canvasid="gamescreen">You're browser does not support HTML5.</canvas>

仅当用户不支持HTML5时,才显示开始和结束画布元素之间的文本。 让他们知道应用程序不会在浏览器中工作是一种简单的方法。

接下来,我将包含对JavaScript的引用,它将驱动整个程序。

<scriptsrc="js/console.js"></script>

同样,我将JavaScript放在名为 js的子文件夹中,以保持。

为什么JavaScript包含在所有内容之后?

画布元素之后加载JavaScript非常重要,因为JavaScript中的代码将引用画布元素。 还有其他方法可以解决这个问题: 使用jquery方法的ready() 或者页面的OnLoad() 事件。 但是,为了保持这个介绍性文章,我选择在画布元素后面添加 JavaScript,以便在画布元素之后加载 JavaScript。

事件的基本摘要

现在我们已经设置了我们的小应用程序将按以下方式运行:

1.页面将加载

2.css将加载

3。JavaScript将加载并执行一些操作。

了解代码的基本操作是控制代码工作方式的第一步和最强大的步骤。 现在,我们来看看实际执行工作的代码。

所有的代码都可以在 console.js 文件中找到。

JavaScript支持画布元素

整个 console.js 超过 220行代码 --,但是很长时间看全部,所以我将把它分解掉,我们将讨论部分代码。 然后,你可以下载代码并检查整个列表。

应用程序初始化

首先让我们看看需要初始化的基本项目,以及为什么我需要在应用程序开始绘图之前设置它们。

//consle.jsvar ctx = null;var theCanvas = null;var lineHeight = 20;var widthOffset = 2;var cursorWidth = 8;var cursorHeight = 3;var fontColor = "#C0C0C0";var outputFont = '12pt Consolas';var charWidth;var allUserCmds = [ ]; // array of strings to hold the commands user typesvar currentCmd = ""; // string to hold current cmd user is typingvar PROMPT = "c:>";var promptWidth = null;var promptPad = 3;var leftWindowMargin = 2;var cursor = null;
window.addEventListener("load", initApp);var flashCounter = 1;

JavaScript如何运行

要了解的第一个问题是JavaScript如何运行。 如你所见,console.js 在文件顶部有一系列初始化。 但是这个代码? 答案是,一旦浏览器加载JavaScript文件,则函数外部的任何代码都以顶层顺序运行。 这意味着显示为 上面 --的代码不会在单独的函数中包装,而是从顶部。

全局变量:运行&尖叫

这是惰性编码器的方法,它初始化一些我们需要的项目。 在较大的应用程序中,因为这些变量是全局变量,并且应该发送你的值。

全局变量很简单: 定义的反模式

这是一个很好的时间,因为创建全局变量是非常容易的。 这为JavaScript通常创建的方式创建了一个 Pattern,实际上它是一个反模式。 反模式是非常流行的,但仍然是错误的。 如果你将了解这个例子是错误的,那么你将在它的他许多开发人员之前进行。

现在,让我们看看我的控制台如何使用这些变量。

画布上下文对象

这里示例中的第一个和最重要的变量是名为 ctx的变量。

你可以看到,我只是将对象初始化为 null。 我有一个命名对象,我可以在以后初始化和使用它。

跳到最后一行,它看起来像:

window.addEventListener("load", initApp);

这是使用纯JavaScript添加 EventListener的标准方法。 这告诉浏览器在 load 事件( 第一个参数) 激发时,调用我们定义的名为 initApp的方法。

注意第一个参数是字符串( 双引号 surrouded ),但最后一个参数是一个对象( 无双引号),它是名为 initApp的函数。 如果仔细阅读,你就知道JavaScript函数是第一类对象。 这意味着JavaScript中的函数是对象,可以使用它们的名称轻松引用。

谁触发加载事件?

加载事件时浏览器本身就会触发load事件。 我们通知浏览器在文档加载完成时通知我们。 还有许多其他的事件,我们可以作为第一个参数提供。 另外,如果我们使用了"装载"或者"装载"这个单词,我们也要记住,因为JavaScript解释器不知道这些事件。 事件由JavaScript创建者预定义。 你可以通过 google JavaScript事件查找更多信息。

好,当文档加载时,我想得到通知,我希望我的initApp() 方法被调用。

所以,在所有变量初始化之后,我都将 register 事件保证为 initApp 方法被调用。

现在我们跳下 initApp() 函数,这样我们可以看到它做了什么工作。

近距离查看 initApp() 函数

initApp函数的整个代码如下所示:

function initApp()
{
 theCanvas = document.getElementById("gamescreen");
 ctx = theCanvas.getContext("2d");
 ctx.font = outputFont;
 var metrics = ctx.measureText("W");
 // rounded to nearest int charWidth = Math.ceil(metrics.width);
 promptWidth = charWidth * PROMPT.length + promptPad;
 cursor = new appCursor({x:promptWidth,y:lineHeight,width:cursorWidth,height:cursorHeight});
 window.addEventListener("resize", draw);
 window.addEventListener("keydown",keyDownHandler);
 window.addEventListener("keypress",showKey);
 initViewArea();
 setInterval(flashCursor,300);
 function appCursor (cursor){
 this.x = cursor.x;
 this.y = cursor.y;
 this.width = cursor.width;
 this.height = cursor.height;
 }
}

你可以看到的第一件事是调用标准 document 方法 getElementById() 并传入我们以前在HTML中定义过的id。 这表示HTML中的Canvas 元素。

有了这个元素,我们可以调用一个代价为的HTML5特定方法所有支持HTML5的浏览器都为我们定义了: getContext("2d")

这种方法将返回 ctx 变量,我们将在 Canvas 变量中存储该对象,因此我们可以在变量中绘制。 每个要在画布上绘制的HTML5应用程序都有一个类似于这个的调用。 这个命令告诉我们,我们想通过提供字符串作为参数来完成 2d 绘图。

利用上下文对象的强大功能

装载这个对象的全部想法是,HTML5开发者和浏览器开发者已经包含了一个库功能,我们现在可以使用。 既然已经获得了 context 对象,现在就可以调用已经为我们定义的方法。 调用它们就像下面这样简单:

1.了解函数的名称

2.了解他们期望的参数( 如果有的话)

要了解更多关于上下文对象的信息,我只需要 google: HTML5上下文对象。

其中的一个链接是:

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D^

这是一个伟大的Mozilla ( Firefox 组织) 站点,拥有很多信息。

画布上每个字母的宽度

我知道,我需要知道--处理画布--上绘制的文本的一个事件是每个字母的宽度。

没有简单的方法可以得到那个价值。 阅读了大量的阅读之后,我发现了我认为最好的方法

1.设置 font-family 和大小( outputFont ),以便在测量字符的宽度基于将要输出的字体时。 我们调用 Canvas context 属性命名恰当,font:

ctx.font = outputFont;

2.使用我的字体集中最宽的字母: 字母W 会做的。

3。调用上下文方法 measureText() 以获取它的宽度

4.将该值舍入到最接近的整数并存储以便以后使用

之后,我将在控制台窗口中显示每个字符的基本宽度。

输出字体

我们还设置了 font-family 和字体大小,当我们将文本( 更多关于这个) 绘制到画布时将使用它们。 我在我们的例子中了解到,控制台窗口的字体通常是 Consolas,我选择了 12.

字体颜色

当然,我们也希望字体与 Windows 控制台的颜色相同,因这里我做了一些试验,以前看到的值:

var fontColor = "#C0C0C0";
很多工作

那是很多工作 ! 是的padawan拥有强大的能量。 这是 spider spider的一个不错的bad,它是来自蜘蛛人的引用和对Star的引用。 我是 UberGeek 不要 jealous。 : )

******* 工具条:移动问题 *****************

此时,我在Android平台上加载了这个示例,并了解到在这个小应用程序加载时存在一些问题。

1.字体非常小。

2.由于画布元素没有启动移动键盘,所以无法键入。

现在这两个问题都可以在你的桌面浏览器中使用,但现在我们已经在你的桌面浏览器中创建了

好了现在我们来看看代码。

接下来我们需要检查的是appCursor函数/对象。

appCursor函数

在初始代码中声明appCursor函数,在我们的外观如下所示:

function appCursor (cursor)
{
 this.x = cursor.x;
 this.y = cursor.y;
 this.width = cursor.width;
 this.height = cursor.height;
}

这很简单,但我们先把它分开。

我把这个函数命名为 appCursor,这样任何开发人员都能立即理解它的用途。 这个函数将为我们使用JavaScript创建一个对象,并使用一个强大的初始化约定。

创建新appCursor对象所需做的就是调用它并发送一个 cursor,它具有你希望它具有的值。

现在,好的是,你可以轻松地使用 JSON ( JavaScript对象表示法) 来创建对象,并发送一个初始化对象来表示应用程序 cursor ( 闪烁下划线)。

调用这里函数时,console.js 中的唯一时间和唯一时间如下所示:

cursor = new appCursor({x:promptWidth,y:lineHeight,width:cursorWidth,height:cursorHeight});

如果你从未见过JSON或者你只使用过它,你可能会觉得有点奇怪。

JSON只是一个或者多个 NAME 值对,用逗号分隔,其中 NAME 和值用冒号分隔。

下面是两个简单的JSON示例:

{name:value}
{color:green}

由于开放/关闭括号 { } 是JavaScript中的对象初始值设定项,因这里实际上创建具有 NAME 值的对象。

下面是另一个例子:

var myFont = {color:green};

现在可以在该对象上使用以下语法来获取它的颜色值:

console.log(myFont.color);

那么输出将是: 绿色

用于DOM事件的register

接下来我们在 initApp 函数中做的事情是设置一些DOM事件。

window.addEventListener("resize", draw);
window.addEventListener("keydown",keyDownHandler);
window.addEventListener("keypress",showKey);

addEventListener 是纯JavaScript方法,它在浏览器事件触发时将你的函数注册为回调。

第一个参数是定义的事件( resizekeydownkeypress ) 作为字符串。 第二个参数是应该调用的函数的NAME,但请注意它不是字符串。 它是函数引用 --,因为JavaScript中的函数是第一类对象。

按键和 Keydown

你可以看到,当调整了浏览器窗口时,我已经注册了一些特殊的工作,当发生rtc时。 是的,最后两个有点不同。

因为在 initApp 中发生了一些更多的事情,我们将在完成 initApp的代码之后,确切地介绍这些函数。

接下来发生的事情是 initViewArea ( ) 被调用:

function initViewArea() {
 // the -5 in the two following lines makes the canvas area, just slightly smaller// than the entire window. this helps so the scrollbars do not appear. ctx.canvas.width = window.innerWidth-5;
 ctx.canvas.height = window.innerHeight-5;
 ctx.fillStyle = "#000000";
 ctx.fillRect(0,0,ctx.canvas.width, ctx.canvas.height);
 ctx.font = outputFont;
 ctx.fillStyle = fontColor;
 var textOut = PROMPT;
 ctx.fillText (textOut,leftWindowMargin, cursor.y);
 draw();
}

首先,我们要初始化画布宽度和高度,使它占据整个窗口,除了一个小的5像素宽的边界。

然后我们设置 fillStyle 以便它是 black 并调用 fillRect,用 black 填充整个区域。

那是控制台窗口的background。

字体在画布中绘制

finally,我将字体设置为前面定义的那个 outputFont。 我查找了 Windows 控制台字体,我使用这个,使假控制台窗口看起来像真实的东西。

接下来,我必须绘制提示符的文本( 由c 表示): > )。请记住,画布元素需要绘制所有的内容。 我们使用名为 fillText的画布上下文函数来绘制文本。

draw() 函数:主循环

而 finally 我们称之为 draw() 函数。 如果用户调整窗口大小,这将是

每次改变窗户的时候都必须画出来。 这个 draw() 函数最终是一个主循环。

function draw()
{
 ctx.canvas.width = window.innerWidth-5;
 ctx.canvas.height = window.innerHeight-5;
 ctx.fillStyle = "#000000";
 ctx.fillRect(0,0,ctx.canvas.width, ctx.canvas.height);
 ctx.font = outputFont;
 ctx.fillStyle = fontColor;
 for (var i=0;i<allUserCmds.length;i++)
 {
 drawPrompt(i+1);
 if (i == 0)
 {
 xVal = promptWidth;
 }
 else {
 xVal = promptWidth-charWidth;
 }
 ctx.font = outputFont;
 ctx.fillStyle = fontColor;
 for (var letterCount = 0; letterCount <allUserCmds[i].length;letterCount++)
 {
 ctx.fillText(allUserCmds[i][letterCount], xVal, lineHeight * (i+1));
 xVal+=charWidth;
 } }
 if (currentCmd!= "")
 {
 drawPrompt(Math.ceil(cursor.y/lineHeight));
 ctx.font = outputFont;
 ctx.fillStyle = fontColor;
 xVal = promptWidth-charWidth;
 for (var letterCount = 0; letterCount <currentCmd.length;letterCount++)
 {
 ctx.fillText(currentCmd[letterCount], xVal, cursor.y);
 xVal += charWidth;
 }
 }
 else {
 drawPrompt(Math.ceil(cursor.y/lineHeight));
 }
}

在 draw() 函数中要关注的两

这里有趣的代码是我需要做的工作来计算每个字母--的宽度,以便可以将 cursor 移到右边。 如果用户backspaces我需要能够在( blot ) 上绘制这个字符,并将 cursor 移回到正确的位置。 对于创建控制台窗口的真正的开发人员来说,这是很大的工作。 : )

键入命令的列表

另外,请注意,我保留了 array 中类型化命令的列表,然后在任何时候重新调整windonw的大小或者更改。 工作很多,但工作相当好。 粗体的代码循环显示我循环遍历列表以在屏幕上绘制它们。

闪烁 cursor,就像真正的控制台

这是让这个感觉非常真实的部分,我想。 在initApp中,我使用JavaScript方法setInterval在指定的时间间隔内设置了一个运行函数。

设置看起来像:

setInterval(flashCursor,300);

这个设置了一个回调方法 --,这种情况下我的函数叫做 flashCursor --,它将运行每 300ms 个( 0.3秒)。

flashCursor是一个非常简单的方法,它看起来像:

function flashCursor(){
 var flag = flashCounter % 3;
 switch (flag)
 {
 case1 :
 case2 :
 {
 ctx.fillStyle = fontColor;
 ctx.fillRect(cursor.x,cursor.y,cursor.width, cursor.height);
 flashCounter++;
 break;
 }
 default:
 {
 ctx.fillStyle = "#000000";
 ctx.fillRect(cursor.x,cursor.y,cursor.width, cursor.height);
 flashCounter= 1;
 }
 }
}

为了在 1和 3之间生成一个值,我做了模除法,我只是在这个标志上做了 switch。 这允许我改变 cursor的颜色,所以它有时是 black 并且不出现,然后其他时候它是正常字体颜色。 这一切都产生了 cursor 闪烁和关闭的错觉。

finally,我们将看一下我编写的showKeykeydownHandler 方法,你将有一些需要知道的代码。

function showKey(e){
 blotOutCursor();
 ctx.font = outputFont;
 ctx.fillStyle = fontColor;
 ctx.fillText (String.fromCharCode(e.charCode),cursor.x, cursor.y);
 cursor.x += charWidth;
 currentCmd += String.fromCharCode(e.charCode);
}

当用户按下键时,会发生 showKey。 我得到 charCode 并使用 fillText 绘制它,以便它显示在屏幕上。 但是现在我必须管理 cursor 在屏幕上的位置,因为它现在将更进一步。

为什么使用 KeyDown?

KeyDown允许我捕获不可打印的字符,如退格键。输入键等等。

对于每一个我都必须做一些计算,然后在新的正确位置绘制文本和 cursor。

function keyDownHandler(e){
 var currentKey = null;
 if (e.code!== undefined)
 {
 currentKey = e.code;
 console.log("e.code :" + e.code);
 }
 else
 {
 currentKey = e.keyCode;
 console.log("e.keyCode :" + e.keyCode);
 }
 console.log(currentKey);
 // handle backspace key if((currentKey === 8 || currentKey === 'Backspace') && document.activeElement!== 'text') {
 e.preventDefault();
 // promptWidth is the beginning of the line with the c:> if (cursor.x> promptWidth)
 {
 blotPrevChar();
 if (currentCmd.length> 0)
 {
 currentCmd = currentCmd.slice(0,-1);
 }
 }
 }
 // handle <ENTER> key if (currentKey == 13 || currentKey == 'Enter')
 {
 blotOutCursor();
 drawNewLine();
 cursor.x=promptWidth-charWidth;
 cursor.y+=lineHeight;
 if (currentCmd.length> 0)
 {
 allUserCmds.push(currentCmd);
 currentCmd = "";
 }
 }
}

这么简单的工作for惊人的工作量

对于如此简单的事情来说,它是不是一个惊人的工作量?

限制:没有滚动

我没有实现滚动,因这里如果键入了这么多命令,它们会从屏幕上出现,我没有处理。 我把这个留给你。

你的for

我为娱乐和学习创造了这个愚蠢的应用。 它可以很容易地扩展到。 接下来,当用户键入特定命令时,你可以做一些有趣的输出。 它可能是一个真正的声音,它会欺骗很多人。

使用代码

  • 获取下载
  • 解开它
  • 将它放到文件夹中
  • 双击 console.htm 文件,它将在默认浏览器中加载。

注意 : 显然,你的浏览器必须支持HTML5和 Canvas。

Have。

历史记录

更新了 aricle ( 最后的代码列表和修复退格键和输入kesy的问题的代码: 04-28-2016

文章最初发布:01 -27-2015


COM  JAVA  Javascript  COMM  bro  Comma  
相关文章