Web Applicaation」カテゴリーアーカイブ

JavaScript Image.onload Part2

前回の続き。
2つの Image.onload コールバックを検知してから描写しないといけない。
それなら最初のコールバックの中で次の onload を呼び出しすればいいじゃない。
それに気が付くまで二週間も掛かった、いや連休前で仕事も忙しかったし。

これでインラインのように処理、、、、、できなかった。
コールバックの中でしか画像の大きさを得ることができないのが痛い。

画像が横長なのか調べる必要があるけど2つ目のコールバックまで何もできない。
これを得ないと現在表示しているページ番号が不定になってしまう。
Linux, macOS 版 Comipoli のコードはやっぱり流用できそうにない。
しかたがないので prev 処理は左右ページを入れ替えるという最終手段に。

var LocaleComicViewer = {
    readComic(files) {
        //
        // etc...
        //
        // image
        this.firstPage = new Image();
        this.secondPage = new Image();
        this.firstPage.onload = ()=> {
            if (this.num == -1) {
                this.spread = false;
                this.num = 0;
                this.drawPage();
            } else {
                if (this.prev) {
                    if (this.firstPage.width > this.firstPage.height) {
                        this.spread = false;
                        this.drawPage();
                    } else {
                        if (this.num > 0) {
                            this.spread = true;
                            this.secondPage.src = this.comics[this.num - 1];
                            this.num -= 1;
                        } else {
                            this.spread = false;
                            this.drawPage();
                        }
                    }
                } else {
                    if (this.firstPage.width > this.firstPage.height) {
                        this.spread = false;
                        this.drawPage();
                    } else {
                        if (this.comics.length > this.num + 1) {
                            this.spread = true;
                            this.secondPage.src = this.comics[this.num + 1];
                        } else {
                            this.spread = false;
                            this.drawPage();
                        }
                    }
                }
            }
        }
        this.secondPage.onload = ()=> {
            if (this.secondPage.width > this.secondPage.height) {
                this.spread = false;
                this.drawPage();
            } else {
                this.drawPage();
            }
        }
        this.firstPage.src = this.comics[0];
    },
    drawPage() {
        this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
        let aw = this.canvas.width;
        let ah = this.canvas.height;
        let w = this.firstPage.width;
        let h = this.firstPage.height;
        if (w - h > 0 || !this.spread) {
            //
            // etc...
            //
        } else {
            if (this.LtoR || this.prev) {
                //
                // etc...
                //

full src
cv,js

なんとかなったけどまだ動作があやしい。
Linux 版 Comipoli も安定させるのに一年くらい使ったし、まあこんなもんや。

ところで Firefox は location.reload だけでは読み直ししないのね。
javascript – window.location.reload not working for Firefox and Chrome – Stack Overflow

setTimeout(()=> {location.reload(true);});

で解決したけど何故に。。。。。

それと今回から class をヤメて ES6 簡略構文を使うことにした。
gjs の Lang.Class とほぼ同様だしアロー関数で this は保持できるし。
new でインスタンスを作る必要が無いのであればこっちのほうが簡単なのでお勧め。

JavaScript Image.onload

Comipoli Web 版を作るとココに随分前から書いているがそろそろ本気で。
使う人がいるかどうかなんてどうだっていいんだよ。
一度だけでもサーバーサイドをやりたい、経験になれば充分!

実は今までの TestPage で着々と準備はしている。
Canvas の動的作成やらスクロールのロックやら矢印キーの取得やらetc…
次は肝心な画像の見開き表示の実装だ。

で、コミックの見開き表示なら Canvas に Image を2つ表示すればいい。
困った、Image の読み込みは非同期だ。
2つの Image.onload コールバックを検知してから描写しないといけない。
つまり Linux, macOS 版みたいな画像切り替え処理は流用できない、なんてことだ。

歳くってジジイな頭でなんとか考えた。
ひたすらインクリメントして偶数だった場合に更新処理すればよくね?

HTML5 Canvas TestPage – L’Isola di Niente

一応抜き出しすると以下のように。

var Html5CanvaTest = class {
    readComic(files) {
        // var
        this.num = -1;
        this.en = 0; //Even number
        //
        // etc...
        //
        // image
        this.firstPage = new Image();
        this.firstPage.onload = ()=> {
            this.newPage();
        }
        this.secondPage = new Image();
        this.secondPage.onload = ()=> {
            this.newPage();
        }
        this.firstPage.src = this.comics[0];
    }
    newPage() {
        if (this.num == -1) {
            this.num = 0;
            this.drawPage();
            return;
        }
        this.en += 1;
        if ((this.en % 2) == 0) {
            this.drawPage();
        }
    }
    nextPage(num) {
        if (this.comics.length > 0 && this.comics.length > this.num + 1) {
            this.firstPage.src = this.comics[this.num + 1];
            if (this.comics.length > this.num + 2) {
                this.secondPage.src = this.comics[this.num + 2];
                this.num += 2;
            } else {
                this.en += 1;
                this.num += 1;
            }
        }
    }
    drawPage() {
        this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
        // etc...

解り辛ぇ…

onload コールバック毎に this.en をインクリメント。
その this.en が偶数だった場合に canvas に描写、というのが現在の処理。
とりあえず目的は果たしたけど、なんだかなぁ。

うーん、もっとイイ方法は無いのだろうか?

関係ないけど JavaScript で検索するとマジでみんな mac だなぁ。
エロゲ専用 OS はともかく Linux 使いは何をやっているのやら。

JavaScript Event

DOM Keyboardイベントで押されたキーを判別するにはkeyプロパティを使う

JavaScript はたった数年で浦島太郎だ!
見つけてビックリ。
いやコンピューター関連は全部そうなんだけど。

JXA をやっている時に Objective-c 関連のサイトを探しまくった時。
日本の個人サイトは全部情報が古いまま放置ばかりででチト頭にきたことがある。
Linux 関連ではもう使えないコマンドを書いたブログの放置多すぎ!
古い情報なんか何も役に立たない。

そうはなりたくはないので色々と書き換えすることに。
Fedora Tips 以下も古いよな、次はココかな。

canvas size

Smart Phone Game ページを追加。
というか「ひよこを倒す」の糞みたいなコードを ES6 で書き換えた。
iPhone と Google Chrome の開発者モードでしか確認していない、多分大丈夫。

んでドハマリしたこと。
canvas のサイズは style で指定してはいけない。
こんなページをみつけてやっと解決した。

HTML canvas 基礎0 – socialakiba wiki

var ES6Game = class {
    constructor() {
        // etc...
    doBlockBreaking() {
        this.canvas = document.createElement("canvas");
        // Do not use.
        //this.canvas.style.width = `${document.documentElement.clientWidth}px`;
        //this.canvas.style.height = `${window.innerHeight}px`;
        // OK!
        this.canvas.width = document.documentElement.clientWidth;
        this.canvas.height = window.innerHeight;

と。

style 指定だと moveTo 等がワケワカな位置になってしまう。
それ以外は何も難しいことはなかった。

とにかく古臭いコードの一掃だ!

click addEventListener

前回なにげに書いたコードを見返してアレ?となった。
addEventListener には click イベントを指定できるのか。
touchend とか mouseup みたいなのでなくていいんだね。

タッチパネルとマウスの両方がこの指定でイケるみたい。
それぞれでどんな感じになるか実験ページを書いてみよう。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>タップとクリック</title>
<!-- for Smart Phone -->
<meta name="viewport" content="
    width=device-width,
    initial-scale=1.0,
    minimum-scale=1.0,
    maximum-scale=1.0,
    user-scalable=no" />
<style>
body {
    -webkit-text-size-adjust: 100%;
    font-size: 24pt;
}
div {
    background-color: #000088;
    border: 1px solid #0000ff;
    color: #ffffff;
}
</style>
<script type="text/javascript"><!--

    var counts = [0, 0, 0];
    var touch, mouse, click = null;

    var init = function() {
        // Touch
        //if (window.TouchEvent) {
            touch = document.getElementById("ID_TAP");
            touch.addEventListener("touchend", function() {
                counts[0] += 1;
                touch.innerHTML = "タップカウント: " + counts[0];
            });
        //}
        // Mouse
        mouse = document.getElementById("ID_MOUSE");
        mouse.addEventListener("mouseup", function() {
            counts[1] += 1;
            mouse.innerHTML = "マウスカウント: " + counts[1];
        });
        // Click
        click = document.getElementById("ID_CLICK");
        click.addEventListener("click", function() {
            counts[2] += 1;
            click.innerHTML = "クリックカウント: " + counts[2];
        });
    }
    //-->
</script>

</head>
<body onLoad="init()">

<div id="ID_TAP">タップカウント: 0</div>
<br />
<div id="ID_MOUSE">マウスカウント: 0</div>
<br />
<div id="ID_CLICK">クリックカウント: 0</div>
<br />
<p><a href=".">Back</a></p>
</body>
</html>

タップとクリック

tap_click

あれ?タッチパネルエミュレートで mouseup イベントが発生するのね。
iPhone Safari で試してもやはり同じ、そういうものなのか。

touchend は当然タッチパネルかエミュレートでしか反応しない。
まあこのイベントは本来マルチタッチ用途ですし使い道が違うかと。

click イベントという名前も直感的だし両対応だし今後はコイツだな。
しかし HTML5 関連サイトでもあまり見かけないような。