【HTML5游戏开发小技艺】RPG情景对话中,令文本逐字输出
以前用javascript实现过令文本逐字输出的效果,今天我来用html5中的canvas实现一下。canvas里的内容可不像<p>那样好操作,首先,你需要懂得一些html5的API才能操作canvas,而<p>可以用DOM直接操作,相对而言,canvas还是要比<p>复杂些。那么本篇就为大家讲述入股令文本逐字输出。
首先我先说明,本篇我不打算用任何引擎,因为今天我们是来研究技巧和原理的。
一,原理
做一个富有技巧的程序我们首先得搞清楚原理,而令文本逐字输出的原理很简单。
假如我们有一串字符,我们可以把它们分成一个个字符,然后装入数组。例入有一个字符串yorhom,那么我们可以把他分成
var arr = ['y','o','r','h','o','m'];的形式,这样要输出文字的话就可以编历这个数组,然后每隔一段时间就把当前遍历的那个字符输出。这样一来就可以将文字逐渐输出。
光说还不行,我们还得去实现,否则就是纸上谈兵。
二,实现
首先我们看看代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>html5输出文字类</title> <script type="text/javascript"> function type(){ //画布的id var canvasId = "mycanvas"; //用于输出文字的变量 var sub = 0; var arr = []; var time = 0; //设定文字颜色,字体,大小,x和y坐标 var x = 0; var y = 50; var color = "red"; var size = "20"; var font = "宋体"; //设制文字内容 var tosplitFont = "I'm yorhom,这是个令文本逐字显示的小程序"; sub = 0; arr = tosplitFont.split(''); var c = document.getElementById(canvasId); var ctx = c.getContext("2d"); ctx.font = size+"px"+" "+font; ctx.fillStyle = color; ctx.clearRect(0,0,c.width,c.height); //循环输出 for(var i=0;i<arr.length;i++){ setTimeout(function(){ ctx.fillText(arr[sub],x,y); x += ctx.measureText(arr[sub]).width; sub += 1; },time); time += 100; } } </script> </head> <body onload="type()"> <canvas width="500",height="300" id="mycanvas"></canvas> </body> </html>这就是包括html和javascript的所有代码,只有46行,看来不怎么难。接下来我将讲解 一下这些纤纤渣渣的代码。
html里的代码不解释,我们直接跳到javascript部分。看看type函数:
function type(){ //画布的id var canvasId = "mycanvas"; //用于输出文字的变量 var sub = 0; var arr = []; var time = 0; //设定文字颜色,字体,大小,x和y坐标 var x = 0; var y = 50; var color = "red"; var size = "20"; var font = "宋体"; //设制文字内容 var tosplitFont = "I'm yorhom,这是个令文本逐字显示的小程序"; sub = 0; arr = tosplitFont.split(''); var c = document.getElementById(canvasId); var ctx = c.getContext("2d"); ctx.font = size+"px"+" "+font; ctx.fillStyle = color; ctx.clearRect(0,0,c.width,c.height); //循环输出 for(var i=0;i<arr.length;i++){ setTimeout(function(){ ctx.fillText(arr[sub],x,y); x += ctx.measureText(arr[sub]).width; sub += 1; },time); time += 100; } }
在这里,我解释一下变量sub,time和arr。首先sub是遍历数组的下标,也许你会说可以用控制循环的变量作为下标,其实我也试过,如果用控制循环的变量的来作下标,会出现错误。因为在javascript中的循环会先循环完,然后再慢慢执行里的内容。所以如果你用控制循环的变量的来作下标,那么输出的就一直是最后一个。因此我设定了sub变量,让它在循环内部增加,这样即使循环里最后慢慢执行,那也无妨。
arr是装满被分开的文字的数组,通过split方法赋值。如下:
arr = tosplitFont.split('');split用法是没遇见参数字符,就将这个字符前面的那一个加到数组中。我表述可能不大清楚,还是让专业人士w3cschool为你解答吧:http://www.w3school.com.cn/js/jsref_split.asp
time是个控制等待时间的变量,因为setTimeout是在某一个时刻做某事,所以我们需要不断改这个时刻。
接下来我们看输出部分:
//循环输出 for(var i=0;i<arr.length;i++){ setTimeout(function(){ ctx.fillText(arr[sub],x,y); x += ctx.measureText(arr[sub]).width; sub += 1; },time); time += 100; }
首先我们先遍历了上述的arr,接下来我们在里面通过setTimeout在某个时刻输出文字。
fillText是什么?我想我只能告诉你是html5中输出文字的东东,看看专业人士的又一讲解:http://www.w3school.com.cn/html5/canvas_filltext.asp
由于html5中如果不是一次性输出文字,文字坐标且不改变,那么文字将叠在一起。所以我们只有改变坐标,由于我们用变量x和y控制文字位置,所以我们只用改变x就能将文字移到它该去的位置。我首先想到了可以将x设定为当前字符传的长度。
但怎么才能算出这个字符传的长度呢?我无意间看到了measureText方法,它可以取出当前字符串的长度,所以我们就利用这个玩意儿算出上个字符长度,然后用x加上这个长度,就可以算出下一个文字该去的位置。measureText怎么用呢,看看这里吧:http://www.w3school.com.cn/html5/canvas_measuretext.asp
就这样,逐字输出就搞定了。
看看效果吧:
http://www.cnblogs.com/yorhom/archive/2013/04/04/3000017.html
三,源码下载
源码在这里:http://files.cnblogs.com/ducle/html5-%E8%BE%93%E5%87%BA%E6%96%87%E5%AD%97.rar
贴几张demo图,不想看代码只想看效果的朋友可以看看:
今天是清明节,但由于这个节日太xx了,所以我就不祝大家清明节快乐了。
----------------------------
欢迎大家转载我的文章。
转载请注明:转自Yorhom's Game Box
欢迎继续关注我的博客
- 6楼ssrc0604hx昨天 09:33
- /**nt一个逐字输出的文字对象nnt@param context 2D画布nt@param text 需要现实的文字nt@param time n*/nfunction AnimateText(context, text, time){ntvar ME = this;nntthis.context = context;ntthis.text = text;ntthis.time = time;nntthis.index = 0;nntthis.timer = setInterval(nttfunction(){ntttME.update();ntttME.print();ntt},nttthis.timent);nntthis.update = function(){nttthis.index ++;nttif(this.index > this.text.length){ntttthis.stop();ntt}nt}nntthis.print = function(){nttthis.context.save();nnttthis.context.font = "15px 宋体";nttthis.context.fillStyle = "#0000fa";nttthis.context.fillText(ntttthis.text.substring(0, this.index), 0, 40ntt);nnttthis.context.restore();nt}nntthis.stop = function(){nttif(this.timer){ntttclearInterval(this.timer);ntt}nt}n}
- Re: yorhomwang昨天 11:27
- 回复ssrc0604hxn你切割文字用的是substring的方法吗?其实最好用split,因为substring在某些浏览器上不兼容。不过现在只要支持html5的浏览器都应该能支持substring吧。
- Re: ssrc0604hx昨天 16:45
- 回复yorhomwangn这种情况暂时没有碰到。因为考虑到是现实text的一个子串,就用了substring这个方法,嘻嘻
- 5楼h270768095昨天 08:46
- 学习了
- 4楼u010172962昨天 23:51
- 学习了
- 3楼html5_lover昨天 23:49
- 真的很不错,以前一直不知道怎么实现,看了总算明白了
- 2楼ylbxsdn昨天 23:39
- 看来html5将淘汰asp php之流
- Re: yorhomwang昨天 23:39
- 回复ylbxsdnn现在HTML5效率还不是很高,至于取代asp和php要看HTML5以后发展如何了。
- 1楼ssrc0604hx昨天 23:35
- LZ 谈得不错。你的方法比较适合canvas不刷新的情况。n我模仿LZ写了一个,可以在canvas刷新的时候一样使用:nvar canvas = null;//画布元素nvar context = null;//nnwindow.onload = function(){ntif(buildCanvas("mycanvas")){nttvar str = "Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言";nttnew AnimateText(context, str, 80);nt}n}nn/**n初始化canvas对象n成功则返回truen*/nfunction buildCanvas(id){ntcanvas = document.getElementById(id);ntif(canvas){nttcontext = canvas.getContext("2d");nnttreturn context != null;nt}ntelse{nttalert("canvas 对象不能为空!");nttreturn false;nt}ttn}