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

comico

comico アプリを iPhone に入れた。
たしか「ももくり」アニメが始まった直後だったから約2年ぶり。
当事は iPhone 5s だったので「画面ちいさすぎでアカン!」だった。

iPhone 7 の今はド近視+老眼ぎみな筆者でも悪くないと思えるように。
画面はデカくなる一方なのでスマホで漫画はもう全然問題無いのかも。
てか、縦スクロールで読む漫画ってスマホでは本当に最適かも。

いや実は「マンガUP!」等は随分前から入れていたりするんだけーが。
横フリックでページめくりは縦長画面の恩恵が無いって感じ。

そんなこんなで。
Comipoli Web 版はスマホでは自動で comico 型になるようにしたいなと。
特許は無いよな?

とりあえず、スマホやタブレットを見分ける方法を捜さないと。
[JavaScript] ユーザーエージェントを判定し、にクラスを付与する
こんなにアッサリ、Web JavaScript 楽すぎる。

ES6 なら includes が使えるし PC ならプラットホームも得てみたいし。
ということで。

getUserAgent(id) {
    let ua = navigator.userAgent;
    let res = "";
    if (ua.includes("iPhone"))
        res = "iPhone";
    else if (ua.includes("iPad"))
        res = "iPad";
    else if (ua.includes("Android"))
        if (ua.includes("Mobile"))
            res = "Android Smartphone";
        else
            res = "Android Tablet";
    else
        res = navigator.platform; // pc
    document.getElementById(id).innerHTML = `This is a ${res}`;
}

こんな感じに。

ちなみに iPhone, iPad 用 Google Chrome でも iPhone になる。
PC の場合ブラウザ毎に違うので「Linux x86_64」等を表示するオマケ。
window.navigator.platform – Web API インターフェイス | MDN

どうでもいいけどついでに。
navigator のプロパティ一覧なんかは以下で得ることができる。

let ss = "";
for (let s in navigator) ss += `${s}: ${navigator[s]}\n`;
document.getElementById(id).innerHTML = ss;

常識かも。

コレ書いていて JavaScript でも内包表記できればなぁと思ったけど。
配列内包表記 – JavaScript | MDN
SpiderMonkey 限定で以前はできていたのか、知らなかった。
ちなみに Gjs では今でも使えるようです。

ただし for in はできないようだ、結局意味ネェ!

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 等がワケワカな位置になってしまう。
それ以外は何も難しいことはなかった。

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