ティラノスクリプトでセーブ後もセーブ画面を残そうのコーナー

というコーナーです。毎度のごとく強引なことをやっておりますので、「強引だなあ……」という目でご覧ください。使用ティラノスクリプトは475a(5月21日)版です。なおtyranoフォルダ内のJSをいじったり何だりしていますので、その辺の操作を分かっていないと理解しにくいかもしれません。説明ぶん投げでやっています。つまりはただのメモだ!(強引)

セーブ後もセーブ画面を残すには、

  • セーブ画面の載っているメニューレイヤを閉じない
  • メニューレイヤ(save.html・デフォルトのままならmenu.htmlも)をhtml2canvasに撮影させない
  • セーブ後、個別のセーブデータのHTMLを更新する
    • (ついでにやりたい場合:その際にセーブが完了したかどうかを確認する)

という感じのことが必要となります。

メニューレイヤを閉じない

これは簡単ですね。kag.menu.jsのdisplaySave内の、githubのコード上では177~179行目、


            var layer_menu = that.kag.layer.getMenuLayer();
            layer_menu.hide();
            layer_menu.empty();
        

ここをサクッと削ります。それだけです。

メニューレイヤ(menu.html)をhtml2canvasに撮影させない

ただこれだけだとhtml2canvasさんがメニューレイヤもばっちり撮影するため、セーブ画面がスクショに残ります。これをどうするかというと、簡単です。以下の記事を参考に。

html2canvasの使い方メモ(canvasで出力、画像としてダウンロード) - JavaScript|ST40PG https://oar.st40.xyz/article/3122

html2canvasはdata-html2canvas-ignore=“true”という属性がつけられた要素を無視してくれます。ですのでsave.html(と、menu.html(デフォルトのようにメニューからセーブ画面を呼び出している場合))の最初のdivにでも、data-html2canvas-ignore=“true”と入れればセーブ画面がスクショに残らなくなります。これは色々使えるので、覚えておくと便利ですね。ちなみに私はマサオたたきで使ったのに最近まで普通に忘れていました。駄目人間です。


          <div data-html2canvas-ignore="true">
        

前はlayer_menu.hide();にだけしてhtml2canvasが撮り終わった後に復帰する形で改造してた気がするのですが、この方法を思い出して「これでいいか!」となり、改造コードが消え失せました。でもセーブ時にはラグが発生するので、こっちのやり方の方が安定して安心できる気がします。

セーブ後、個別のセーブデータのHTMLを更新する

ここまでで、セーブ画面が消えずにスクショにセーブ画面も映らなくなったぞ!万歳!なのですが、セーブしたセーブデータのHTMLが更新されていないので、「これ……本当に……セーブできたんですかね……?」状態になってしまいます。これはいけない。

多分ここでの更新方法は他にもあるような気がするのですが、私はもう面倒だったので強引に更新することにしました。save.htmlで生成されたHTMLを元に直接書き換えてしまいます。

kag.menu.jsのdoSaveを改造します。$.setStorageでストレージにセーブが終わった後、強引にセーブデータ情報で上書きする感じです。githubコードだと250行~あたりです。


        data = that.snap;
        data.save_date = $.getNowDate() + " " + $.getNowTime();
        array_save.data[num] = data;
        $.setStorage(that.kag.config.projectID + "_tyrano_data", array_save, that.kag.config.configSave);
        
        //★強引に更新
        var div = "<span class='save_list_item_thumb'><img style='width:100px' src='" + array_save.data[num]["img_data"] + "'></span><span class='save_list_item_area'><span class='save_list_item_date'>" + array_save.data[num]["save_date"] + "</span><span class='save_list_item_text'>" + array_save.data[num]["title"] + "</span></span>";
        var layer_menu = that.kag.layer.getMenuLayer();
        layer_menu.find(".save_display_area").eq(num).html(div);
        
        

セーブデータ配列から情報を呼び出して、元のHTMLを更新してます。このHTMLはティラノのデフォルトのセーブ画面から持ってきたやつなので、それを改造している場合はここも変更が必要となります。

とりあえず完了

これでセーブ後もセーブ画面を残すことができました。475a(5月21日)版でできたので、多分大体できると思います。できなかったらすみません。

セーブが完了したかどうかを確認する

この状態では、webstorageがいっぱいでセーブできない場合、セーブデータが空白の場合は空白のままで、既にある場合は更新されずに終わります(コンソールにはエラーが出る)。ですのでプレイヤー側でセーブの失敗に気付くことができるのではないでしょうか。

ただ、この時にどうせなら先にセーブができているか判定しておきたい、と思わないでもありません。というわけで、セーブ可否を判定をしたいわけですが、これは既にめも調さんで記事を公開してくださっています。ありがたやー!

セーブ失敗アラートを出す

この通りにすればOKです。ありがたやー!

なおセーブができない状態を再現したい時は、Config.tjsで

;configSave = webstorage
;configThumbnailQuality = high ;

とすると、デフォルト画面サイズで大体4個セーブできて残りの1個失敗くらいの塩梅になります。サムネの容量がすごいことになるわけですね。セーブ失敗時の確認をしたい時にはとても便利ですが、普段はよほど画質にこだわらなければlowでいいんじゃなかろうかと思います。webstorageも保存する変数が多くなければ圧縮でもさほど重くはならないかなあと。fileの場合は勿論関係ありません。

こうして判定を先にすると、kag.menu.jsで、


        if ($.setStorage(that.kag.config.projectID + "_tyrano_data", array_save, that.kag.config.configSave) != false) {
        
            //★強引に更新
            var div = "<span class='save_list_item_thumb'><img style='width:100px' src='" + array_save.data[num]["img_data"] + "'></span><span class='save_list_item_area'><span class='save_list_item_date'>" + array_save.data[num]["save_date"] + "</span><span class='save_list_item_text'>" + array_save.data[num]["title"] + "</span></span>";
            var layer_menu = that.kag.layer.getMenuLayer();
            layer_menu.find(".save_display_area").eq(num).html(div);
        }
        

こういう感じに書けますね。……この書き方でいいんだろうか?(適当)

自分の改造

$.setStorageWebと、$.setStorageCompressをそれぞれ改造する場合。

    $.setStorageWeb = function(key, val) {
                val = JSON.stringify(val);
                //localStorage.setItem(key, LZString.compress(escape(val)));
                    try {
                        //localStorage.setItem(key, LZString.compress(escape(val)));
                        localStorage.setItem(key, escape(val));
                    } catch (domException) {
                        if (domException.name === 'QuotaExceededError' ||
                            domException.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
                            $.alert("セーブに失敗しました");
                            return false;
                        }
                    }
            };
        
            $.setStorageCompress = function(key, val) {
                val = JSON.stringify(val);
                try {
                    localStorage.setItem(key, LZString.compress(escape(val)));
                } catch (domException) {
                    if (domException.name === 'QuotaExceededError' ||
                        domException.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
                        $.alert("セーブに失敗しました");
                        return false;
                    }
                }
                //localStorage.setItem(key, escape(val));
            };
        

こんな感じですね。どこかからコピペってきた気がします。

https://www.html5rocks.com/ja/tutorials/offline/quota-research/

多分ここを見たのではないかと思いますが、もっとスマートなやり方もあるでしょうか。でも動くのでとりあえずこういう感じで使っています。

$.setStorageにすべてを預ける版。

   $.setStorage = function (key, val, type) {
        
                if (type == "webstorage_compress") {
        
                    val = JSON.stringify(val);
                    try {
                        localStorage.setItem(key, LZString.compress(escape(val)));
                    } catch (domException) {
                        if (domException.name === 'QuotaExceededError' ||
                            domException.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
                            $.alert("セーブに失敗しました。");
                            return false;
                        }
                    }
        
                } else if (type == "file") {
        
                    $.setStorageFile(key, val);
        
                } else {
                    val = JSON.stringify(val);
                    try {
                        //localStorage.setItem(key, LZString.compress(escape(val)));
                        localStorage.setItem(key, escape(val));
                    } catch (domException) {
                        if (domException.name === 'QuotaExceededError' ||
                            domException.name === 'NS_ERROR_DOM_QUOTA_REACHED') {
                            $.alert("セーブに失敗しました。");
                            return false;
                        }
                    }
                }
        
            };
        

多分個々に書き換えるのが面倒だったんですね。でも判定を同じコードで書いてあるあたり省力化をまったく考えていない駄目な奴です。ひどい。