はじめに
スマホゲームやSwitchなどのゲームのUIでよく見る、「長押しボタン」をWEB画面で実装します。
使う技術としては、HTML、CSS、JavaScriptだけで、JavaScriptのライブラリや画像やSVGは使いません。
長押しボタンと言ってもイメージが付かないと思いますので、完成系のGifを用意しました。(なぜか、WEBではあまり見かけないUIですよね...)
実装
1. メータ部分の作成
まずは、メータ部分を作成するのですが、divタグ
を使って円を作成します。
background-image
にconic-gradient
を指定して、円グラフのような見た目ができるスタイルを使っています。
<div id="outer_circle"></div>
#outer_circle {
position: relative;
margin-right: auto;
margin-left: auto;
width: 100px;
height: 100px;
border-radius: 50%;
background-image: conic-gradient(#d5525f 0% 0%, #d9d9d9 0% 100%);
}
conic-gradient
の第二引数または第三引数の割合を増やしていくと、以下のような動きになります。(今回はJavaScript側で動きを制御したいので、CSSのアニメーションは使いません)
2. ボタン部分の見た目を作成
次は、ボタン部分の見た目を完成させます。
先ほど作成した、outer_circle
のdivタグ
でinner_circle
を作成し、中に少し小さい円を作成します。
<div id="outer_circle">
<div id="inner_circle"></div>
</div>
#inner_circle {
text-align: center;
background-color: #676767;
width: 80px;
height: 80px;
border-radius: 50%;
position: relative;
top: 10px;
left: 10px;
}
見た目はこれで完成になります。まだ、JavaScript部分を作っていないのでクリックしても動作しませんが、疑似的に動かすと以下のような感じになります。
3. 長押しの処理を実装
次にボタンの長押し時の処理をJavascriptで実装します。
longPress
のオブジェクトを作成し状態を管理しており、長押し中にconic-gradient
の割合を計算し画面に随時反映しています。
(下記処理は、画面読み込み後に実行されるようにする必要があります)
const longPress = {
// プロパティ
innerEl: document.getElementById("inner_circle"), //内側の円
outerEl: document.getElementById("outer_circle"), //外側の円
second: 3, //長押しの時間
count: 0,
timerId: 0,
interval: 10,
// 初期化処理
init: function(param){
// イベントリスナー
this.innerEl.addEventListener('pointerdown', ()=>{this.start()}, false);
this.innerEl.addEventListener('pointerup', ()=>{this.end()}, false);
},
// 長押し中の処理
start: function(){
this.timerId = setInterval(()=>{
this.count++;
this.outerEl.style.backgroundImage = 'conic-gradient(#d5525f 0% '+ this.count/this.second +'%, #d9d9d9 0% 100%)';
if (this.count / 100 === this.second) {
alert('ボタンを' + this.second + '秒長押ししました!');
this.end();
}
}, this.interval);
},
// 長押し中断の処理
end: function(){
clearInterval(this.timerId);
this.count = 0;
this.outerEl.style.backgroundImage = 'conic-gradient(#ff0019 0% 0%, #d9d9d9 0% 100%)';
}
};
//longPressの初期化
longPress.init();
実際に長押し操作を行うと以下のような動作になります。
4. バグについて
実は、上記コードだと考慮していない操作があり、長押しメーターが止まらないというバグがあります。バグが発生する操作としては以下の通りです。
- 長押し中に右クリック
- 長押し中にマウスのポインタが外れる
init
メソッド内に下記の処理を追記することで解消されます。
this.innerEl.addEventListener('pointerout', ()=>{ this.end() }, false);
this.innerEl.oncontextmenu = () => {return false;}
おわりに
長押しのボタンをHTML・CSS・JavaScriptで実装してみました。
今回は、円グラフのようなUIで作成しましたが、カスタマイズすることで棒グラフが伸びていくUIや水が溜まっていくようなUIにすることも可能かと思います。
また、longPressのオブジェクトを使って長押しメーターの色やタイマーの時間や長押しし終わったときにコールバック関数を使って特定の処理を実行することも可能です。下記リンクが、パラメータを色々とカスタマイズできるようにしたサンプルです。(気になった方は、ぜひ触ってみてください)
ここまで見ていただきありがとうございました。