以前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の場合
<div id="app">
<!-- svg、input要素 -->
</div>
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の場合
<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>
<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>
//テキスト入力時のイベント 入力文字をSVGのTEXT要素に反映
$('.svg-text').on('input',function(e) {
let targetTspan=$(this).data('target');
$(targetTspan).text($(this).val());
})
Vue.jsの場合
<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>
<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>
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 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" >
<button class="btn btn-info" id="create-image">画像を取得</button>
//画像取得ボタンクリック時のイベント 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 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" >
<button class="btn btn-info" @click="createImage">画像を取得</button>
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の場合
<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
//bootstrap4のモーダルを表示
$('#svg-box').modal();
Vue.jsの場合
<b-modal ref="svgBox" title="右クリック・長押しで保存" hide-footer>
<img :src="svgImage" style="width:100%;">
</b-modal>
//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には豊富にあるので、これからは上手く使い分けていきたいです。
それでは最後まで読んでいただきありがとうございました。
コメントを残す