GASでSVGを使った座席管理アプリを作る
使いドコロと使う理由
使い所
SVGで自由自在にレイアウトを構築することが出来、単純なHTMLとCSSよりも直感的にアプリケーションを使って構築が可能です。このSVG画像を使うことで
フリーアドレス対応の座席管理アプリの構築
様々な予約管理システムの構築
センサーデータと連携して、作物の監視状況の可視化
グラフィカルなサイトマップの作成
などなど応用が可能です。通常の画像とライブラリで作るよりも遥かに手軽で、大きさがスケールし、JSで操作も出来、SVGであるためクリッカブルマップのような古い技術よりも手軽につくれます。
使う理由
SVG画像はベクターグラフィックスとも呼ばれ、ウィンドウの大きさによって、その内容が自動的に劣化すること無くスケールする、中身はXMLで出来た特殊な画像形式です。
その構造であるため、HTMLの中に呼び出せれば、JavaScriptで属性や中身を変更する事も可能であり(DOM操作が可能)、色々な使い方をすることが出来ます。その元データをGoogle Spreadsheetで行えれば、立派なアプリを手早く構築が可能です。
同様の技術に古い手としてクリッカブルマップがありますが、単体で構築するのは非常に面倒で、尚且ウィンドウの大きさ等にスケールさせるためのレスポンシブ対応が難しい。SVGはライブラリも不要でSVGの特性上、レスポンシブにもともと対応してる点がメリットです。
また、最近この手の座席管理アプリのウェブサービスが出てきていますが、正直その為だけに月額数百円を人数分サブスクするというのはかなり、コスト的にどうなの?と疑問。
また、自分の場合は、クリック時に出勤打刻、リリース時に退勤打刻、合わせて追加機能で工数報告などを加えてるので、何でもソリューションで解決を図ってるとITコストが青天井に膨れ上がるので、GASを使っての内製をおすすめします。
事前準備
SVG画像の用意
Inkscapeを利用して作成します。オープンソースで無償で使うことが可能ですので、高価なイラストレータ等不要です。適当に作成した後に、XMLエディタや、ファイルをVSCodeで読み込ませて、各パーツに対して以下の修正を加えます。
rectやpathに対してIDを加えて連番となるような値を追加する
rectやpathに対して後でCSSでhover設定をする為にclass指定を加える
rectやpathのスタイルがstyleにまとめられてしまってるので、fillやstroke、stroke-widthについては切り出して追加する
textをパーツ内に用意した場合、tspanというタグがあるので、そのタグにもIDを加えて連番となるような値を追加する
aタグをパーツの大本に加えて、クリック時にイベントを起こせるようにしておく(今回はseatinfo関数を実行し、引数に直下のタグのseatA2というIDを拾って渡すようにしています)
またこのSVG画像は、大本のタグにIDがsvg5みたいなIDが振られてるのでこれをコピーしておく。その場合の完成形の1パーツ分のコードは以下の通り。
<a href="javascript:void(0);" onclick="seatinfo($(this).children().attr('id'));" id="a23">
<g id="seatA2" transform="matrix(0.84466019,0,0,0.88518024,17.616658,98.837363)">
<rect
id="A2"
width="94.380722"
height="69.397591"
x="24.057831"
y="45.33976"
class="bar"
fill="#afdde9"
stroke-width="3"
stroke="blue" />
<text xml:space="preserve"
style="font-size:16.31940592px;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';fill:#1a1a1a;stroke-width:0.0867171"
x="26.065416"
y="89.968636"
id="textA2"
transform="scale(0.99324444,1.0068015)">
<tspan sodipodi:role="line"
id="spanA2"
style="fill:#1a1a1a;stroke-width:0.0867171;font-size:16.31940592px"
x="26.065416"
y="89.968636"> </tspan>
</text>
</g>
</a>
スプレッドシートを用意
前項のSVGのIDなどを記録しておいた一覧表をスプレッドシートに用意しておく。クリックして確保されたらスプレッドシートに記録し、リリースされたらスプレッドシートから除外する処理を構築すればOK
今回は固定フラグオンで誰も確保出来ない特別な席とし、その他は確保されたら社員IDと名前を記録。他のユーザが開くとこの一覧データを拾ってマップに反映させます。
ソースコード
詳細は以下の詳細応用編はこちらから参照してください。
GAS側コード
GAS側コードはシートデータを返す処理、キープ時の処理、リリース時の処理、さらに夜中の0時にシートデータを自動クリアするトリガーを設置する等の裏方の仕事を用意しておきます。
SVG画像ファイルのロードの事例は以下のようなコードを記述します。
//SVGデータを取得して返す
function svgload(){
//SVG画像ファイルのID
let svgid = "ここにSVG画像のファイルのIDを記述する";
//ドライブのSVGファイルの中身を直接取得する
let svg = DriveApp.getFileById(svgid).getBlob().getDataAsString("utf-8");
//HTML側へ取得内容を返す
return svg;
}
またスマフォ対応する場合は、HTMLのロードをするdoGetは以下のように記述します。
function doGet(){
//スクリプトレットを使えるようにしておく
var url = 'https://officeforest.org/wp/library/mashroom.png';
var html = HtmlService.createTemplateFromFile("seatchart")
.evaluate()
.addMetaTag('viewport', 'width=device-width, initial-scale=1, maximum-scale=2.0, user-scalable=yes')
.setTitle('座席表SVG')
.setFaviconUrl(url);
return html;
}
HTML側コード
HTML側はクリック時の処理や、画面のウィンドウの大きさリサイズ時のイベント、GAS側への問い合わせ処理、SVG画像に対してのDOM操作(文字の変更、色の変更、枠線の色の変更等)を装備します。
SVG画像はDriveからロードし、IDがmapのDIVに対して読み込ませるようにします。SVGに対するCSSは以下のようなものを用意。マウスオーバーでホバーの色に変化します。
<style>
svg {
width: 100%;
height:300px;
}
svg a path{
transition: fill 0.3s linear;
}
.bar {
pointer-events: all;
}
.bar:hover {
opacity: 0.7;
fill: red;
}
#map{
width:100%;
height:1px;
}
</style>
また、リサイズ時にスケールさせるために、前項で取得したSVGの大本のIDなどを指定してリサイズ対応します。今回はsvg2がそのIDになります。
//リサイズ時にウィンドウにフィットさせる
window.onresize = function(){
setGridHeight();
}
//サイズを自動でウィンドウにフィットする
$(document).ready(function () {
setGridHeight();
});
//座席表の高さを自動補正する関数
function setGridHeight() {
var layoutHeight = $(window).height() - 25;
$('#svg2').css('height', layoutHeight + 'px');
$('#map').css('height', layoutHeight + 'px');
}
また、パーツクリック時にはseatinfo関数を実行するようにしていますが、seatinfoの引数は座席ナンバーが入ってるので、これを受け取って、GAS側で処理をさせます。
//席のキープや情報ウィンドウを出す
function seatinfo(seatid){
}
表示サンプル
詳細や応用編はこちら
#GAS #SVG #レスポンシブ #アプリ #クリッカブルマップ #JavaScript