文字ジェネレーターをVue.jsでも実装!jQueryとの違いを比較してみる

Pocket

以前jQueryで使用して文字ジェネレーターのサンプルを作りましたが、今回「Vue.js」で実装してみました。

サンプルではほとんどコードを書いていないので意味があるかわかりませんがjQueryとの書き方の違いを比べていきます。

 

以前作ったサンプルの記事は以下となります。

サンプル

動作はほとんど変わりませんが。。。

ソース内容

jQuery

<!DOCTYPE html> <!-- HTML5のDOCTYPE宣言 -->
<html lang="ja"> <!-- lang属性 日本語であることを宣言 -->
<head>
	<meta charset="UTF-8"> <!-- 文字コードをUTF-8にする -->
	<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- ビューポートを指定 -->

	<!-- タイトル設定 -->
	<title>文字ジェネレーター</title>
    <!-- bootstrap4 CDN CSS -->
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">	
</head>
<body>
	<!-- ------------------------------------------------------------------------- -->
	<!-- ヘッダー -->
	<!-- ------------------------------------------------------------------------- -->
	<nav class="navbar navbar-expand-lg fixed-top navbar-light bg-dark">
		<div class="collapse navbar-collapse justify-content-center">
			<ul class="navbar-nav">
			  <li class="nav-item active">
				<a class="nav-link text-white" href="#"><h1 class="h5 font-weight-bold">文字ジェネレーター</h1></a>
			  </li>
			</ul>
		</div>
	</nav>
	<!-- ------------------------------------------------------------------------- -->
	<!-- コンテンツ -->
	<!-- ------------------------------------------------------------------------- -->
	<div class="container mt-5">
		<div class="row">
			<div class="col-12">
				<!-- ------------------------------------------------------------------------- -->
				<!-- SVG要素 -->
				<!-- SVGフォントに源ノ角ゴシック(https://github.com/adobe-fonts/source-han-sans)を使用しています -->
				<!-- Licensed under SIL Open Font License 1.1 (http://scripts.sil.org/OFL) -->
				<!-- ------------------------------------------------------------------------- -->
				<div class="form-group text-center mt-5">
					<?xml version="1.0" encoding="utf-8"?>
					<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
					<svg version="1.1" id="svg-generator" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
							y="0px" viewBox="0 0 506 253" style="enable-background:new 0 0 506 253;width:100%;" xml:space="preserve" width="506" height="253" >
						<style type="text/css">
							@font-face {font-family:SourceHanSansJP-Heavy-83pv-RKSJ-H;src:url("data:application/x-font-woff;base64,d09GRk9UVE8ACKNwAAk...") format("woff")}
							.st0{fill:#FFFFFF;}
							.st1{font-family:'SourceHanSansJP-Heavy-83pv-RKSJ-H';}
							.st2{font-size:90px;}
							.st3{fill:#FF0000;}
						</style>
						<rect width="506" height="253"/>
						<text transform="matrix(1 0 0 1 28 163.7373)"><tspan x="0" y="0" class="st0 st1 st2" id="text-1">文字の</tspan><tspan x="270" y="0" class="st3 st1 st2" id="text-2">生成</tspan></text>
					</svg>

				</div>
				<!-- ------------------------------------------------------------------------- -->
				<!-- テキスト入力・画像取得ボタン -->
				<!-- ------------------------------------------------------------------------- -->
				<div class="form-group mt-5 row">
					<div class="col-sm-6">
						<input type="text" class="form-control svg-text" data-target="#text-1" value="文字の" placeholder="文字を入力してください">
					</div>
					<div class="col-sm-6">
						<input type="text" class="form-control svg-text" data-target="#text-2" value="生成" placeholder="文字を入力してください">
					</div>
				</div>

				<div class="form-group mt-5 text-center">
					<button class="btn btn-info" id="create-image">画像を取得</button>
				</div>

			</div>
		</div>
	</div>
	<!-- ------------------------------------------------------------------------- -->
	<!-- フッター -->
	<!-- ------------------------------------------------------------------------- -->
    <footer class="fixed-bottom text-center">
			©<a href="/">文字ジェネレーター</a>
	</footer>

	<!-- ------------------------------------------------------------------------- -->
	<!-- モーダルダイアログ -->
	<!-- ------------------------------------------------------------------------- -->
	<div class="modal fade" id="svg-box">
		<div class="modal-dialog" role="document">
			<div class="modal-content">
				<div class="modal-header">
					<h5 class="modal-title">右クリック・長押しで保存</h5>
					<button type="button" class="close" data-dismiss="modal" aria-label="Close">
					<span aria-hidden="true">×</span>
					</button>
				</div>
				<div class="modal-body">
					<img src="" id="svg-image" style="width:100%;">
				</div>
			</div>
		</div>
	</div>


	<!-- ------------------------------------------------------------------------- -->
	<!-- JavaScript -->
	<!-- ------------------------------------------------------------------------- -->

	<!-- jQueryの読み込みを宣言 -->
	<script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
	<!-- bootstrap4のJavascript読み込みを宣言 -->
	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

	<script>
		//テキスト入力時のイベント 入力文字をSVGのTEXT要素に反映
		$('.svg-text').on('input',function(e) {
			let targetTspan=$(this).data('target');
			$(targetTspan).text($(this).val());
		});

		//画像取得ボタンクリック時のイベント SVG要素を画像に変換し表示する
		$('#create-image').on('click',function(e) {
			//SVG要素をbase64エンコードしDataURI形式に変換
			let svgElem = document.getElementById('svg-generator');
			let svgStr = new XMLSerializer().serializeToString(svgElem);
			let svgBase64 = "data:image/svg+xml;base64,"
				+ btoa(unescape(encodeURIComponent(svgStr)));

			// HTMLCanvasElement オブジェクトを作成する
			let canvas = document.createElement("canvas");
			// CanvasRenderingContext2D オブジェクトを取得する
			let ctx = canvas.getContext("2d");

			// 新たな img 要素を作成
			let image = new Image();
			image.onload = function(){
				//Retina対応しているブラウザだと画像がぼやけるため2倍にする
				canvas.width = image.width*2;
				canvas.height = image.height*2;

				//SVG画像をCanvasに描画
				ctx.drawImage( image,0,0,image.width,image.height,0,0,canvas.width,canvas.height);

				//Canvasに描画されている画像をDataURI形式でsrc属性に設定
				$('#svg-image').attr('src',canvas.toDataURL("image/png"));

				//bootstrap4のモーダルを表示
				$('#svg-box').modal();
			}
			// Base64エンコードしたSVG画像を設定
			image.src = svgBase64;
		});

	</script>
</body>
</html>

 

Vue.jsのコード

<!DOCTYPE html> <!-- HTML5のDOCTYPE宣言 -->
<html lang="ja"> <!-- lang属性 日本語であることを宣言 -->
<head>
	<meta charset="UTF-8"> <!-- 文字コードをUTF-8にする -->
	<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- ビューポートを指定 -->

	<!-- タイトル設定 -->
	<title>文字ジェネレーター</title>
    <!-- bootstrap4 CDN CSS -->
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">	
</head>
<body>
	<div id="app">
		<!-- ------------------------------------------------------------------------- -->
		<!-- ヘッダー -->
		<!-- ------------------------------------------------------------------------- -->
		<nav class="navbar navbar-expand-lg fixed-top navbar-light bg-dark">
			<div class="collapse navbar-collapse justify-content-center">
				<ul class="navbar-nav">
				<li class="nav-item active">
					<a class="nav-link text-white" href="#"><h1 class="h5 font-weight-bold">文字ジェネレーター</h1></a>
				</li>
				</ul>
			</div>
		</nav>
		<!-- ------------------------------------------------------------------------- -->
		<!-- コンテンツ -->
		<!-- ------------------------------------------------------------------------- -->
		<div class="container mt-5">
			<div class="row">
				<div class="col-12">
					<!-- ------------------------------------------------------------------------- -->
					<!-- SVG要素 -->
					<!-- SVGフォントに源ノ角ゴシック(https://github.com/adobe-fonts/source-han-sans)を使用しています -->
					<!-- Licensed under SIL Open Font License 1.1 (http://scripts.sil.org/OFL) -->
					<!-- ------------------------------------------------------------------------- -->
					<div class="form-group text-center mt-5">
						<?xml version="1.0" encoding="utf-8"?>
						<!-- Generator: Adobe Illustrator 23.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
						<svg version="1.1" ref="svgGenerator" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
								y="0px" viewBox="0 0 506 253" style="enable-background:new 0 0 506 253;width:100%;" xml:space="preserve" width="506" height="253" >
							<svg:style type="text/css">
								@font-face {font-family:SourceHanSansJP-Heavy-83pv-RKSJ-H;src:url("data:application/x-font-woff;base64,d09GRk9UVE8ACKNwA...") format("woff")}
								.st0{fill:#FFFFFF;}
								.st1{font-family:'SourceHanSansJP-Heavy-83pv-RKSJ-H';}
								.st2{font-size:90px;}
								.st3{fill:#FF0000;}
							</svg:style>
							<rect width="506" height="253"/>
							<text transform="matrix(1 0 0 1 28 163.7373)"><tspan x="0" y="0" class="st0 st1 st2">{{text1}}</tspan><tspan x="270" y="0" class="st3 st1 st2">{{text2}}</tspan></text>
						</svg>

					</div>
					<!-- ------------------------------------------------------------------------- -->
					<!-- テキスト入力・画像取得ボタン -->
					<!-- ------------------------------------------------------------------------- -->
					<div class="form-group mt-5 row">
						<div class="col-sm-6">
							<input type="text" v-model="text1" class="form-control" placeholder="文字を入力してください">
						</div>
						<div class="col-sm-6">
							<input type="text" v-model="text2" class="form-control" placeholder="文字を入力してください">
						</div>
					</div>

					<div class="form-group mt-5 text-center">
						<button class="btn btn-info" @click="createImage">画像を取得</button>
					</div>

				</div>
			</div>
		</div>
		<!-- ------------------------------------------------------------------------- -->
		<!-- フッター -->
		<!-- ------------------------------------------------------------------------- -->
		<footer class="fixed-bottom text-center">
				©<a href="/">文字ジェネレーター</a>
		</footer>

		<!-- ------------------------------------------------------------------------- -->
		<!-- モーダルダイアログ -->
		<!-- ------------------------------------------------------------------------- -->
		<b-modal ref="svgBox" title="右クリック・長押しで保存" hide-footer>
			<img :src="svgImage" style="width:100%;">
		</b-modal>		

	</div>
	<!-- ------------------------------------------------------------------------- -->
	<!-- JavaScript -->
	<!-- ------------------------------------------------------------------------- -->

    <!-- 古いブラウザでは非対応のJavascriptの機能を補完 -->
    <script src="https://polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver"></script>
	<!-- vue.jsの読み込みを宣言 -->
    <script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
	<!-- bootstrap vue.jsの読み込みを宣言 -->
    <script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>

	<script>
        var app = new Vue({
            el: '#app',
            data: {
                text1: '文字の',
                text2: '生成',
				svgImage:''
			},
			methods: {
				createImage: function (event) {
					//SVG要素をbase64エンコードしDataURI形式に変換
					let svgElem = this.$refs.svgGenerator;
					let svgStr = new XMLSerializer().serializeToString(svgElem);
					let svgBase64 = "data:image/svg+xml;base64,"
						+ btoa(unescape(encodeURIComponent(svgStr)));

					// HTMLCanvasElement オブジェクトを作成する
					let canvas = document.createElement("canvas");
					// CanvasRenderingContext2D オブジェクトを取得する
					let ctx = canvas.getContext("2d");

					//vueのインスタンスを設定
					let vueIns=this;
					// 新たな img 要素を作成
					let image = new Image();
					image.onload = function(){
						//Retina対応しているブラウザだと画像がぼやけるため2倍にする
						canvas.width = image.width*2;
						canvas.height = image.height*2;

						//SVG画像をCanvasに描画
						ctx.drawImage( image,0,0,image.width,image.height,0,0,canvas.width,canvas.height);

						//Canvasに描画されている画像をDataURI形式でsrc属性に設定
						vueIns.svgImage=canvas.toDataURL("image/png");
						//bootstrapのモーダルを表示
						vueIns.$refs['svgBox'].show();

					}
					// Base64エンコードしたSVG画像を設定
					image.src = svgBase64;

				}
			}
		});

	</script>
</body>
</html>

jQueryとVue.jsの書き方の違い

JavaScriptの読み込み

jQueryの場合

<!-- jQueryの読み込みを宣言 -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
<!-- bootstrap4のJavascript読み込みを宣言 -->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

Vue.jsの場合

<!-- 古いブラウザでは非対応のJavascriptの機能を補完 -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver"></script>
<!-- vue.jsの読み込みを宣言 -->
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<!-- bootstrap vue.jsの読み込みを宣言 -->
<script src="https://unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>

「Vue.js」はscriptタグで読み込む以外にパッケージ管理ツールの「npm」を利用してインストールする方法もあります。

こちらは大規模アプリケーションを構築する場合に推奨されるインストールですが、今回はjQueryとの違いに絞って解説していくので詳しい説明は省きます。

「app」idの指定

jQueryの場合

なし

Vue.jsの場合

HTML
<div id="app">
  <!-- svg、input要素 -->
</div>
Javascript
var app = new Vue({ 
 el: '#app'
...

JavaScriptのelプロパティでidを指定します。これにより<div id="app"></div>内にある要素がVueの監視下に置かれ、jQueryのように直接DOM要素を操作することがほとんどなくなります。

 

SVG内のstyleタグ

jQueryの場合

<style type="text/css"></style>

Vue.jsの場合

<svg:style type="text/css"></svg:style>

 

テキスト周りの処理

jQueryの場合

SVG
<text transform="matrix(1 0 0 1 28 163.7373)">
    <tspan x="0" y="0" class="st0 st1 st2" id="text-1">文字の</tspan>
    <tspan x="270" y="0" class="st3 st1 st2" id="text-2">生成</tspan>
</text>
HTML
<div class="form-group mt-5 row">
    <div class="col-sm-6">
        <input type="text" class="form-control svg-text" data-target="#text-1" value="文字の" placeholder="文字を入力してください">
    </div>
    <div class="col-sm-6">
        <input type="text" class="form-control svg-text" data-target="#text-2" value="生成" placeholder="文字を入力してください">
    </div>
</div>
Javascript
//テキスト入力時のイベント 入力文字をSVGのTEXT要素に反映
$('.svg-text').on('input',function(e) {
    let targetTspan=$(this).data('target');
    $(targetTspan).text($(this).val());
})

Vue.jsの場合

SVG
<text transform="matrix(1 0 0 1 28 163.7373)">
    <tspan x="0" y="0" class="st0 st1 st2">{{text1}}</tspan>
    <tspan x="270" y="0" class="st3 st1 st2">{{text2}}</tspan>
</text>
HTML
<div class="form-group mt-5 row">
    <div class="col-sm-6">
        <input type="text" v-model="text1" class="form-control"  placeholder="文字を入力してください">
    </div>
    <div class="col-sm-6">
        <input type="text" v-model="text2" class="form-control"  placeholder="文字を入力してください">
    </div>
</div>
Javascript
var app = new Vue({
    el: '#app',
    data: {
        text1: '文字の',
        text2: '生成',
    ...

Vue.jsの特徴が出てきました。

Javascriptのdataで指定している「text1」「text2」プロパティの値がsvg内の{{text1}}、{{text2}}に表示されます。

またinputタグの「v-model」属性(vueではディレクティブと呼ばれている)に値(text1、text2)を指定するだけで、Javascriptのdataプロパティ値の取得、反映をvue.js内部で処理してくれます。

jQueryだとinputイベントでDOM要素を直接指定し処理を書く必要がありますが、vueではv-modelを指定すれば処理は不要となります。

 

画像取得イベントの処理

jQueryの場合

SVG
<svg version="1.1" id="svg-generator" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
        y="0px" viewBox="0 0 506 253" style="enable-background:new 0 0 506 253;width:100%;" xml:space="preserve" width="506" height="253" >
HTML
<button class="btn btn-info" id="create-image">画像を取得</button>
Javascript
//画像取得ボタンクリック時のイベント SVG要素を画像に変換し表示する
$('#create-image').on('click',function(e) {
    //SVG要素をbase64エンコードしDataURI形式に変換
    let svgElem = document.getElementById('svg-generator');
    let svgStr = new XMLSerializer().serializeToString(svgElem);
    let svgBase64 = "data:image/svg+xml;base64,"
        + btoa(unescape(encodeURIComponent(svgStr)));

    // HTMLCanvasElement オブジェクトを作成する
    let canvas = document.createElement("canvas");
    // CanvasRenderingContext2D オブジェクトを取得する
    let ctx = canvas.getContext("2d");

    // 新たな img 要素を作成
    let image = new Image();
    image.onload = function(){
        //Retina対応しているブラウザだと画像がぼやけるため2倍にする
        canvas.width = image.width*2;
        canvas.height = image.height*2;

        //SVG画像をCanvasに描画
        ctx.drawImage( image,0,0,image.width,image.height,0,0,canvas.width,canvas.height);

        //Canvasに描画されている画像をDataURI形式でsrc属性に設定
        $('#svg-image').attr('src',canvas.toDataURL("image/png"));

        //bootstrap4のモーダルを表示
        $('#svg-box').modal();
    }
    // Base64エンコードしたSVG画像を設定
    image.src = svgBase64;
});

Vue.jsの場合

SVG
<svg version="1.1" ref="svgGenerator" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
        y="0px" viewBox="0 0 506 253" style="enable-background:new 0 0 506 253;width:100%;" xml:space="preserve" width="506" height="253" >
HTML
<button class="btn btn-info" @click="createImage">画像を取得</button>
Javascript
methods: {
    createImage: function (event) {
        //SVG要素をbase64エンコードしDataURI形式に変換
        let svgElem = this.$refs.svgGenerator;
        let svgStr = new XMLSerializer().serializeToString(svgElem);
        let svgBase64 = "data:image/svg+xml;base64,"
            + btoa(unescape(encodeURIComponent(svgStr)));

        // HTMLCanvasElement オブジェクトを作成する
        let canvas = document.createElement("canvas");
        // CanvasRenderingContext2D オブジェクトを取得する
        let ctx = canvas.getContext("2d");

        //vueのインスタンスを設定
        let vueIns=this;
        // 新たな img 要素を作成
        let image = new Image();
        image.onload = function(){
            //Retina対応しているブラウザだと画像がぼやけるため2倍にする
            canvas.width = image.width*2;
            canvas.height = image.height*2;

            //SVG画像をCanvasに描画
            ctx.drawImage( image,0,0,image.width,image.height,0,0,canvas.width,canvas.height);

            //Canvasに描画されている画像をDataURI形式でsrc属性に設定
            vueIns.svgImage=canvas.toDataURL("image/png");
			
			//bootstrapのモーダルを表示
            vueIns.$refs['svgBox'].show();

        }
        // Base64エンコードしたSVG画像を設定
        image.src = svgBase64;

    }
}

inputタグに@click="createImage"を指定し、JavascriptのcreateImageメソッドを呼び出します。

DOM要素を参照する場合ref属性を使用する

直接DOM要素を参照、操作する場合はref属性を指定します。

svgタグでref="svgGenerator"と指定し、Javascript4行目のthis.$refs.svgGeneratorによりsvgのDOM要素を取得しています。

 

Bootstrap Vueコンポーネントを使用しモーダルダイアログ表示

jQueryの場合

HTML
<div class="modal fade" id="svg-box">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">右クリック・長押しで保存</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                <span aria-hidden="true">×</span>
                </button>
            </div>
            <div class="modal-body">
                <img src="" id="svg-image" style="width:100%;">
            </div>
        </div>
    </div>
</div
Javascript
//bootstrap4のモーダルを表示
$('#svg-box').modal();

 

Vue.jsの場合

HTML
<b-modal ref="svgBox" title="右クリック・長押しで保存" hide-footer>
    <img :src="svgImage" style="width:100%;">
</b-modal>
Javascript
//bootstrapのモーダルを表示
vueIns.$refs['svgBox'].show();

bootstrap vue compornentを使用するとb-modalタグを指定し上記のようにコードがシンプルになります。

詳しいタグの説明は以下を参照してください

https://bootstrap-vue.js.org/docs/components/modal

 

以上がvue.jsとjQueryで実装した文字ジェネレーターの比較でした。

 

個人的にはVue.jsで実装しているとJavascriptでコード書くのが楽しくなります。

 

jQueryは個人で開発するには手軽で良いんですけどね。

複数名で開発してjsが外部に定義されていたりすると、どこに処理が書いてあるのか分からなくなってコードを追うのに苦労します。

 

でも強力なプラグインがjQueryには豊富にあるので、これからは上手く使い分けていきたいです。

それでは最後まで読んでいただきありがとうございました。

Pocket

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です