@wwawing/virtual-pad 3.8.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 1996-2015 NAO
4
+ Copyright (c) 2015-2022 WWA Wing Team
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
@@ -0,0 +1,51 @@
1
+ export declare enum VirtualPadButtonCode {
2
+ BUTTON_ENTER = 0,
3
+ BUTTON_ESC = 1,
4
+ BUTTON_SIDEBAR = 2,
5
+ BUTTON_ESTIMATE = 3,
6
+ BUTTON_FAST = 4,
7
+ BUTTON_SLOW = 5,
8
+ BUTTON_LEFT = 6,
9
+ BUTTON_UP = 7,
10
+ BUTTON_RIGHT = 8,
11
+ BUTTON_DOWN = 9
12
+ }
13
+ export declare enum VirtualPadState {
14
+ NONE = 0,
15
+ TOUCH = 1,
16
+ TOUCHING = 2,
17
+ LEAVE = 3
18
+ }
19
+ export declare type VirtualPadButtons = {
20
+ [VirtualPadButtonCode.BUTTON_ENTER]: HTMLButtonElement;
21
+ [VirtualPadButtonCode.BUTTON_ESC]: HTMLButtonElement;
22
+ [VirtualPadButtonCode.BUTTON_SIDEBAR]?: HTMLButtonElement;
23
+ [VirtualPadButtonCode.BUTTON_ESTIMATE]: HTMLButtonElement;
24
+ [VirtualPadButtonCode.BUTTON_FAST]: HTMLButtonElement;
25
+ [VirtualPadButtonCode.BUTTON_SLOW]: HTMLButtonElement;
26
+ [VirtualPadButtonCode.BUTTON_LEFT]: HTMLButtonElement;
27
+ [VirtualPadButtonCode.BUTTON_UP]: HTMLButtonElement;
28
+ [VirtualPadButtonCode.BUTTON_RIGHT]: HTMLButtonElement;
29
+ [VirtualPadButtonCode.BUTTON_DOWN]: HTMLButtonElement;
30
+ };
31
+ declare type VirtualPadEventFunction = (buttonCode: VirtualPadButtonCode) => void;
32
+ export default class VirtualPadStore {
33
+ private _enabled;
34
+ private _onTouchStart;
35
+ private _onTouchEnd;
36
+ private _availableButtons;
37
+ private _isTouchingButtons;
38
+ private _moveButtonsElement;
39
+ constructor(buttons: VirtualPadButtons | {}, moveButtons?: HTMLElement, onTouchStart?: VirtualPadEventFunction, onTouchEnd?: VirtualPadEventFunction);
40
+ private _detectMovingMoveButton;
41
+ checkTouchButton(buttonType: VirtualPadButtonCode): boolean;
42
+ checkTouchingButton(buttonType: VirtualPadButtonCode): boolean;
43
+ getButtonState(buttonType: VirtualPadButtonCode): VirtualPadState;
44
+ setTouchInfo(buttonType: VirtualPadButtonCode): void;
45
+ clearTouchInfo(buttonType: VirtualPadButtonCode): void;
46
+ allMoveClear(): void;
47
+ allClear(): void;
48
+ static isMoveButton(buttonType: VirtualPadButtonCode): boolean;
49
+ update(): void;
50
+ }
51
+ export {};
@@ -0,0 +1,188 @@
1
+ export var VirtualPadButtonCode;
2
+ (function (VirtualPadButtonCode) {
3
+ VirtualPadButtonCode[VirtualPadButtonCode["BUTTON_ENTER"] = 0] = "BUTTON_ENTER";
4
+ VirtualPadButtonCode[VirtualPadButtonCode["BUTTON_ESC"] = 1] = "BUTTON_ESC";
5
+ VirtualPadButtonCode[VirtualPadButtonCode["BUTTON_SIDEBAR"] = 2] = "BUTTON_SIDEBAR";
6
+ VirtualPadButtonCode[VirtualPadButtonCode["BUTTON_ESTIMATE"] = 3] = "BUTTON_ESTIMATE";
7
+ VirtualPadButtonCode[VirtualPadButtonCode["BUTTON_FAST"] = 4] = "BUTTON_FAST";
8
+ VirtualPadButtonCode[VirtualPadButtonCode["BUTTON_SLOW"] = 5] = "BUTTON_SLOW";
9
+ VirtualPadButtonCode[VirtualPadButtonCode["BUTTON_LEFT"] = 6] = "BUTTON_LEFT";
10
+ VirtualPadButtonCode[VirtualPadButtonCode["BUTTON_UP"] = 7] = "BUTTON_UP";
11
+ VirtualPadButtonCode[VirtualPadButtonCode["BUTTON_RIGHT"] = 8] = "BUTTON_RIGHT";
12
+ VirtualPadButtonCode[VirtualPadButtonCode["BUTTON_DOWN"] = 9] = "BUTTON_DOWN";
13
+ })(VirtualPadButtonCode || (VirtualPadButtonCode = {}));
14
+ export var VirtualPadState;
15
+ (function (VirtualPadState) {
16
+ VirtualPadState[VirtualPadState["NONE"] = 0] = "NONE";
17
+ VirtualPadState[VirtualPadState["TOUCH"] = 1] = "TOUCH";
18
+ VirtualPadState[VirtualPadState["TOUCHING"] = 2] = "TOUCHING";
19
+ VirtualPadState[VirtualPadState["LEAVE"] = 3] = "LEAVE";
20
+ })(VirtualPadState || (VirtualPadState = {}));
21
+ var VirtualPadMoveButtonCodes = [
22
+ VirtualPadButtonCode.BUTTON_LEFT,
23
+ VirtualPadButtonCode.BUTTON_UP,
24
+ VirtualPadButtonCode.BUTTON_RIGHT,
25
+ VirtualPadButtonCode.BUTTON_DOWN
26
+ ];
27
+ var VirtualPadStore = (function () {
28
+ function VirtualPadStore(buttons, moveButtons, onTouchStart, onTouchEnd) {
29
+ if (moveButtons === void 0) { moveButtons = null; }
30
+ if (onTouchStart === void 0) { onTouchStart = null; }
31
+ if (onTouchEnd === void 0) { onTouchEnd = null; }
32
+ var _this = this;
33
+ this._enabled = Object.keys(buttons).length > 0;
34
+ this._onTouchStart = onTouchStart || null;
35
+ this._onTouchEnd = onTouchEnd || null;
36
+ this._availableButtons = [];
37
+ this._isTouchingButtons = {};
38
+ this._moveButtonsElement = moveButtons;
39
+ var _loop_1 = function (buttonTypeString) {
40
+ var buttonCode = parseInt(buttonTypeString);
41
+ var button = buttons[buttonCode];
42
+ this_1._availableButtons.push(buttonCode);
43
+ button.setAttribute("type", buttonTypeString);
44
+ this_1._isTouchingButtons[buttonCode] = {
45
+ prev: false,
46
+ current: false,
47
+ next: false
48
+ };
49
+ var cancelBrowserTouchEvent = function (event) {
50
+ if (event.cancelable) {
51
+ event.preventDefault();
52
+ }
53
+ };
54
+ var cancelVirtualPad = function (event) {
55
+ cancelBrowserTouchEvent(event);
56
+ _this.allClear();
57
+ };
58
+ button.addEventListener("touchstart", function (event) {
59
+ cancelBrowserTouchEvent(event);
60
+ _this.setTouchInfo(buttonCode);
61
+ });
62
+ button.addEventListener("cancel", cancelVirtualPad);
63
+ button.addEventListener("touchcancel", cancelVirtualPad);
64
+ if (VirtualPadStore.isMoveButton(buttonCode)) {
65
+ button.addEventListener("touchmove", this_1._detectMovingMoveButton.bind(this_1));
66
+ button.addEventListener("touchend", this_1.allMoveClear.bind(this_1));
67
+ }
68
+ else {
69
+ button.addEventListener("touchend", function (event) {
70
+ cancelBrowserTouchEvent(event);
71
+ _this.clearTouchInfo(buttonCode);
72
+ });
73
+ }
74
+ };
75
+ var this_1 = this;
76
+ for (var buttonTypeString in buttons) {
77
+ _loop_1(buttonTypeString);
78
+ }
79
+ if (moveButtons !== null) {
80
+ moveButtons.addEventListener("touchmove", this._detectMovingMoveButton.bind(this));
81
+ }
82
+ }
83
+ VirtualPadStore.prototype._detectMovingMoveButton = function (event) {
84
+ event.preventDefault();
85
+ this.allMoveClear();
86
+ var moveButtonRect = this._moveButtonsElement.getBoundingClientRect();
87
+ var bodyRect = document.body.getBoundingClientRect();
88
+ var centerPositionX = moveButtonRect.left - bodyRect.left + (moveButtonRect.width / 2);
89
+ var centerPositionY = moveButtonRect.top - bodyRect.top + (moveButtonRect.height / 2);
90
+ var touch = event.targetTouches.item(0);
91
+ var touchX = touch.pageX - centerPositionX;
92
+ var touchY = touch.pageY - centerPositionY;
93
+ if (touchX >= touchY) {
94
+ if (touchX <= -touchY) {
95
+ this.setTouchInfo(VirtualPadButtonCode.BUTTON_UP);
96
+ }
97
+ else {
98
+ this.setTouchInfo(VirtualPadButtonCode.BUTTON_RIGHT);
99
+ }
100
+ }
101
+ else {
102
+ if (touchX >= -touchY) {
103
+ this.setTouchInfo(VirtualPadButtonCode.BUTTON_DOWN);
104
+ }
105
+ else {
106
+ this.setTouchInfo(VirtualPadButtonCode.BUTTON_LEFT);
107
+ }
108
+ }
109
+ };
110
+ VirtualPadStore.prototype.checkTouchButton = function (buttonType) {
111
+ if (!this._enabled) {
112
+ return false;
113
+ }
114
+ var state = this.getButtonState(buttonType);
115
+ return state === VirtualPadState.TOUCH;
116
+ };
117
+ VirtualPadStore.prototype.checkTouchingButton = function (buttonType) {
118
+ if (!this._enabled) {
119
+ return false;
120
+ }
121
+ var state = this.getButtonState(buttonType);
122
+ return state === VirtualPadState.TOUCH || state === VirtualPadState.TOUCHING;
123
+ };
124
+ VirtualPadStore.prototype.getButtonState = function (buttonType) {
125
+ if (!this._enabled) {
126
+ return VirtualPadState.NONE;
127
+ }
128
+ var touched = this._isTouchingButtons[buttonType].prev;
129
+ var isTouching = this._isTouchingButtons[buttonType].current;
130
+ if (touched && isTouching) {
131
+ return VirtualPadState.TOUCHING;
132
+ }
133
+ else if (isTouching) {
134
+ return VirtualPadState.TOUCH;
135
+ }
136
+ else if (touched) {
137
+ return VirtualPadState.LEAVE;
138
+ }
139
+ return VirtualPadState.NONE;
140
+ };
141
+ VirtualPadStore.prototype.setTouchInfo = function (buttonType) {
142
+ if (!this._enabled) {
143
+ return;
144
+ }
145
+ this._isTouchingButtons[buttonType].next = true;
146
+ };
147
+ VirtualPadStore.prototype.clearTouchInfo = function (buttonType) {
148
+ if (!this._enabled) {
149
+ return;
150
+ }
151
+ this._isTouchingButtons[buttonType].next = false;
152
+ };
153
+ VirtualPadStore.prototype.allMoveClear = function () {
154
+ var _this = this;
155
+ VirtualPadMoveButtonCodes.forEach(function (buttonCode) {
156
+ if (_this._availableButtons.includes(buttonCode)) {
157
+ _this.clearTouchInfo(buttonCode);
158
+ }
159
+ });
160
+ };
161
+ VirtualPadStore.prototype.allClear = function () {
162
+ var _this = this;
163
+ this._availableButtons.forEach(function (buttonCode) {
164
+ _this._isTouchingButtons[buttonCode].next = false;
165
+ });
166
+ };
167
+ VirtualPadStore.isMoveButton = function (buttonType) {
168
+ return VirtualPadMoveButtonCodes.includes(buttonType);
169
+ };
170
+ VirtualPadStore.prototype.update = function () {
171
+ var _this = this;
172
+ this._availableButtons.forEach(function (buttonCode) {
173
+ var currentButtonTouching = _this._isTouchingButtons[buttonCode];
174
+ _this._isTouchingButtons[buttonCode].prev = currentButtonTouching.current;
175
+ _this._isTouchingButtons[buttonCode].current = currentButtonTouching.next;
176
+ switch (_this.getButtonState(buttonCode)) {
177
+ case VirtualPadState.TOUCH:
178
+ _this._onTouchStart(buttonCode);
179
+ break;
180
+ case VirtualPadState.LEAVE:
181
+ _this._onTouchEnd(buttonCode);
182
+ break;
183
+ }
184
+ });
185
+ };
186
+ return VirtualPadStore;
187
+ }());
188
+ export default VirtualPadStore;
@@ -0,0 +1,2 @@
1
+ export declare function initializeRotate(): void;
2
+ export default function autoRotate(): void;
@@ -0,0 +1,23 @@
1
+ export function initializeRotate() {
2
+ var headElement = document.getElementsByTagName('head')[0];
3
+ var viewportElement = document.createElement('meta');
4
+ viewportElement.setAttribute('name', 'viewport');
5
+ headElement.appendChild(viewportElement);
6
+ autoRotate();
7
+ }
8
+ export default function autoRotate() {
9
+ var WWA_WIDTH = 560;
10
+ var WWA_HEIGHT = 440;
11
+ var viewportElement = document.querySelector("meta[name='viewport']");
12
+ var browserWidth = window.innerWidth;
13
+ var browserHeight = window.innerHeight;
14
+ var viewportValue = "user-scalable=no";
15
+ if (browserWidth > browserHeight) {
16
+ var width = Math.floor((browserWidth / browserHeight) * WWA_HEIGHT);
17
+ viewportValue = "width=".concat(width, ",").concat(viewportValue);
18
+ }
19
+ else if (browserWidth <= browserHeight) {
20
+ viewportValue = "width=".concat(WWA_WIDTH, ",").concat(viewportValue);
21
+ }
22
+ viewportElement.setAttribute("content", "".concat(viewportValue));
23
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import VirtualPadStore, { VirtualPadState, VirtualPadButtonCode, VirtualPadButtons } from './VirtualPad';
2
+ import autoRotate, { initializeRotate } from './autoRotate';
3
+ import makeInject from './makeInject';
4
+ export { VirtualPadStore, VirtualPadState, VirtualPadButtonCode, VirtualPadButtons, autoRotate, initializeRotate, makeInject };
package/lib/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import VirtualPadStore, { VirtualPadState, VirtualPadButtonCode } from './VirtualPad';
2
+ import autoRotate, { initializeRotate } from './autoRotate';
3
+ import makeInject from './makeInject';
4
+ export { VirtualPadStore, VirtualPadState, VirtualPadButtonCode, autoRotate, initializeRotate, makeInject };
@@ -0,0 +1 @@
1
+ export default function makeInject(): string;
@@ -0,0 +1,3 @@
1
+ export default function makeInject() {
2
+ return "\n <div id=\"wwa-virtualpad-left\">\n <button class=\"wwa-virtualpad__button\" id=\"wwa-up-button\"></button>\n <button class=\"wwa-virtualpad__button\" id=\"wwa-left-button\"></button>\n <button class=\"wwa-virtualpad__button\" id=\"wwa-right-button\"></button>\n <button class=\"wwa-virtualpad__button\" id=\"wwa-down-button\"></button>\n <div class=\"wwa-virtualpad__hole\"></div>\n </div>\n <div id=\"wwa-virtualpad-right\">\n <button class=\"wwa-virtualpad__button\" id=\"wwa-slow-button\">I</button>\n <button class=\"wwa-virtualpad__button\" id=\"wwa-fast-button\">P</button>\n <button class=\"wwa-virtualpad__button\" id=\"wwa-enter-button\">Y</button>\n <button class=\"wwa-virtualpad__button\" id=\"wwa-esc-button\">N</button>\n <button class=\"wwa-virtualpad__button\" id=\"wwa-estimate-button\">M</button>\n </div>";
3
+ }
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "@wwawing/virtual-pad",
3
+ "version": "3.8.0-beta.1",
4
+ "description": "WWA Wing Virtual Pad for mobile phone",
5
+ "main": "lib/index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1",
8
+ "build": "tsc -p .",
9
+ "prepare": "npm run build"
10
+ },
11
+ "author": "WWA Wing Team",
12
+ "license": "MIT",
13
+ "devDependencies": {
14
+ "typescript": "^4.2.4"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "gitHead": "f27dbc4de044cc28ab944997ea1c3361e94228cc"
20
+ }
@@ -0,0 +1,326 @@
1
+ export enum VirtualPadButtonCode {
2
+ BUTTON_ENTER,
3
+ BUTTON_ESC,
4
+ BUTTON_SIDEBAR,
5
+ BUTTON_ESTIMATE,
6
+ BUTTON_FAST,
7
+ BUTTON_SLOW,
8
+ BUTTON_LEFT,
9
+ BUTTON_UP,
10
+ BUTTON_RIGHT,
11
+ BUTTON_DOWN
12
+ }
13
+
14
+ /**
15
+ * NONE: ボタンに一切触れていません
16
+ * TOUCH: ボタンに触れ始めました
17
+ * TOUCHING: ボタンに触れています
18
+ * LEAVE: ボタンから離れました
19
+ */
20
+ export enum VirtualPadState {
21
+ NONE,
22
+ TOUCH,
23
+ TOUCHING,
24
+ LEAVE
25
+ }
26
+
27
+ export type VirtualPadButtons = {
28
+ [VirtualPadButtonCode.BUTTON_ENTER]: HTMLButtonElement,
29
+ [VirtualPadButtonCode.BUTTON_ESC]: HTMLButtonElement,
30
+ [VirtualPadButtonCode.BUTTON_SIDEBAR]?: HTMLButtonElement,
31
+ [VirtualPadButtonCode.BUTTON_ESTIMATE]: HTMLButtonElement,
32
+ [VirtualPadButtonCode.BUTTON_FAST]: HTMLButtonElement,
33
+ [VirtualPadButtonCode.BUTTON_SLOW]: HTMLButtonElement,
34
+ [VirtualPadButtonCode.BUTTON_LEFT]: HTMLButtonElement,
35
+ [VirtualPadButtonCode.BUTTON_UP]: HTMLButtonElement,
36
+ [VirtualPadButtonCode.BUTTON_RIGHT]: HTMLButtonElement,
37
+ [VirtualPadButtonCode.BUTTON_DOWN]: HTMLButtonElement
38
+ };
39
+
40
+ type VirtualPadButtonTouching = {
41
+ prev: boolean,
42
+ current: boolean,
43
+ next: boolean
44
+ };
45
+
46
+ type VirtualPadEventFunction = (buttonCode: VirtualPadButtonCode) => void;
47
+
48
+ const VirtualPadMoveButtonCodes = [
49
+ VirtualPadButtonCode.BUTTON_LEFT,
50
+ VirtualPadButtonCode.BUTTON_UP,
51
+ VirtualPadButtonCode.BUTTON_RIGHT,
52
+ VirtualPadButtonCode.BUTTON_DOWN
53
+ ];
54
+
55
+ /**
56
+ * 仮想パッドの状態管理を行うクラスです。
57
+ * @todo PCといった、タッチデバイスでないデバイスでは、このクラスのインスタンスを生成しないようにする。
58
+ * (this._enabled で判別しているけど、いちいち判定処理書くのつらい...)
59
+ */
60
+ export default class VirtualPadStore {
61
+
62
+ /**
63
+ * 仮想パッドが有効か
64
+ * @property
65
+ */
66
+ private _enabled: boolean;
67
+
68
+ private _onTouchStart: VirtualPadEventFunction | null;
69
+ private _onTouchEnd: VirtualPadEventFunction | null;
70
+
71
+ /**
72
+ * 有効なボタンが格納されている配列です。各ボタンを繰り返し処理する場合に使用します。
73
+ * @property
74
+ */
75
+ private _availableButtons: [VirtualPadButtonCode?];
76
+ private _isTouchingButtons: {
77
+ [key in VirtualPadButtonCode]?: VirtualPadButtonTouching
78
+ };
79
+
80
+ /**
81
+ * 移動ボタンの要素自体です。主に移動ボタンで指を動かす際に使用します。
82
+ * @property
83
+ */
84
+ private _moveButtonsElement: HTMLElement;
85
+
86
+ /**
87
+ * @param buttons 仮想パッドの各要素
88
+ * @param moveButtons 仮想パッドの移動ボタンの要素
89
+ * @param onTouchStart 仮想パッドを押下した場合に発生するコールバック関数
90
+ * @param onTouchEnd 仮想パッドを話した場合に発生するコールバック関数
91
+ */
92
+ constructor(
93
+ buttons: VirtualPadButtons | {},
94
+ moveButtons: HTMLElement = null,
95
+ onTouchStart: VirtualPadEventFunction = null,
96
+ onTouchEnd: VirtualPadEventFunction = null
97
+ ) {
98
+ this._enabled = Object.keys(buttons).length > 0;
99
+ this._onTouchStart = onTouchStart || null;
100
+ this._onTouchEnd = onTouchEnd || null;
101
+ this._availableButtons = [];
102
+ this._isTouchingButtons = {};
103
+ this._moveButtonsElement = moveButtons;
104
+
105
+ for (let buttonTypeString in buttons) {
106
+ /**
107
+ * for in ... で渡される buttonTypeString は必ず文字列型になります。
108
+ * このまま buttons の配列のキーに渡すと、正しく要素が受け取れません。
109
+ * このため、一度 parseInt で数字に変換した上で渡しています。
110
+ */
111
+ let buttonCode = parseInt(buttonTypeString);
112
+ let button: HTMLButtonElement = buttons[buttonCode];
113
+ this._availableButtons.push(buttonCode);
114
+
115
+ /**
116
+ * type 属性について
117
+ * HTML側の各仮想パッドボタンは、 type 属性を元に各ボタンを特定しています。
118
+ * 各仮想パッドボタンの種類を判別するために、初期化時に type 属性を割り振っています。
119
+ */
120
+ button.setAttribute("type", buttonTypeString);
121
+
122
+ this._isTouchingButtons[buttonCode] = {
123
+ prev: false,
124
+ current: false,
125
+ next: false
126
+ };
127
+
128
+ const cancelBrowserTouchEvent = (event: TouchEvent) => {
129
+ if (event.cancelable) {
130
+ event.preventDefault();
131
+ }
132
+ };
133
+
134
+ /**
135
+ * 何かしらの割り込み処理が発生した場合に、緊急で仮想パッドを停止する処理です。
136
+ * @param event
137
+ */
138
+ const cancelVirtualPad = (event: TouchEvent) => {
139
+ cancelBrowserTouchEvent(event);
140
+ this.allClear();
141
+ };
142
+
143
+ button.addEventListener("touchstart", (event: TouchEvent) => {
144
+ cancelBrowserTouchEvent(event);
145
+ this.setTouchInfo(buttonCode);
146
+ });
147
+
148
+ button.addEventListener("cancel", cancelVirtualPad);
149
+ button.addEventListener("touchcancel", cancelVirtualPad);
150
+
151
+ /**
152
+ * 移動ボタンに関しては、指先を移動しながら操作することがあるため、 touchmove イベントにも対応します。
153
+ */
154
+ if (VirtualPadStore.isMoveButton(buttonCode)) {
155
+ button.addEventListener("touchmove", this._detectMovingMoveButton.bind(this));
156
+ button.addEventListener("touchend", this.allMoveClear.bind(this));
157
+ } else {
158
+ button.addEventListener("touchend", (event: TouchEvent) => {
159
+ cancelBrowserTouchEvent(event);
160
+ this.clearTouchInfo(buttonCode);
161
+ });
162
+ }
163
+ }
164
+ if (moveButtons !== null) {
165
+ moveButtons.addEventListener("touchmove", this._detectMovingMoveButton.bind(this));
166
+ }
167
+ }
168
+
169
+ /**
170
+ * TouchMove した要素から触れた先の要素に、触れたことを呼び出します。
171
+ * @param event
172
+ */
173
+ private _detectMovingMoveButton(event: TouchEvent) {
174
+ event.preventDefault();
175
+ this.allMoveClear();
176
+
177
+ // 中央のポジションを取得
178
+ const moveButtonRect = this._moveButtonsElement.getBoundingClientRect();
179
+ const bodyRect = document.body.getBoundingClientRect();
180
+ const centerPositionX = moveButtonRect.left - bodyRect.left + (moveButtonRect.width / 2);
181
+ const centerPositionY = moveButtonRect.top - bodyRect.top + (moveButtonRect.height / 2);
182
+
183
+ const touch = event.targetTouches.item(0);
184
+ const touchX = touch.pageX - centerPositionX;
185
+ const touchY = touch.pageY - centerPositionY;
186
+
187
+ if (touchX >= touchY) { // 上と右
188
+ /**
189
+ * touchY をマイナスにして、グラフの空間上で擬似的に表現します。
190
+ */
191
+ if (touchX <= -touchY) { // 上
192
+ this.setTouchInfo(VirtualPadButtonCode.BUTTON_UP);
193
+ } else { // 右
194
+ this.setTouchInfo(VirtualPadButtonCode.BUTTON_RIGHT);
195
+ }
196
+ } else { // 左と下
197
+ if (touchX >= -touchY) { // 下
198
+ this.setTouchInfo(VirtualPadButtonCode.BUTTON_DOWN);
199
+ } else { // 左
200
+ this.setTouchInfo(VirtualPadButtonCode.BUTTON_LEFT);
201
+ }
202
+ }
203
+ }
204
+
205
+ /**
206
+ * 指定したボタンが押されたかを判別します。
207
+ * 戦闘予測ボタンといった、1回しか押さないボタンの判定に使用します。
208
+ * @param buttonType
209
+ */
210
+ public checkTouchButton(buttonType: VirtualPadButtonCode): boolean {
211
+ if (!this._enabled) {
212
+ return false;
213
+ }
214
+ const state = this.getButtonState(buttonType);
215
+ return state === VirtualPadState.TOUCH;
216
+ }
217
+
218
+ /**
219
+ * 指定したボタンが押されているかを判別します。
220
+ * 移動ボタンといった、長時間押すボタンの判定に使用します。
221
+ * @param buttonType
222
+ */
223
+ public checkTouchingButton(buttonType: VirtualPadButtonCode): boolean {
224
+ if (!this._enabled) {
225
+ return false;
226
+ }
227
+ const state = this.getButtonState(buttonType);
228
+ return state === VirtualPadState.TOUCH || state === VirtualPadState.TOUCHING;
229
+ }
230
+
231
+ /**
232
+ * 今の仮想パッドのボタンの状態を出力します
233
+ * @param buttonType
234
+ */
235
+ public getButtonState(buttonType: VirtualPadButtonCode): VirtualPadState {
236
+ if (!this._enabled) {
237
+ return VirtualPadState.NONE;
238
+ }
239
+
240
+ const touched = this._isTouchingButtons[buttonType].prev;
241
+ const isTouching = this._isTouchingButtons[buttonType].current;
242
+ if (touched && isTouching) {
243
+ return VirtualPadState.TOUCHING;
244
+ } else if (isTouching) {
245
+ return VirtualPadState.TOUCH;
246
+ } else if (touched) {
247
+ return VirtualPadState.LEAVE;
248
+ }
249
+ return VirtualPadState.NONE;
250
+ }
251
+
252
+ /**
253
+ * ボタンにタッチ信号を与えます
254
+ * @param buttonType
255
+ */
256
+ public setTouchInfo(buttonType: VirtualPadButtonCode) {
257
+ if (!this._enabled) {
258
+ return;
259
+ }
260
+
261
+ this._isTouchingButtons[buttonType].next = true;
262
+ }
263
+
264
+ /**
265
+ * ボタンのタッチ信号を解除します
266
+ * @param buttonType
267
+ */
268
+ public clearTouchInfo(buttonType: VirtualPadButtonCode) {
269
+ if (!this._enabled) {
270
+ return;
271
+ }
272
+
273
+ this._isTouchingButtons[buttonType].next = false;
274
+ }
275
+
276
+ /**
277
+ * すべての移動ボタンのタッチ信号をキャンセルします
278
+ */
279
+ public allMoveClear(): void {
280
+ VirtualPadMoveButtonCodes.forEach((buttonCode) => {
281
+ if (this._availableButtons.includes(buttonCode)) {
282
+ this.clearTouchInfo(buttonCode);
283
+ }
284
+ });
285
+ }
286
+
287
+ /**
288
+ * すべてのボタンのタッチ信号をキャンセルします。
289
+ */
290
+ public allClear(): void {
291
+ this._availableButtons.forEach((buttonCode) => {
292
+ this._isTouchingButtons[buttonCode].next = false;
293
+ });
294
+ }
295
+
296
+ /**
297
+ * 押したボタンが移動ボタンか判定します。
298
+ * @param buttonType
299
+ */
300
+ public static isMoveButton(buttonType: VirtualPadButtonCode): boolean {
301
+ return VirtualPadMoveButtonCodes.includes(buttonType);
302
+ }
303
+
304
+ /**
305
+ * 今の仮想パッドボタンの状態を次の状態に送ります。
306
+ */
307
+ public update() {
308
+ this._availableButtons.forEach((buttonCode) => {
309
+ let currentButtonTouching = this._isTouchingButtons[buttonCode];
310
+ this._isTouchingButtons[buttonCode].prev = currentButtonTouching.current;
311
+ this._isTouchingButtons[buttonCode].current = currentButtonTouching.next;
312
+
313
+ /**
314
+ * ボタンの状態に応じて、コールバック関数を実行
315
+ */
316
+ switch (this.getButtonState(buttonCode)) {
317
+ case VirtualPadState.TOUCH:
318
+ this._onTouchStart(buttonCode);
319
+ break;
320
+ case VirtualPadState.LEAVE:
321
+ this._onTouchEnd(buttonCode);
322
+ break;
323
+ }
324
+ });
325
+ }
326
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * 自動回転制御の初期化を行うメソッドです。
3
+ */
4
+ export function initializeRotate() {
5
+ const headElement = document.getElementsByTagName('head')[0];
6
+ let viewportElement = document.createElement('meta');
7
+
8
+ viewportElement.setAttribute('name', 'viewport');
9
+ headElement.appendChild(viewportElement);
10
+ autoRotate();
11
+ }
12
+
13
+ /**
14
+ * 回転の自動制御メソッドです。 "resize" イベントと併せてご利用ください。
15
+ * @example window.addEventListener("resize", autoRotate);
16
+ */
17
+ export default function autoRotate() {
18
+ const WWA_WIDTH = 560;
19
+ const WWA_HEIGHT = 440;
20
+
21
+ const viewportElement = document.querySelector("meta[name='viewport']");
22
+ const browserWidth = window.innerWidth;
23
+ const browserHeight = window.innerHeight;
24
+ /**
25
+ * autoRotate を有効化すると、誤動作を防ぐため、拡大操作が無効になります。
26
+ * Webページの中に設置する場合は、特にご注意ください。
27
+ */
28
+ let viewportValue = "user-scalable=no";
29
+
30
+ if (browserWidth > browserHeight) {
31
+ const width = Math.floor((browserWidth / browserHeight) * WWA_HEIGHT);
32
+ viewportValue = `width=${width},${viewportValue}`;
33
+ } else if (browserWidth <= browserHeight) {
34
+ viewportValue = `width=${WWA_WIDTH},${viewportValue}`;
35
+ }
36
+ viewportElement.setAttribute("content", `${viewportValue}`);
37
+ }
package/src/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ import VirtualPadStore, { VirtualPadState, VirtualPadButtonCode, VirtualPadButtons } from './VirtualPad';
2
+ import autoRotate, { initializeRotate } from './autoRotate';
3
+ import makeInject from './makeInject';
4
+
5
+ export {
6
+ VirtualPadStore,
7
+ VirtualPadState,
8
+ VirtualPadButtonCode,
9
+ VirtualPadButtons,
10
+ autoRotate,
11
+ initializeRotate,
12
+ makeInject
13
+ }
@@ -0,0 +1,17 @@
1
+ export default function makeInject() {
2
+ return `
3
+ <div id="wwa-virtualpad-left">
4
+ <button class="wwa-virtualpad__button" id="wwa-up-button"></button>
5
+ <button class="wwa-virtualpad__button" id="wwa-left-button"></button>
6
+ <button class="wwa-virtualpad__button" id="wwa-right-button"></button>
7
+ <button class="wwa-virtualpad__button" id="wwa-down-button"></button>
8
+ <div class="wwa-virtualpad__hole"></div>
9
+ </div>
10
+ <div id="wwa-virtualpad-right">
11
+ <button class="wwa-virtualpad__button" id="wwa-slow-button">I</button>
12
+ <button class="wwa-virtualpad__button" id="wwa-fast-button">P</button>
13
+ <button class="wwa-virtualpad__button" id="wwa-enter-button">Y</button>
14
+ <button class="wwa-virtualpad__button" id="wwa-esc-button">N</button>
15
+ <button class="wwa-virtualpad__button" id="wwa-estimate-button">M</button>
16
+ </div>`;
17
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "./src",
5
+ "outDir": "./lib",
6
+ "module": "esnext"
7
+ },
8
+ "include": [
9
+ "src/**/*.ts"
10
+ ],
11
+ "exclude": [
12
+ "node_modules"
13
+ ]
14
+ }