jqueryとt.jsでタイピング風の文字アニメーションを実装する方法

#やりたいこと
まずは[デモ](https://rawgit.com/mntn-dev/t.js/master/demo.htm)を見てみてください。
このようにまるでタイピングをしているかのように文字を表示させることができます。
#実装方法
まずはjqueryとt.min.jsを読み込ませます。/bodyタグの直前に以下のコードをコピペしてください。

```html
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script type="text/javascript" src="t.min.js">
````

t.min.jsは[GitHub](https://github.com/mntn-dev/t.js)からダウンロードできます。
面倒な方には下記に書いておくのでファイルを作成してコピペしても構いません。

```js
/*t.js-1.0;(c)2014-2018 - Mntn(r) <https://mn.tn/> c/o Benjamin Lips <g--[AT]--mn.tn>;MIT-Licensed <https://mit-license.org/>;For documentation see <https://mntn-dev.github.io/t.js/>*/
;(function(d){d.fn.t=function(n,A){return this.each(function(){var a=A,k=n,b=d(this),r,t,m=!1,x=-1,u="12qwertyuiop[]asdfghjkl;zxcvbnm,./~!@#$%^&*()_+:1234567890-=op".split([]),e=function(a,b){return d.type(a)[0]==(b||"n")},y=function(){g=d.grep(h,function(a){return"&"==a[0]||!a[1]}).length-1;return-1<g?g:0},w=function(b){x!=b&&a.blink&&(a.blink_perm||l.parent().data("blinking",x=b?1:0))},f={c:0,beep:function(){0==f.c&&(f.c=d("html").data().__TAC);f.o&&f.o.stop();f.o=f.c.createOscillator();f.o.frequency.setValueAtTime(1,f.c.currentTime);f.g=f.c.createGain();f.o.connect(f.g);f.g.connect(f.c.destination);f.o.start();f.o.stop(f.c.currentTime+.03)}};if("beep"==k&&!b.data().is_typing&&d("html").data().__TAC)return f.beep(),this;""===k&&(k="<del>*</del>");if(b.data().is_typing)return k=="paused".slice(0,-1)&&(b.data("paused",e(a,"b")?oo_=a:b.data("paused")?oo_=!1:oo_=!0),b.data("blinking",oo_?1:0)),this;if(k=="paused".slice(0,-1))return this;b.data("is_typing",1);e(k,"o")&&(a=k);if(/t\-/.test(b.attr("class")))return this;if("add"==k&&b.data().t){var q=a;a=d.extend({},b.data());var l=b=d(":first",b),z=e(a.typing,"f");q="<"+a.tag+' class="typing-add">'+q+"</"+a.tag+">"}else{"add"==k&&(k=a,a={});a=d.extend({t:!0,delay:!1,speed:75,speed_vary:!1,caret:"\u258e",tag:"span",blink:!0,beep:!1,blink_perm:!1,repeat:-3,pause_on_click:!1,wrap:!1,mistype:!1,locale:"en",init:!1,typing:!1,fin:!1},a?a:b.data());q=t=!1;var c;b.data().t||(b.wrapInner(d("<"+a.tag+"/>",{"class":"t-container",style:"top:auto;bottom:auto;"})),/^[ar]/.test(b.css("position"))||b.css({position:"relative"}),b.css({overflow:"hidden"}));a.wrap&&!b.parent().data().t_wrap&&(b.wrap(d("<div/>",/[.#]/.test(a.wrap[0])?"#"==a.wrap[0]?{id:a.wrap.substr(1)}:{"class":a.wrap.substr(1)}:{style:a.wrap})),b.parent().data("t_wrap",1));e(a.beep,"b")||(a.beep=!1);!0===a.beep&&e(d("html").data().__TAC,"u")&&(d("html").data("__TAC",__TAC=window.AudioContext||window.webkitAudioContext?new AudioContext:!1),__TAC||(a.beep=!1));!1===a.repeat&&(a.repeat=-3);!0===a.caret&&(a.caret="\u258e");e(a.caret,"s")&&!d(".t-caret",b)[0]&&(!0===a.blink&&(a.blink=3*a.speed),e(a.blink)&&100>a.blink&&(a.blink=100),!e(a.blink)&&(a.blink=!1),t=d("<"+a.tag+"/>",{"class":"t-caret",html:a.caret}).appendTo(b),a.blink&&b.append("\u200b")&&b.data("bi",setInterval(function(){(l.parent().data().blinking|(v="h"==t.css("visibility")[0])||a.blink_perm)&&t.css({visibility:v?"visible":"hidden"})},e(a.blink)?a.blink:a.speed*(a.speed_vary?4:5))));a.blink||b.data().bi&&clearInterval(b.data().bi)&&b.removeData("bi");!e(a.blink_perm,"b")&&(a.blink_perm=!0);a.speed=!e(a.speed)||10>a.speed?10:a.speed;a.speed_vary&&(a.speed/=2.5);1<a.mistype||(a.mistype=!1);b.data(a);d(".typing-0",b).replaceWith(function(){return this.childNodes});d(".typing-add",b).remove();l=b=d(":first",b);var h=e(k,"s")?k:b.html();""==h&&(h="\u200b");b.empty();l.parent().show().css({visibility:"visible"});e(a.delay)&&0<a.delay&&(c=~~(1E3*a.delay/a.speed))&&a.blink_perm||b.parent().data("blinking",1);z=e(a.typing,"f");!0===a.pause_on_click&&b.parent().off("click").click(function(a){"1"!=d(a.target).data().click&&d(this).t("pause")})}/<kbd.*?>/i.test(h=String(q||h))&&b.parent().data("kbd",j_=1)&&b.parent().data("mistype",b.parent().data("mistype")?_j=b.parent().data().mistype:_j=10)&&(a.mistype=_j)&&(a.kbd=j_?j_:!1);h=h.replace(/(.*?)[\u200b]+$/,"$1").replace(/<!\-\-([\s\S]+?)\-\->/g,"$1").replace(/<ins>([^0-9])<\/ins>/g,"$1").replace(/<(embed|command|col|wbr|img|br|input|hr|area|source|track|keygen|param)(.*?)[\/]?>/g,"<#$1$2/>").replace(/<ins>\s*(\d*[.]?\d*)\s*(<\/ins>)/g,'<ins data-ins="$1"></ins>').replace(/<ins(.*?)>([\s\S]*?)(<\/ins>)/g,function(a,b,c){return"<#ins"+b+">"+c.replace(/<(?!#)/g,"<#")+"<#/ins>"+(c?"":"</ins>")}).replace(/<(del.*?data-del=")(.*?)(".*?)><\/(del>)/g,"<#$1$2$3><#/$4$2</$4").replace(/<del(.*?)>([\s\S]*?)<\/del>/g,function(a,b,c,d){s=(s=c.match(/
\s*(.*?)\s*<\/s>/i))&&s[0]?' data-s="'+(s[1]||"1")+'"':"";i=(i=c.match(/data-ins="(.*?)"/))&&i[1]?i[1]:""==s?.25:.75;c=c.replace(/(
.*?<\/s>|<[\/]?.*?>)/g,"");return"<del"+b+s+' data-del="'+c.replace(/\n/,"\\n")+'" data-ins="'+i+'">'+("*"!=c?c:"")+"</del>"}).replace(/<(\w+)(.*?)>/g,"<$1$2><#/$1>").replace(/<\/(\w+)>/g,"</> ($1)").replace(/<[#]+/g,"<").replace(/(\/del>)\*</g,"$1<").match(/<ins.*?>[\s\S]*?<\/ins>|<[^<]+\/>|<\/> \(\w+\)|<[\s\S]+?><\/\w+>|&[#x]?[a-z0-9]+;|\r|\n|\t|\S|\s/ig);!e(c)&&(c=h.shift());h.push("\u200b");"de"==a.locale&&(u='12qwertzuiop\u00fc+asdfghjkl\u00f6\u00e4#<yxcvbnm,.-!"\u00a7$%&/(()=?1234567890\u00df*p+');var B=y()+1;!q&&e(a.init,"f")&&a.init(l.parent());var C=setInterval(function(){if(!l.parent().data("paused")&&!m){m=!m;if(e(c)){if(0<--c){m=!m;w(.25>=b.data().ins?0:1);return}c=b.data().ins?"</>":h.shift()}else if(a.speed_vary&&~~(4*Math.random())){m=!m;return}w(0);if(b.data().del&&(!0===l.parent().data().beep&&f.beep(),b.data().s&&!c[0]&&b.text(""),r=String(b.data().del),!e(c,"a")&&"/"==c[1]&&(c=r.replace(/\\n/g,"\n").split([])),e(c,"a"))){if(p=c.pop()){b.data().s?b.html(c.join([])+"<mark "+("."==(_=String(b.data().s))[0]?'class="'+_.substr(1)+'"':'style="background:'+("1"==_?"yellow":_.split(",")[0])+((_=_.split(",")[1])?";color:"+_:"")+';"')+">"+b.data().del.substr(c.length)+"</mark>"):b.text(c.join([]));m=!m;return}"*"==r&&(l.wrapInner(d("<"+a.tag+"/>",{"class":"typing-0",style:"display:none;"})),b=b.parent(),q&&(h=d.merge(["<"+a.tag+' class="typing-add"></'+a.tag+">"],h,["</"+a.tag+">"]),b=b.parent()));b=b.parent();"\u200b"==r&&b.find(":last").remove();c=""}for(;"/"==c[1];)b=b.parent(),c=h.shift()||"";for(;;)if(!0===l.parent().data().beep&&f.beep(),b.append(c),z&&a.typing(l.parent(),c,y(),B),!/<ins.*?>[\s\S]+</.test(c)&&/></.test(c)&&(b=b.find(":last")),h[0]&&/<\w+/.test(h[0]))c=h.shift();else break;(c=h.shift())?((a.mistype&&!a.kbd||a.kbd&&/kbd/i.test(b.prop("tagName")))&&c&&!c[1]&&"\u200b"!=b.data().del&&" "!=c&&!~~(Math.random()*a.mistype)&&-1<(__=d.inArray(c.toLowerCase(),u,2))&&(__+=~~(2*Math.random())+1,~~(2*Math.random())&&(__-=3),h=d.merge([90>c.charCodeAt(0)?u[__].toUpperCase():u[__],"</del>",c],h),c='<del data-ins=".25" data-del="\u200b"></del>'),c&&"/"==c[1]&&b.data().ins&&(c=~~(1E3*Number(b.data().ins)/a.speed)),m=!m):(clearInterval(C),l.parent().removeData(["is_typing","paused"]),e(a.repeat)&&--a.repeat,-1<a.repeat?(a.init=!1,l.parent().t(e(k,"o")?a:k,a)):(w(1),e(a.fin,"f")&&a.fin(l.parent())))}},a.speed)})};d.fn.a=function(n){return this.each(function(){d(this).data().t&&d(this).t("add",n)})};d.fn.p=function(n){return this.each(function(){d(this).data().is_typing&&d(this).t("pause",n?!1===n||!0===n?n:void 0:void 0)})};d.fn.b=function(n){return this.each(function(){d(this).t("beep")})}})(jQuery);
```

次に文字を表示させたいところに以下のコードを書きます。

```html
<div class="test">
テストテストテストテストテスト
</div>
```

最後に以下を記述してください

```html
<script>
$(function(){
  $(".test").t()
});
</script>
```

これで動くはずです。

#最後に

ユニークな機能として一度書いてからとり消すものもあります。消したい文字をdelタグで囲んでください。

```html
テスト<del>一度表示させてから消したい文字</del>テストテスト
```

他にも文字の表示速度だったりをいじることもできるみたいですが、うまくいかなかったのでまたできたら追記したいと思います。