基本の表示と簡単なファイル構成が整ってきたので、次は数値の入力を搭載したいと思います。
通常数値の入力は、inputタグでキーボード入力する方式ですが、数独アプリなどを使ってみると、1~9の数字ボタンが表示されてそれをクリックするのが定番になっているようです。
個人的に入力するマスを選択して、数値ボタンをさらにクリックする2回の手間が、少し操作がしずらいと思ったので、今回は1回のクリック(タップ)とそのままドラッグして数値入力をする操作方法を搭載してみようと思います。
変更するソースコード
[更新] main.js
import { View } from './js/view.js'
import { Input } from './js/input.js'
export const Main = {
stage_id : 'NumberPlace',
}
function init(){
Main.view = new View()
Main.input = new Input()
}
switch(document.readyState){
case 'complete':
case 'interactive':
init()
break
default:
window.addEventListener('DOMContetLoaded' , init)
break
}
[新規] js/input.js
import { Main } from '../main.js'
export class Input{
constructor(){
this.set_event()
}
get table(){
return document.getElementById(Main.stage_id)
}
get next_num(){
if(!this.data){return null}
const next_num = this.data.num + 1
return next_num > 9 ? 0 : next_num
}
get interval(){
return 10
}
set_event(){
if(typeof window.ontouchstart !== 'undefined'){
this.table.addEventListener('touchstart' , this.touchstart.bind(this))
this.table.addEventListener('touchmove' , this.touchmove.bind(this))
this.table.addEventListener('touchend' , this.mouseup.bind(this))
}
else{
this.table.addEventListener('mousedown' , this.mousedown.bind(this))
this.table.addEventListener('mousemove' , this.mousemove.bind(this))
this.table.addEventListener('mouseup' , this.mouseup.bind(this))
}
}
touchstart(e){
this.mousedown(e.touches[0])
}
touchmove(e){
e.preventDefault()
this.mousemove(e.touches[0])
}
mousedown(e){
const cell = e.target.closest('td')
if(!cell){return}
this.data = {
cell : cell,
num : Number(cell.textContent || 0),
pos : {
x : e.pageX,
y : e.pageY,
},
}
}
mousemove(e){
if(!this.data){return}
const size = Math.abs(e.pageX - this.data.pos.x)
if(size < this.interval){return}
const num = this.pos2num(size)
this.data.cell.textContent = num || ''
this.data.num = num
this.data.move_flg = true
}
mouseup(e){
if(!this.data){return}
if(!this.data.move_flg){
this.data.num = this.next_num
}
this.data.cell.textContent = this.data.num
delete this.data
}
// 移動距離を0~9の数値に変換する
pos2num(pos){
const num = ~~(pos / this.interval)
return num > 9 ? num % 10 : num
}
}
デモ
マス目をクリックすると、数字がインクリメントされていきます。
他にも、マス目をマウスクリックか、スマホタッチで押した状態で左右に動かしてみて下さい。
数値が切り替わるのが確認できればOKです。
※うまく動かない場合は、ご連絡ください。
解説とポイント
数値入力をドラッグイベントでやるという、あまり他にない入力方法にした理由としては、
個人的な実験的な要素が強いのですが、やってみたところ、意外と違和感が無いことに気が付きました。
(人によって間隔が違うと思いますが・・・)
イベント6種
そして、今回のプログラムでは、tableタグ(またはその上位のタグ)に対して、以下の6個のイベントをセットしています。
mousedown , mousemove , mouseup, touchstart , touchmove , touchend
mouse(マウス)系とtouch(タッチ)系の2種類は、パソコン用とスマホ用という意味で分けています。
その中に、さらに3種類あるのは、
mousedownとtouchstartは、ほぼ同じ意味で、クリック、タッチした瞬間で押している状態の時のイベントで、一連の動作の開始処理です。
mousemoveとtouchmoveは、押している状態で、マウスや指を動かした情報が取得でき、数値の入れ替え処理をしています。
mouseupとtouchendは、上記イベントの終了処理です。
ドラッグ移動などでも使える便利ワザ
今回の、クリック(タッチ)して、それを動かして、マウス(指)を話す、この一連の動作をコントロールすると、
表示されているアイコンや画像などの要素を、ドラッグして、動かすというような、インタラクティブな操作が、通常のホームページでもできてしまいます。
この操作は、ゲームを作る時に非常に有効なので、使い慣れておいたほうが良いですね。
ということで、今回のサンプルコードを自分なりに変更して使って、イジり倒してください。
一連イベント操作のポイント
まず、クリックした状態の時に、その一連の情報を変数に格納します。
この変数がない状態で、移動イベントや終了イベントは動作しないようにしています。
ちなみに、クリックしたイベントで送られてくる変数の中の、targetプロパティにクリックされたタグが格納されているので、
closest関数を使って、tdタグに置き換えて、cellという変数名を確定しています。
この時に、クリックされた座標を取得しておいて、次のmoveイベントで、座標の値の誤差を計算して、その誤差値によって、入力する数値を取得しています。
今回は、intervalという格納値で10px毎に数値が変わるようにしているので、10px左右に動けば、数値は1、20px左右に動けば2、という感じです。
これで1-9とブランクを順番に表示しているという仕様です。
最後に、終了処理として、クリックの時に格納した変数を削除しています。
タッチイベントのクセ
スマホのタッチイベントは、2本指や3本指などに対応できるように、タッチされた情報が複数送られてきます。
マウスクリックは、単一の情報に対して、タッチの場合は、配列で送られてくるという状態ですね。
今回の処理では、配列の最初の情報のみを取得するようにしていて、そのままマウス操作と同じ関数で処理をさせています。
なので、2本指で操作をしても、まるで動かないイベント処理になっています。
スマホ限定でアプリを作る場合などは、複数ある情報を使って、2本指操作や3本指操作などを搭載すると、便利な操作感覚になると思います。
あとがき
今回作った数値入力操作は、ナンプレでのゲーム操作感そのものになるため、非常に重要な機能であるとも考えられます。
いろいろな人が操作をする時に、誰もが受け入れやすい操作にするというのは非常に重要です。
今回はそうではないですが、他のアプリやゲームでやっている操作を真似するというのも、操作重視で考えるとユーザーライクであると考えられます。
今後、独自のゲームを作りたいと考えている人は、是非いろいろな操作方式を自分で構築して、独自の操作理論を育ててみてはいかがでしょうか?
0 件のコメント:
コメントを投稿