てけとーぶろぐ。

ソフトウェアの開発と、お絵かきと、雑記と。

Reader Capture 機能紹介: 範囲選択機能

電子書籍をPDFファイル/ZIPファイルに変換できるWindows用アプリReader Captureに追加した機能を紹介します。 今回は範囲選択機能です。

この度、固定トリミングの範囲選択が使いやすくなりました。

Reader Capture

…といっても、そもそも固定トリミングって何のこと? かと思いますのでそこから説明させていただきます。

Reader Capture は電子書籍リーダーのスクリーンショットを撮って保存していくわけですが 保存の際にスクリーンショットの余計な部分を取り除いて電子書籍の誌面部分だけになるようにトリミングを行うことができます。

トリミングには固定トリミングと自動トリミングがあり、両方ONにした場合はまず固定トリミングが行われ、その結果に対して自動トリミングが行われます。

固定トリミングはスクリーンショットの上下左右を指定された幅だけ切り落とします。

例えばスクリーンショットがこのような場合 左:100、右:100、上:0、下:0、と指定すると、ここから左右100ピクセル幅だけ、つまりこのオレンジ枠の部分が切り落とされます。

自動トリミングはスクリーンショットの上下左右の各辺について辺上が単一色であるかぎり切り落としていきます。

スクリーンショットがこのような場合 上辺、このオレンジ枠の領域(縦幅1ピクセル)について見てみると両端が黒で真ん中が白というように黒と白が混ざっているので上辺はこれ以上切り落としません。 左辺、このオレンジ枠の領域(横幅1ピクセル)について見てみると黒一色なので切り落とします。 このように上下左右の辺を切り落とせる辺がなくなるまで切り落とします。 結果として左右の黒い部分が切り落とされ、誌面にあたる白い部分だけが残ります。

それで、実際に電子書籍リーダーをキャプチャーするときにどんな指定にすべきかについてですが…

こんな風にフルスクリーンで誌面と余白のみであれば自動トリミングのみでOKです。

こんな風に誌面の周りに自動トリミングで取り除けなそうなものがある場合は固定トリミングもONにしておおまかにトリミングして後は自動トリミングに任せます。

あるいは、誌面がどのページも固定サイズなのであれば手動トリミングのみONにして誌面がちょうど残るように正確に上下左右のトリミング幅を指定すればOKです。

前置きが長くなりましたが、特に一番最後に出てきた正確に上下左右のトリミング幅を指定する際に便利なのが今回使いやすくなった固定トリミングの範囲選択機能です。

使い方は簡単。「範囲選択」ボタンをクリックして、始点、終点、とクリックしてやればこの範囲が残るように上下左右のトリミング幅がセットされます。

範囲選択の際にはマウスカーソルの周りが拡大表示されており、カーソルキーで位置の微調整もできるのできっちり範囲選択できます。

書籍「AndroidスマホだけではじめるWebアプリ開発」

ここ最近やっていたAndroidだけを使ったWebアプリ開発の連載に加筆・修正を加えて本にしました。

PCを持っていなくても本を片手にAndroidスマホ/タブレットだけで完結できるよう構成しています。

学生の方なんかにも手にとってもらいたくて価格を抑えています。プレゼントなどにもどうぞ~。

AndroidでWebブラウザーのデベロッパーツールを使う

デベロッパーツール

パソコン用のメジャーなWebブラウザーにはデベロッパーツールという開発者用の機能があります。

このデベロッパーツールでは例えばWebサイトの画面の構成要素の詳細な情報を確認できたり、プログラムからのメッセージを表示するのに使えたりするコンソールというものがあったりします。

Web開発には必須とも言えるデベロッパーツールですがAndroidChromeには見当たりません。 そこでAndroidデベロッパーツールを使う方法を紹介します。

Kiwi Browser

Chromeには見当たらないのですがChromeと同じくChromiumをベースに作られている「Kiwi Browser」というWebブラウザーには開発者ツールがあるのでこれを使います。

Kiwi Browser をインストールしましょう。Kiwi Browser のWebサイトを開きます。

kiwibrowser.com

「Play Store」のボタンがあるのでタップします。

直接Playストアで探してインストールしても構いません。通常のアプリと同じようにインストールします。

インストールできたら起動します。Kiwi Browser もWebブラウザーですからChromeと同じようにWebを閲覧できます。たとえば「google.com」にアクセスしてみます。

このようにWebサイトを開いた状態で、右上の「…」ボタンからメニューを開き、メニューの下の方にある「開発者ツール」をタップすると、新しいタブとしてデベロッパーツールが開きます。右上のタブの数の表示が「2」になっています。

タブを切り替えてデベロッパーツールを見てみましょう。 左上のタブ数が表示されているボタンをタップし「DevTools」ではじまるタイトルになっているタブをタップします。これがデベロッパーツールです。

はじめての表示だとこんな風に日本語で表示するかを問われるかもしれません。 日本語で表示するなら右のボタンをタップします。 Chromeの言語と一致させるなら左のボタンをタップします。

日本語で表示するとこんな風になります。

コンソールへの出力

デベロッパーツールにはたくさんの機能がありますが、ここでは試しにコンソールを使ってみましょう。 WebサイトのJavaScriptプログラムからコンソールにメッセージを出力して、そのメッセージをデベロッパーツールのコンソールで確認します。

AndroidでWebアプリを作る - てけとーぶろぐ。 で作ったゲームにコンソールへのメッセージ出力を加えてみましょう。

microで「script.js」ファイルを開きます。 「handleTouch()」関数は画面がタップされた時に呼ばれる関数です。ここにコンソールへのメッセージ出力を加えてみます。具体的には「handleTouch()」関数の1行目に以下を加えます。

console.log('handleTouch() gameState: ' + gameState);

「console.log()」がコンソールにメッセージを出力する命令で「()」の中が出力するメッセージです。

メッセージは何でもいいのですがここでは「gameState」変数の値を表示しています。 メッセージ出力を加えた「handleTouch()」関数のはじめの方は以下のようになります。

function handleTouch() {
    console.log('handleTouch() gameState: ' + gameState);
    if (gameState === 'title') {
        gameState = 'beforeGame'
…略…

動作を確認してみましょう。これまでと同じようにWebサーバーを起動して、Webブラウザーでアクセスするわけですけど、ここで使うWebブラウザーはChromeではなくKiwi Browserになります。Kiwi Browser で「localhost:8080」にアクセスします。

ゲーム画面が表示されたらデベロッパーツールを開きます。

「コンソール」タブをタップします。

コンソールには

Failed to load resource: the server responded with a status of 404 (File not found)

といったエラーメッセージが出力されていますがまだ画面をタップしていないのでタップで出力するようにしたメッセージについてはまだ出力されていません。

ちなみにこのエラーメッセージはメッセージの通りで「favicon.ico」というファイルを用意してやれば出なくなります。興味があれば調べてみてください。

ゲーム画面のタブに切り替え、ゲーム画面をタップしてから、再度デベロッパーツールのタブに切り替えみましょう。

コンソールに「handleTouch() gameState: title」と出力があるはずです。

画面がタップされて「handleTouch()」関数が呼び出されるたびに出力され、そのときのgameState」変数の値が確認できます。 こんな風にコンソールへの出力を使うとプログラムの処理の流れを追ったり、処理の途中での変数の値を確認したりといったことができプログラムの確認や修正に役立ちます。

AndroidでWebアプリを作る

作成するゲーム

プログラムの詳細には触れないのでファイルを書き換えるだけの単純作業になってしまうかもしれませんが一応ゲームアプリっぽく仕上げてみましょう。

名付けて「10秒で何回タップできるかゲーム」です。

おおよそ察しがついたかと思いますがプレイ画面と一緒にゲームの流れを説明します。

  • WebアプリのURLにアクセスすると「Tap To Start」と表示されます。

  • 画面をタップすると「Ready...」と表示され…

  • ゲーム開始です。「Time」のカウントダウンがはじまります。 ひたすら画面をタップするとスコアがあがっていきます。

  • 「Time」が0になったら終了です。

  • すこしすると「Time」の表示が消えます。 ここで画面をタップするとはじめの画面に戻ります。

画面遷移を整理するとこんなですね。

HTMLファイル

それでは作っていきましょう。 このゲームのWebアプリも既に用意した「index.html」「style.css」「script.js」の3ファイルで構成されています。

まずは「index.html」を以下の内容にします。

<!DOCTYPE html>
<html lang="ja" ontouchstart="handleTouch()">

<head>
    <meta charset="utf-8">
    <meta name="viewport"
        content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <title>Rapid Fire Game</title>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
</head>

<body>
    <div id="message"></div>
    <div id="remaining-time">Time: <span id="remaining-time-value"></span></div>
    <div id="score">Score: <span id="score-value"></span></div>
    <div id="high-score">High Score: <span id="high-score-value"></span></div>
</body>

</html>

以下のURLからコピーできます。

https://github.com/kurima-yoshida/web-dev-on-android/blob/main/rapid-fire-game/index.html

「メッセージ」「残り時間」「スコア」「ハイスコア」それぞれのために要素を用意してIDを振っています。

CSSファイル

次に「style.css」を以下の内容にします。 これは前の状態から変更なしです。

html {
    height: 100%;
}

body {
    background-color: #00bfff;
    color: white;
    font-size: 40px;
    margin: 0;
    height: 100%;
    user-select: none;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

以下のURLからコピーできます。

https://github.com/kurima-yoshida/web-dev-on-android/blob/main/rapid-fire-game/style.css

JSファイル

最後に「script.js」を以下の内容にします。

var gameState = 'title';
var elapsedSeconds = 0;
var gameTimer = null;
var touchNumber = 0;
var highScoreTouchNumber = 0;

function handleTouch() {
    if (gameState === 'title') {
        gameState = 'beforeGame'
        elapsedSeconds = 0;
        gameTimer = setInterval(handleTimer, 1000);
        touchNumber = 0;
    } else if (gameState === 'game') {
        touchNumber++;
        if (touchNumber > highScoreTouchNumber) {
            highScoreTouchNumber = touchNumber;
        }
    } else if (gameState === 'result') {
        gameState = 'title'
    }
    updateScreen();
}

function handleTimer() {
    elapsedSeconds++;
    if (elapsedSeconds === 1) {
        gameState = 'game';
    } else if (elapsedSeconds === 1 + 10) {
        gameState = 'afterGame';
    } else if (elapsedSeconds === 1 + 10 + 3) {
        gameState = 'result';
        clearInterval(gameTimer);
        gameTimer = null;
    }
    updateScreen();
}

function updateScreen() {
    if (gameState === 'title') {
        document.getElementById('message').style.display = 'block';
        document.getElementById('remaining-time').style.display = 'none';    
        document.getElementById('score').style.display = 'none';    
        document.getElementById('high-score').style.display = 'none';    
        document.getElementById('message').innerText = 'Tap To Start';
    } else if (gameState === 'beforeGame') {
        document.getElementById('message').innerText = 'Ready...';    
    } else if (gameState === 'game') {
        document.getElementById('message').style.display = 'none';
        document.getElementById('remaining-time').style.display = 'block';    
        document.getElementById('score').style.display = 'block';    
        document.getElementById('high-score').style.display = 'block';    
        var remainingTime = 1 + 10 - elapsedSeconds;
        document.getElementById('remaining-time-value').innerText = remainingTime;    
        document.getElementById('score-value').innerText = touchNumber;    
        document.getElementById('high-score-value').innerText = highScoreTouchNumber;    
    } else if (gameState === 'afterGame') {
        document.getElementById('remaining-time-value').innerText = 0;
    } else if (gameState === 'result') {
        document.getElementById('remaining-time').style.display = 'none';    
    }
}

setTimeout(updateScreen);

以下のURLからコピーできます。

https://github.com/kurima-yoshida/web-dev-on-android/blob/main/rapid-fire-game/script.js

ポイントだけ説明します。

  • touchstartイベントの処理を「handleTouch()」関数に、画面の更新処理を「updateScreen()」関数にまとめて、ゲームの状態を表す変数「gameState」の値に応じて実行する処理を切り替えています。
  • 1秒経過ごとに処理をするために「setInterval()」という命令を使っています。「setInterval(handleTimer, 1000)」とすると1000ミリ秒(=1秒)経過するごとに「handleTimer()」関数が呼び出されます。
動作確認

ファイルを更新したらWebサーバーを起動してうまく動くか確認してみましょう。

問題なければレンタルサーバーにアップロードしてそちらでも動くか確認してみましょう。

AndroidでWebサイトを作る(5)

Webサイトの公開

Webサイトを構成するファイルを作成し、スマホ/タブレット上でWebサーバーを起動し、Webブラウザーで確認することができました。Webサイト作成の最後としてこれを公開します。

Webサイトを公開するというのはインターネットに接続された世界中のコンピューターからそのサイトを閲覧できるようにすることです。ですからあなたが作ったWebサイトを公開すれば、他のWebサイト同様、友達のスマホから簡単に見ることができます。

ところでここまででもスマホ/タブレット上でWebサーバーを起動して同じスマホ上のWebブラウザーでWebサイトを見ることができていました。公開には何が足りないのでしょうか?

まずスマホ/タブレット上のWebサーバーはネットワーク的にインターネット経由でアクセスできるようになっていません。インターネット経由でアクセスできるようにすることがほぼ公開そのものですから、そりゃそうだ、ではあります…。

それからもう1つ、スマホ/タブレット上のWebサーバーは常にアクセスできるようにはなっていません。Webサーバーを終了すればアクセスできなくなりますし、スマホ/タブレットの電源を切ってもアクセスできなくなります。Webサイトはおおよそいつでもアクセスできることが望ましいです。

レンタルサーバ

このような問題を解決する手軽な方法の1つとして、上記のような問題がないコンピューターを借りて、そこに自分が作ったWebサイトのデータを置かせてもらうといった方法があげられます。実際これはよく採用される方法で、こういった用途に借りられるコンピューターをレンタルサーバーと呼びます。

コンピューターを借りるといってもコンピューターの本体を借りるわけではありません。コンピューター本体は世界のどこかで動いている状態にあって、そのコンピューターにWebサイトのデータをインターネット経由でアップロードして置いておいてもらいます。つまりWebサイトのデータ保存のためのディスク領域などを借りることになるわけです。

借りるとなるとお金がかかるのではと思われるでしょう。実際有料のレンタルサーバーもあるのですが幸い無料のレンタルサーバーというものもあります。

無料である分置けるデータ容量が少なかったりと何らかの制限があることがほとんどですがここまで作ってきたような簡単なWebサイトを公開するには十分です。

無料レンタルサーバ

ということで無料のレンタルサーバーを使ってWebサイトの公開をしてみましょう。今回はAndroidからのWebサイトのデータのアップロードのしやすさなどからXFREE(https://www.xfree.ne.jp)という無料レンタルサーバーを使います。

はじめにXFREEのWebサイトから利用の申し込みをします。

www.xfree.ne.jp

XFREEのWebサイトはパソコンでの閲覧を想定しているようでスマホの縦画面だと見づらいかもしれません。その場合横画面にして表示すると良さそうです。

  1. 「無料レンタルサーバーご利用お申し込み」のボタンをタップします。
  2. メールアドレスを登録します。
  3. 登録したメールアドレスに「お申し込みURL」が記載されたメールが届くのでそのURLにアクセスします。
  4. 会員情報登録フォームにお客様情報を入力し、確認画面へ進みます。
  5. 内容に問題がなければ会員登録を確定します。
  6. 登録したメールアドレスに会員登録完了のお知らせのメールが届き そこに「管理パネル」のURLが記載されているのでアクセスし メールにあった会員IDと会員情報登録の際に登録したパスワードでログインします。
  7. 画面左のメニューから「無料レンタルサーバー」をタップします。
  8. 無料レンタルサーバー利用にあたってサーバーIDの登録をします。 サーバーIDは公開するWebサイトのURLの一部となるのでそれらしいものにしましょう。 例えばサーバーIDを「kurima」としたらWebサイトのURLは「http://kurima.html.xdomain.jp」となりました。 サーバーIDを入力して確認画面へ進みます。
  9. 問題がなければサーバーIDの登録を確定します。
  10. 登録が完了した、利用にはメニューの「無料レンタルサーバー」をクリック といったメッセージが表示されるので「無料レンタルサーバー」をタップします。
  11. ご利用状況一覧が表示されます。Webサーバーを利用したいので「HTML」の行の「利用を開始する」をタップします。
  12. ご利用状況一覧の「HTML」の行のステータス列が「利用中」に変わり、サーバーパネル列に「管理パネルログイン」ボタンが表示されます。これでレンタルサーバーのWebサーバーが使えるようになりました。「管理パネルログイン」ボタンをタップします。
  13. サーバー管理パネル画面で「ドメイン設定」をタップします。 ドメイン設定一覧にドメイン名が表示されています。このドメイン名がほぼWebサイトのURLとなります。 例えばドメイン名が「kurima.html.xdomain.jp」であればWebサイトのURLは「http://kurima.html.xdomain.jp」となります。 あとでアクセスするのでメモしておきましょう。
  14. 続けて画面左のメニューから「FTPアカウント設定」をタップします。
  15. FTPアカウント設定画面が表示されます。 レンタルサーバーへのWebサイトのデータのアップロードにはFTPという仕組みを使います。 FTPでのアップロードに必要になるのでこの画面に表示されている 「FTPホスト」「FTPユーザー(アカウント名)」「FTPパスワード」をメモしておきましょう。「FTPパスワード」についてはこれから設定します。 「FTPパスワード」設定のため「メニュー」列の「編集」ボタンをタップします。
  16. 任意のパスワードを入力して「確認画面」ボタンをタップします。
  17. 問題がなければ確定します。

これでレンタルサーバーの設定は完了です。

ここで現状レンタルサーバーのWebサーバーが公開しているWebサイトを確認してみましょう。 Webブラウザーで先程メモしたドメイン名に基づくURLにアクセスします。URL欄にドメイン名そのまま入力しても大丈夫です。

「まだホームページがアップロードされていません」と書かれたWebサイトが表示されたかと思います。 これは現状Webサイトのデータとしてこのような内容のHTMLファイルが置かれているためです。

このWebサイトのデータをこれまで作成したWebサイトのデータに置き換えてやればこのURLへのアクセスで作成したWebサイトが表示され公開完了となります。

FTP

WebサイトのデータであるHTMLファイル、CSSファイル、JSファイルを今操作しているスマホ/タブレットからレンタルサーバーにアップロードするためにはTermux上で「ftp」コマンドを使います。早速「ftp」コマンドでファイルのアップロードをしてみましょう。

ftp」コマンド実行の前にカレントディレクトリにアップロードしたいファイルがあることを確認しましょう。カレントディレクトリのファイルを確認するには「ls」コマンドを使うのでした。

ls

「index.html」「style.css」「script.js」があるでしょうか?ファイルの存在を確認したら以下の書式でftpを起動してレンタルサーバーとの通信を開始します。

ftp FTPホスト

FTPホストの部分はXFREEのFTPアカウント設定で確認したものです。例えばFTPホストが「sv2.html.xdomain.ne.jp」であればコマンドとしては

ftp sv2.html.xdomain.ne.jp

となります。コマンドを実行すると続けて

Name (…): 

のように表示されFTPユーザーの入力を促されるのでFTPアカウント設定で確認したFTPユーザーを入力します。すると続けて

Password: 

FTPパスワードの入力を促されるのでFTPアカウント設定で設定したFTPパスワードを入力します。 「FTPホスト」「FTPユーザー」「FTPパスワード」が正しく入力できると

230 User FTPユーザー logged in.
ftp> 

のように表示されます。 正しく入力できなかった場合は

530 Login incorrect.
ftp: Login failed.
ftp> 

のように表示されます。 ログインできなかった場合でもftp自体は起動しており「ftp>」と表示されてftp用のコマンドを入力できるようになってしまっています。その場合は

ftp> quit

と入力してftpを終了し、再度「ftp」コマンドの実行から行ってください。 「ftp>」の部分は既に表示されているものなので実際に入力するのは「quit」だけです。

その他しばらく操作せずに放っておいた場合などでもレンタルサーバーとの通信の接続が切れてしまう場合があります。その場合ftp用のコマンド実行に対して

Not connected.

といったメッセージが表示されます。その場合も

ftp> quit

と入力してftpを終了し、再度「ftp」コマンドの実行から行ってください。

これでレンタルサーバーとの通信を開始できました。「ftp>」と表示されてftp用のコマンドを入力できます。ftp用のコマンドにはTermux上でファイル・ディレクトリの確認に使ったものと似たものがあります。 まずカレントディレクトリを確認してみましょう。「pwd」コマンドを使います。

ftp> pwd

コマンドを実行すると

257 "/" is the current directory

と表示されます。「/」がレンタルサーバーにおけるカレントディレクトリということです。 そしてレンタルサーバーのそのディレクトリ内にあるファイルを確認してみましょう。「ls」コマンドを使います。

ftp> ls

画面の幅が狭いと見づらいかもしれませんが各行末にあるのがファイル名で「index.html」もありますね。これが先程見たWebサイトを構成するファイルです。これらのファイルがレンタルサーバーのWebサーバーによって公開されているわけです。

それではファイルをアップロードしてみましょう。アップロードには「put」コマンドを使います。以下の書式です。

ftp> put ファイル名

「ファイル名」にはスマホ/タブレットのカレントディレクトリ内にあるアップロードしたいファイルのファイル名を指定します。 まずは「index.html」をアップロードしてみましょう。

ftp> put index.html

続けて「style.css」「script.js」もアップロードしてみましょう。

ftp> put style.css
ftp> put script.js

アップロードできたか念のため「ls」コマンドで確認してみましょう。

ちなみに間違ったファイルをアップロードしてしまった場合などにレンタルサーバー上のファイルを削除するには「delete」コマンドを使います。

ftp> delete ファイル名

アップロードが終わったらftpを終了します。終了には「quit」コマンドを使います。

ftp> quit

Webサイトのデータを更新したのでWebブラウザーで表示を確認してみましょう。 表示できたでしょうか?

もちろん友達のスマホからもこのURLにアクセスすることでこのWebサイトを見ることができます。

AndroidでWebサイトを作る(4)

JSファイルの作成

続けてJSファイルにプログラムを書いてみましょう。JSファイルはJavaScriptというプログラミング言語で記述します。「script.js」を以下の内容にします。

alert('Hello, JS!');

「alert()」は指定された内容を持つダイアログを表示する命令です。

JavaScriptの動作を確認

Webサーバーを起動してWebブラウザーでWebサイトにアクセスして動作を確認してみてください。アクセスするとすぐにダイアログが表示されます。

関数の定義

次に関数を定義してみます。関数とは処理のまとまりに名前をつけたものと考えてください。

function 関数名() { 処理 }

という書式で関数を定義します。例えば「script.js」を以下の内容にしてみましょう。

function myFunction() {
  alert('Hello, Function!');
}

「myFunction」という名前の関数を定義し、その処理内容として「aler()」で「Hello, Function!」と表示するようにしています。

これを実行すると、つまりWebブラウザーでWebサイトにアクセスするとどうなるでしょうか?予想した上で、実際に試してみてください。

試してみると分かるかと思いますが、何も起きずダイアログが表示されることもありません。というのも「function myFunction() { … }」という記述は関数の定義にすぎないからです。「処理」の部分に書かれた一連の処理に「myFunction」という名前をつけただけなのです。

ではこの「処理」の部分に書かれた一連の処理は一体いつ実行されるのかと言いますと、関数が呼び出された時に実行されます。

実際にやってみましょう。先程の「script.js」の末尾に関数の呼び出しを書き加えます。「script.js」全体は以下のようになります。

function myFunction() {
  alert('Hello, Function!');
}

myFunction();

「myFunction();」の部分が関数の呼び出しです。「function myFunction() { … }」で定義された関数「myFunction()」が「myFunction();」の行で実行され、それによってその処理内容である「alert('Hello, Function!');」が実行されます。

動作を確認してみましょう。

ここで、定義した関数の呼び出しと「alert()」の呼び出しで書式が似ていることに気づいたかと思います。「alert()」ははじめから用意されている命令です。一方で自分でも命令と似た関数を作れるわけです。そしてあらかじめ用意されている命令や、自分で作った関数を呼び出すような処理内容の新しい関数を作ることもできます。

イベントハンドラ

関数「myFunction()」を定義し、その呼び出しを行いました。呼び出しは「script.js」から行いました。 さてこのように「script.js」に「function 関数名() { … }」で囲むことなく直接書いた処理は、「script.js」の内容が実行されるWebサイトの読み込み時に一度実行されるだけです。 しかし、ユーザーが何らかの操作を行ったらその操作に対応した処理を行う、といった仕組みがあった方が分かりやすくプログラムを書けそうではないでしょうか?アプリ的な機能を持つWebアプリでは特にそうです。 その仕組みにあたるのがイベントハンドラーという仕組みです。

ユーザーからの操作などの出来事をイベントと呼び、そのイベントを処理するものということでイベントハンドラーという名前がついています。具体的にどんなものであるかは実際に使ってみたほうが分かりやすいかと思います。試しにイベントハンドラーを使ってユーザーがWebサイトの画面をタップしたら「alert()」で「Touched!」と表示するようにしてみましょう。

まず画面がタップされた時に実行したい処理を持った関数を定義します。関数名は何でもいいですがタップのイベントで呼び出される関数なので「handleTouch()」としましょう。実行したい処理も書けるかと思います。ということで「script.js」は以下の内容になります。

function handleTouch() {
  alert('Touched!');
}

以下のURLからコピーできます。

https://github.com/kurima-yoshida/web-dev-on-android/blob/main/js-sample/script.js

あとはこの「handleTouch()」がタップされた時に呼び出されるようにすればいいわけです。これにはHTMLファイル「index.html」を編集することになります。「index.html」の「<html lang="ja">」を「<html lang="ja" ontouchStart="handleTouch()">」としましょう。「index.html」全体としては以下のようになります。

<!DOCTYPE html>
<html lang="ja" ontouchstart="handleTouch()">

<head>
  <meta charset="utf-8">
  <meta name="viewport"
    content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <title>title</title>
  <link rel="stylesheet" href="style.css">
  <script src="script.js"></script>
</head>

<body>
  Hello!
</body>

</html>

以下のURLからコピーできます。

https://github.com/kurima-yoshida/web-dev-on-android/blob/main/js-sample/index.html

この記述の意味としては「touchstart」イベントが起きたら「handleTouch()」を実行する、つまり「handleTouch()」を呼び出す、です。そしてこの「ontouchstart」がイベントハンドラーです。

「touchstart」イベントはユーザーに対象の要素がタップされたら、正確には画面に指が触れたら起きるイベントです。イベントには様々な種類があり、例えば、画面から指が離れたら起きる「touchend」イベント、画面上で指が動かされたら起きる「touchmove」イベントなどもあります。そしてこれらのイベントにはそれぞれ対応するイベントハンドラーがあります。

「script.js」「index.html」を編集できたら動作を確認してみましょう。画面のタップでダイアログが表示されたでしょうか?

画面の更新

もう少しだけ手を入れてみましょう。現状Webサイトの画面には「Hello!」と表示しています。これを、ユーザーに画面をタップされたら「Hello!」の代わりに「1」だとか「2」だとかユーザーが画面をタップした回数を表示するようにしてみましょう。

まず「index.html」の「<body>」を「<body id="score-value">」としましょう。「index.html」全体としては以下のようになります。

<!DOCTYPE html>
<html lang="ja" ontouchstart="handleTouch()">

<head>
  <meta charset="utf-8">
  <meta name="viewport"
    content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <title>title</title>
  <link rel="stylesheet" href="style.css">
  <script src="script.js"></script>
</head>

<body id="score-value">
  Hello!
</body>

</html>

以下のURLからコピーできます。

https://github.com/kurima-yoshida/web-dev-on-android/blob/main/js-sample/index.html

これは「<body>」と「</body>」で囲われた「<body>」要素の中の「Hello!」をプログラムで書き換える際に、この「<body>」要素を参照しやすいように「<body>」要素に「score-value」というIDを振っています。

次に「script.js」を以下の内容にします。

var touchNumber = 0;

function handleTouch() {
  touchNumber = touchNumber + 1;
  document.getElementById('score-value').innerText = touchNumber;
}

以下のURLからコピーできます。

https://github.com/kurima-yoshida/web-dev-on-android/blob/main/js-sample-2/script.js

内容について簡単に説明します。「var touchNumber = 0;」では「touchNumber」という名前のタップされた回数を保存するための変数(入れ物)を用意しています。

画面タップで呼び出される「handleTouch()」の中で「touchNumber = touchNumber + 1;」としてタップされた回数を1増やしています。そして「document.getElementById('score-value').innerText = touchNumber;」でタップされた回数を表示します。「document.getElementById('score-value')」の部分でHTMLの中の「score-value」というIDを持った要素を取得しています。この要素はつまり先程「index.html」で「score-value」というIDを振った「」要素ですね。「.innerText」は要素の中のテキストを意味し、ここでは「<body>」要素の中のテキストになります。このテキストは「index.html」で「Hello!」と指定されているので何もしなければ「Hello!」です。それを「touchNumber」の内容であるタップされた回数に書き換えています。

つまりユーザーが画面をタップするたびに、タップされた回数である「touchNumber」が1増え、「<body>」要素の中のテキストが「touchNumber」の内容で書き換えられ、結果としてタップされた回数が画面に表示されます。

「script.js」「index.html」を編集できたら動作を確認してみましょう。画面をタップしたらタップした回数が表示されたでしょうか?タップするたびに表示されている回数が増えたでしょうか?

イベントハンドラーによってユーザーから操作を受け付け、何らかの処理を行い、画面の要素を変更して表示を更新する…みなさんが普段使われているWebアプリもこのようにして動いています。

さて、ほんの少しだけゲームっぽくなりました。Webサイト/Webアプリ作成を公開まで含めて一通りを示すのが目的なので、Webサイトの作り込みは一旦この辺にして出来上がったWebサイトを世界に公開してみましょう。

AndroidでWebサイトを作る(3)

まだ自分のスマホ/タブレットからしか見ることはできないものの、一応これでWebサイトを作ったと言えないこともない…。 ですけど、見た目があまりに味気ないですし、最終的には簡単なゲームのWebアプリにしたいのでその準備も兼ねてもう少し手を入れてみます。

Webサイトを構成するファイル

Webサイトを構成するファイルとして代表的なものとしては、既に作成したHTMLファイルの他、CSSファイルとJSファイルがあげられます。 HTMLファイルに書かれるHTMLは主にWebサイトの構造を定義しているのに対して、CSSファイルに書かれるCSSは見た目を定義し、JSファイルに書かれるJavaScriptプログラミング言語でありプログラムにもとづいてWebサイトに動きを与えたりします。

まずはWebサイトの見た目を変えたいのでそれであればCSSを書くことになります。

HTMLからのCSSのリンクとJavaScriptの指定

CSSファイルやJSファイルは、単にそれらを用意するだけでは役割を果たしません。HTMLファイルからCSSファイルをリンクしたり、JSファイルを指定したりする必要があります。

実際にやってみましょう。index.htmlの内容を以下のようにします。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="utf-8">
  <meta name="viewport"
    content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
  <title>title</title>
  <link rel="stylesheet" href="style.css">
  <script src="script.js"></script>
</head>

<body>
  Hello!
</body>

</html>

今までのindex.htmlからの変更箇所は以下の通りです。

* 「<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">」の追記
* 「<link rel="stylesheet" href="style.css">」の追記
* 「<script src="script.js"></script>」の追記
* 「<body>」と「</body>」に囲まれた文言を変更

以下のURLにアクセスしてコピーしてくると簡単です。

https://github.com/kurima-yoshida/web-dev-on-android/blob/main/css-sample/index.html

HTMLファイルに

<link rel="stylesheet" href="style.css">

と書くことでこのHTMLファイルからCSSファイル「style.css」にリンクします。これによってこのHTMLファイルのHTMLの見た目を定義するCSSとして「style.css」のCSSが使われることになります。

またHTMLファイルに

<script src="script.js"></script>

と書くことで「script.js」の内容のJavaScriptがここに埋め込まれているのと同じことになります。これによって「script.js」にWebサイトで実行したい処理のプログラムを書いてWebサイトで実行されるようにできます。

CSSファイルの作成

「index.html」ファイルからリンクするようにしたCSSファイル「style.css」を作成しましょう。

手順の流れはやはりHTMLファイルの作成と同じです。Termuxで以下のコマンドを実行します。

micro style.css

HTMLファイルはHTML言語で記述しました。CSSファイルはCSSという言語で記述します。

「style.css」の内容を以下のようにします。

html {
    height: 100%;
}

body {
    background-color: #00bfff;
    color: white;
    font-size: 40px;
    margin: 0;
    height: 100%;
    user-select: none;
    display: flex;
    flex-direction : column;
    align-items: center;
    justify-content: center;
}

以下のURLにアクセスしてコピーしてくると簡単です。

https://github.com/kurima-yoshida/web-dev-on-android/blob/main/css-sample/style.css

内容を大まかに説明します。

* 「html {…}」はHTML中の「<html>」と「</html>」で囲われた部分に対する見た目の定義であることを表しています。
* 「height: 100%;」は高さを「100%」つまりこの要素を囲む要素いっぱいの高さとしています。
* 「body {…}」はHTML中の「<body>」と「</body>」で囲われた部分に対する見た目の定義であることを表しています。
* 「background-color: #00bfff;」は背景色を「#00bfff」で表される色である水色としています。
* 「color: white;」はテキストなどの色を「white」つまり白としています。
* 「font-size: 40px;」は文字サイズを「40px」つまり40ピクセルとしています。
* 「margin: 0;」はマージン、外周の余白を、「0」つまりなしとしています。
* 「height: 100%;」は高さを「100%」つまりこの要素を囲む要素いっぱいの高さとしています。
* 「user-select: none;」はユーザーがテキストを範囲選択できないようにしています。* 「display: flex;」は要素のコンテンツのレイアウトをフレックスボックスレイアウトと呼ばれる種類のものにしています。これにより後の「flex-direction」「align-items」「justify-content」の指定が有効になります。

* 「flex-direction : column;」は要素内のアイテムを縦方向に並べるようにしています。
* 「align-items: center;」「justify-content: center;」は左右中央、上下中央に配置するようにしています。
仮のJSファイルの作成

ひとまずJSファイルは作成だけして内容は空にしておきましょう。 特にプログラムを書いていないわけですから特に何も実行されないことになります。

micro script.js

microが起動したら何も入力せずに保存して終了します。

CSSの効果の確認

Webサーバーを起動してWebブラウザーでWebサイトにアクセスして表示を確認してみてください。CSSによって見た目が変わったでしょうか?