enchant.jsをタッチパネルに対応させるため修正してみた

## 今さらenchant.js？
　GIGAタブレットが全国の小中学生全員に配布されています。市町村によって機種が異なり、Windows、Chromebook、iPadの3種類のどれかになっています。Webアプリであれば、3種類のGIGAタブレット共通に動きます。enchant.jsもWebアプリを作動させるライブラリとして利用できます。しかし、enchant.jsはiPadでは問題なく作動しますが、タッチパネル上の移動イベント（touchmove）を取得できないため、Windows、Chromebookでは作動が不完全になります。
 　そこで、touchmoveが作動するように書き換えてみました。これで、過去に作成したenchant.jsを利用したプログラムがGIGAタブレットでも作動可能になります。
  
 ×[タッチパネルで操作できない例「とけいの学習」（マウス可、iPadでは作動）](https://kaihatuiinkai.jp/enchantjs/tokei083/ "とけいの学習")

 〇[タッチパネルで操作可能の例「とけいの学習」（マウス可、iPadでも作動）](https://kaihatuiinkai.jp/enchantjs/tokei083kai/ "とけいの学習")
 
　「今さらenchant.js？」と思われるかもしれませんが、過去の作品を少し手直しするだけで、現在の機器で利用できるプログラムに生まれ変わります。
## 修正のしかた
　enchant.js v0.8.3 の場合を例に修正方法を説明します。他のバージョンでも同様に修正するとタブレットでタッチ作動します。（0.5.2でも確認しています）
　「enchant.js」ファイルを修正します。修正場所は５カ所になります。
### 1 変数を定義
　変数を定義します。
```　Javascript:enchant.js 8行目から
var myTouchmoveX;        // touchmoveの座標
var myTouchmoveY;        // touchmoveの座標
var myTouchFlag = 0;     // mousedownとtouchstart連続反応防止フラグ
``` 
### 2 'mousedown' を検索して修正　1つ目
　enchant.js ファイルで「'mousedown'」 を検索します。4か所あります。
 検索1つ目、1129行目から1156行目までの「'mousedown'」「'mousemove'」「'mouseup'」イベントリスナーの部分をコピーします。
1157行目にペースト（複製）し、「'mousedown' を 'touchstart'」「'mousemove'を'touchmove'」「'mouseup'を'touchend'」に変更します。
```　Javascript:enchant.js 1157行目から
stage.addEventListener('touchstart', function(e) {               // touchstartに変更
    var tagName = (e.target.tagName).toLowerCase();
    if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
        e.preventDefault();
        core._mousedownID++;
        if (!core.running) {
            e.stopPropagation();
        }
    }
}, true);
stage.addEventListener('touchmove', function(e) {               // touchmoveに変更
    var tagName = (e.target.tagName).toLowerCase();
    if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
        e.preventDefault();
        if (!core.running) {
            e.stopPropagation();
        }
    }
}, true);
stage.addEventListener('touchend', function(e) {               // touchendに変更
    var tagName = (e.target.tagName).toLowerCase();
        if (enchant.ENV.USE_DEFAULT_EVENT_TAGS.indexOf(tagName) === -1) {
            e.preventDefault();
            if (!core.running) {
                e.stopPropagation();
            }
        }
}, true);
```
### 3 'mousedown' を検索して修正　2つ目
 検索2つ目、1230行目からの「'mousedown'」イベントリスナーを以下のように修正します。
```　Javascript:enchant.js 1230行目から
stage.addEventListener('mousedown', function(e) {
    if(myTouchFlag == 1){                         // mousedownとtouchstartを続けて反応させない
        return;
    };
    myTouchFlag = 1;                              // フラグ設定
    setTimeout(function(){                        // 反応させないための待機時間設定
        myTouchFlag = 0;
    },50);
    var core = enchant.Core.instance;
    var evt = new enchant.Event(enchant.Event.TOUCH_START);
    evt._initPosition(e.pageX, e.pageY);
    var target = core.currentScene._determineEventTarget(evt);
    core._touchEventTarget[core._mousedownID] = target;
    target.dispatchEvent(evt);
}, false);
```
1230行目から1263行目までの「'mousedown'」「'mousemove'」「'mouseup'」イベントリスナーの部分をコピーします。
1264行目にペースト（複製）し、「'mousedown' を 'touchstart'」「'mousemove'を'touchmove'」「'mouseup'を'touchend'」にして以下のように修正します。
```　Javascript:enchant.js 1264行目から
stage.addEventListener('touchstart', function(e) { // touchstart に変更
    if(myTouchFlag == 1){                          // mousedownとtouchstartを続けて反応させない
        return;
    };
    myTouchFlag = 1;                               // フラグ設定
    setTimeout(function(){                         // 反応させないための待機時間設定
        myTouchFlag = 0;
    },50);
    var core = enchant.Core.instance;
    var evt = new enchant.Event(enchant.Event.TOUCH_START);
    evt._initPosition(e.touches[0].pageX, e.touches[0].pageY); // タッチ座標の取得
    var target = core.currentScene._determineEventTarget(evt);
    core._touchEventTarget[core._mousedownID] = target;
        target.dispatchEvent(evt);
    }, false);
stage.addEventListener('touchmove', function(e) {              // touchmove に変更
    var core = enchant.Core.instance;
    var evt = new enchant.Event(enchant.Event.TOUCH_MOVE);
    evt._initPosition(e.touches[0].pageX, e.touches[0].pageY); // タッチ座標の取得
    myTouchmoveX = e.touches[0].pageX;                         // タッチ座標の保存
    myTouchmoveY = e.touches[0].pageY;                         // タッチ座標の保存
    var target = core._touchEventTarget[core._mousedownID];
    if (target) {
        target.dispatchEvent(evt);
    }
}, false);
stage.addEventListener('touchend', function(e) {               // touchendに変更
    var core = enchant.Core.instance;
    var evt = new enchant.Event(enchant.Event.TOUCH_END);
    evt._initPosition(myTouchmoveX, myTouchmoveY);             // touchmoveした座標
    var target = core._touchEventTarget[core._mousedownID];
    if (target) {
        target.dispatchEvent(evt);
    }
    delete core._touchEventTarget[core._mousedownID];
}, false);
```
　マウスの場合には「mouseup」でマウスのボタンを離した（クリック終了、ドラッグ終了）座標を取得できます。しかし、タッチの場合には「touchend」でタッチ終了の座標の取得はできません。よって、touchmoveの最後の座標を「タッチ終了の座標」として処理します。
### 4 'mousedown' を検索して修正　3つ目と4つ目
　検索3つ目、4200行目の「'mousedown'」アド　イベントリスナーの部分をコピー＆ペーストします。
 　4201行目を「'touchstart'」に修正します。
```　Javascript:enchant.js 4200行目から
this.element.addEventListener('mousedown', this._setDomTarget, true);
this.element.addEventListener('touchstart', this._setDomTarget, true);
```
　検索4つ目、4207行目の「'mousedown'」リムーブ　イベントリスナーの部分をコピー＆ペーストします。
 　4208行目を「'touchstart'」に修正します。
```　Javascript:enchant.js 4207行目から
this.element.removeEventListener('mousedown', this._setDomTarget, true);
this.element.removeEventListener('touchstart', this._setDomTarget, true);
```
## enchant.jsは非常に便利
　enchant.js v0.8.3 ファイルは次のURLにあります。
 [https://github.com/wise9/enchant.js](https://github.com/wise9/enchant.js)
 画面をスクロールして中間付近の「Download」の「Download Zip file」からダウンロードしてください。
 　enchant.jsを使ったプログラムのしかたは、ネット検索をすると結構でています。図形をステージに配置して、移動や回転、重なり判定などを簡単にできるenchant.jsは学習用教材づくりに適しています。ディスプレイの大きさに合わせて、部品を自動で拡大縮小してくれるのも便利です。ライブラリの読み込みに若干時間がかかりますが、許せる範囲と思います。enchant.jsのアップデート終了から約10年、開発会社も既に解散し、サイトもなくなってしまっています。それでも、使いやすい日本製のソフトです。「なんで今さら」と思わずにenchant.jsを使ってみてください。