クリック(ホバー)させたくない要素をシールドする方法
【ネタばれ】原森サイトで使っている技を紹介します。【注意】
前置き
この記事は デザイナーさん、フロントエンドエンジニアさん、javascript でプログラム書く web プログラマさん向けに書いています。
クリック(マウスホバー)させたくない要素をシールドする、ってどういうこと?
「クリックするとその下に隠してある説明段落が表示される▼ボタン」「マウスホバーすると、プルダウンするメニュー」など、webサイトでは【クリック】や【マウスホバー】で javascript や CSSアニメなどを使っていろんな演出をしたりします。
普通は、クリックやマウスホバーをさせない、ということはあまり考えないかと思います。
ですが、例えば、javascript のプログラムでクリック後に一瞬で動作が終わらない [setInterval] [setTimeout] 等で処理が終わるまでアニメしたり、時間が必要になるモノが動いている途中に、それを動かすための操作ボタンがもう一度押されてしまうと、昔ながらの手続き関数型でも、オブジェクト指向的なタイプでも、動作途中で新たな重複するような動作がイベントとして発生してしまい、異常動作をしてしまう場合があります。
いろいろなwebシステムで、作った自分は分かっているので、普通に丁寧に動作開始ボタンをクリックしてテストするのですが、それをダブルクリックしてしまう閲覧者もいたりして、作って納品した後に異常動作する場合があることに時間が経ってから気づいてしまう、などもあるかもしれません。
ちょっとアニメさせてその終了を待っているだけなのに、javascript のプログラム中で再度クリックされた場合には…的なプログラム処理を追加して対応するのもちょっとめんどくさい。
そんな場合には、めんどくさがりプログラマ対応として、イベントリスナー登録したボタンや onclick を直接HTMLソースに記述した span ボタンの場合、『操作ボタンを一時的に消す』又は『ボタンソースを書き変えてクリックしてもイベントが発生しない別物にしてしまう』ということを動作開始時にやったりするかもしれません。
今回この記事で紹介するのは原森が昔からやっているテクニックなのですが、それはプログラム的にも超簡単なものとなります。操作ボタンを消す、というものとプログラムは同じなのですが、どうしてもそのボタンを消すことができない場合に、ボタンを押せなくする、という技になります。
原森が命名した技名としては【シールド要素でクリックを邪魔する】です。
また、シールド要素を活用したアイデアを応用して CSS だけでマウスホバーを一定時間だけ邪魔する、
という技もご紹介します。
(css3 の transition アニメが使えるようになったので思いついた技です)
実際に原森webサイトのこのページなどでも使っています。
シールド要素は、以下のようなページで使っています。
プログラム開始のボタンダブルクリックを防ぐために利用:【 WEBコラムの記事 2進数の仕様を「考え方を置き換える」ことで応用する】
別の問題解決のために組み合わせて応用:【各 javascript ツール Transition ソース作成ツール】など
テクニック『シールド』を使ってクリックやマウスホバーの邪魔をする
アイデアのネタは、『要素の上に別の要素を重ねる』ただそれだけです。
サンプルの赤色ボタンと青色ボタンは onclick で緑色のシールド要素を表示非表示する javascript が動作するボタンです。
赤色も青色も、ボタンをクリックすると、緑 div が表示されている時は非表示に、非表示の場合は表示する、という原森web専用関数を動作させています。
青色ボタンは最初は緑 div が上に乗っているので、表示されている時はクリックできません。
緑 div が非表示状態の時にクリックすると、緑 div が表示されます。
この、『シールド』と原森が勝手に名付けている要素は、
青色ボタンがそうであるように、操作ボタンをクリックした瞬間、動き出したプログラムの最初でボタンの上に表示させて、今押したボタンをクリックできないようにする、というものです。
青色ボタンも赤色と同じで、表示非表示切り替えなので、ダブルクリックできれば、緑が表示されてまた消える、という動作(2回動くだけ)になるのですが、クリックして『シールド』が表示された後は青色ボタンは押せなくなるので、表示から非表示の動作は青色ボタンではできない、ということになります。
この仕組みを別のタイマーがあるようなプログラムで使う場合は、プログラム開始時に表示させたシールド要素を、プログラム終了時に非表示にする、等の処理をすることとなります。
※プログラム的には、シールドの表示非表示は、ID 付加したシールド要素の css スタイルで display を none や block (inline-block などなど) に変更するだけの超簡単な仕様です。
原森webでの使用例1 動作中にボタンをシールドする
このテクニックで、ダブルクリックや動作中のボタンクリックを防いでいる例が、
WEBコラムの記事【 2進数の仕様を「考え方を置き換える」ことで応用する】などの記事にある
『複数ページめくり用ボタン』(先日追加しました)です。
このページは【B】【N】ボタンでページをめくりますが、ページめくり動作中は【B】や【N】を表示しないようにしています。(※ボタンを一時非表示にして対応している例)
記事ウインドウのフッター下に複数ページめくりボタンを追加して、連続でページめくり動作をする機能を追加した時に、動作中にボタンをクリックしたり、最初にダブルクリックしてしまうと、異常動作しますので、シールド要素を上に表示させてクリックできなくしています。
動作終了後はシールドを非表示にして、またボタンがクリックできるようになります。
※クリック後、動作終了までボタンをクリックしても動作させない、というのを、シールド以外で、しかもイベントが動作中かどうかを調べるなどの小難しい事をせずに、スイッチonoffで簡単に制御する方法もありますが、それはまた別の記事で紹介します。
あからさまにシールドが表示されている例は、以下になります。
css3研究の記事【 transition-timing-function をならべてみた実験】
transitionアニメ動作の秒数変更とかtransition動作中に余計なクリックを防ぐためにシールドを表示しています。
原森webでの使用例2 CSS演出でのシールドの応用
CSSでの応用です。 このページの記事ウインドウの右にあるメニュー部分にはシールド技を使っています。さて、それはどういうものでしょうか?
【原森サイトの技ネタ紹介】ページの関連記事部分【最初に作った原森サイトのベーシックなサブメニュー】では、「即スライドさせないための小技」と表現しました。(その記事中では紹介だけで、説明はしていません)
…
ウインドウ右側にマウスホバーで本文側が左にスライドして表示されるメニュー。
コンテンツ記事ボックスのスクロールバーの右側にあるMENUの緑色の縦長バーをホバーすると、本文の方が左にスライドします。
※『▲マーク』より上の、MENUのUの辺りぐらいまでは即スライド。
※『▲マーク』から下部分はスクロールバー操作時にずれた時にすぐスライドしないようにこっそり「即スライドさせないための小技」を使ってます。
…
『▲マーク』より上の、MENUのUの辺りぐらいまでは即スライド。これは、右にある縦のメニューブロックにマウスホバーすれば、本文記事部分が左にスライドしてメニューが見えるようになる、というのを CSS の hover と transition を使って演出しています。
ですが、マウスホバーで即スライドの問題点として、
右にあるスクロールバーをドラッグして記事をスクロールしようとした時や、本文へマウスを移動させている時に、マウスが乗ってしまうごとにびこびこ(擬音)とアニメ動作してしまってかなりうっとおしい、ということになってしまうかと思います。
※スクロールバーの上の方でスクロールさせようとして、マウスをちょっと乗せてみると、スクロールバーが左に逃げてしまい、うっとおしさが体感できるかと思います。
対策として、最初はシールドを使って即スライドさせないようにしていました。 そのうち、即スライドできる部分も必要かもしれない、などと思い、結果、シールドの高さを下から▲マークあたりまでにするようにしています。
…ちょっと待った、シールド要素が上にあったら、クリックも、マウスホバーも邪魔するんじゃなかったの?
「ほばーでけへんやん(関西弁)」「hover できないじゃん?(関東弁)」…などとちゃんと記事を読んで理解してくれた方は突っ込んでしまうかもしれません。
そこで CSS での応用として原森がコッソリと、この辺境のwebサイトでご提案するテクニックが『シールドをマウスホバーして少し秒数が経過したら、シールドを動かしてのけてしまう』という技になります。
要するに、シールドにも transition と hover 時の top left right bottom や transform : translateX などを指定して、アニメさせ、移動させてしまう、ということです。
このページの仕様では、シールドの上にマウスがのって、しばらく(0.8s)我慢していると、シールドが右にスライド(right:-100px;)していなくなり、下にあるメニューがマウスホバーできるようになる、というふうに作っています。
これが、シールド要素とcss アニメを組み合わせた『即スライドさせないための小技』です。
シールドからhoverが外れたら、シールドは delay秒数 0.8s だけ我慢してから元の位置に戻ろうとするはずですが、即スライドしようとするメニュー部分のホバーが有効となり、そのメニューホバーでもシールドさんの位置変更を指定してあるので、シールドさんは右にスライド(right:-100px;)させられたままになってしまうのです。
スライドするシールドの模型サンプル
模型サンプルでは、青色が見えている右メニュー上部にマウスホバーで記事ブロックが左にスライドして薄くなり、シールド要素(盾と書いてある薄緑色div)も0.5s待機してから右にスライドしながら赤色になります。
シールド要素(盾)にマウスホバーすると、0.5s後にシールドが右にスライドします。こちらは色変化なしです。
シールドが右にスライドした後は、マウスが右メニューにホバーした状態になりますが、シールドはすでに右スライドしているので、色だけ遅れて赤色に変化します。
CSSの transition transform animation は研究して実験して使ってみると、いろいろな演出アイデアが発見できるかもしれない、などと原森は思ったりします。
原森webでの使用例3 別のjsプログラム中の問題解決で利用
ある問題点を解決するために、シールド要素を使っている部分は、 【各 javascript ツール Transition ソース作成ツール】などにあります。
ドラッグ移動時の問題点
ある問題点とは、下記記事ページに書いたものです。
原森サイトの技ネタ紹介「サブウインドウの移動」の「ポップアップブロックのドラッグ移動の問題点」
…
ポップアップのドラッグ移動の問題点について、やはりもったいぶらずに書いておきます。
それはポップアップブロックをドラッグすると、ポップアップを移動している間に、その下にある記事テキストをマウスドラッグで選択状態にしてしまう、という点です。
…
というものです。
紹介しようとしている解決方法はこの記事をここまで読まれた方には分かるかと思います。
【サブウインドウ(※クリック)】でテスト
※このページではシールド要素を半透明の赤色にしています。
全画面のシールド要素をページの Z軸方向の一番前に表示させて、マウスドラッグにより記事が選択状態にならないようにする、という方法です。
プログラム的には、ドラッグしたい要素をマウスでクリックした瞬間に、全画面のシールド要素を表示させて、一番上にいるマウスカーソルが他の要素のテキストなどをドラッグできないようにシールドしてしまう、マウスが離れた時にはシールドを非表示にする、という方法になります。
原森webでは [移] (移動ボタン)のドラッグでサブウインドウを移動させていますので、最初は [本文記事] → [サブウインドウ] → [シールド] → [移動ボタン]のようにしようとしてましたが、移動ボタンの「移」という文字もドラッグで選択してしまうので、[本文記事] → [サブウインドウ] → [移動ボタン] → [シールド] の並びにして実験してみると、後から シールドの z-index を大きくして手前に出しても、マウスドラッグ状態は外れなかったので、その形で使っています。
クリックとドラッグの違いについて
onclick は、マウスを [押して、放す] で初めて onclick という動作になる(上記の赤色・青色ボタン参照)ので、マウスをクリック(押して、放す )後にシールドが出てボタンが押せなくなりますが、マウスドラッグの場合、イベントリスナー登録時に [mousedown] [mousemove] [mouseup] などでサブウインドウを動かすという動作を作る時に、[mousedown] でシールドを表示させると、mousedownしたまま [mouseup] するまで、[mousemove]できる
つまり、シールドが出てもマウスを押した状態が外れない、というのが実験で判明したので使っています。
※ z-index は数値指定すると、ローカルな重ね合わせコンテキストが作られてしまうので、z-index を指定した親の子供どうしでないと、z-index で前後配置ができないので、原森サイトの場合、動かしたいサブウインドウに移動ボタンを乗せて、全画面のシールドを間に挟む、というのが面倒だった点と、移動ボタンを上に表示した場合に、[移]がテキストなので、やはりドラッグしていると、その文字がテキスト選択状態になってしまう場合がありましたので、いろいろ実験し、 本文記事 → フローティングボックス → シールド要素 → マウスという順になっていれば、文字を選択状態にせずにドラッグできるものが作れたので、それを使っている、ということだったりします。
まとめ
ということで、今回記事では、仕事としてwebサイトをいろいろ作っていると、両方対応しなくてはいけなかった IE や NN(昔話です)の仕様違いで、IE(NN)の時だけなんらかの透明な要素が邪魔して上に乗っかってしまっていて、リンクがクリックできない、とか、ボタンをホバーしたのに画像が入れ変わらない(昔はjavascriptでやってました)、といった問題が時々起こったりして、なんでやねーん、なんでやのーん、と頭を悩ませていた過去に思いついた「要素の重なり順で押せなくなるネタ」を活用して、『クリック(マウスホバー)させたくない要素をシールドする方法』としてわざと『要素の上に別の要素を重ねる』という単純なテクニックの活用について紹介しました。
特に、昔によくやっていたのは、左メニューからサブメニュー・サブサブメニューをフローティング要素として表示させる、等もjavascriptで作ってましたので、マウスホバー(onMouseOver)したら表示、マウスアウト(onMouseOut)したら元に戻す…等を作ったりした時、メニューホバー後にサブメニュー表示。サブメニューホバーでサブサブを表示。
だけど、サブメニューにマウス乗せたら親の方はホバーが(onMouseOut)外れてるよね…消えちゃうよね、どうするのこれ…などとなり、では、マウスが外れたというのを、別の要素にホバーしたらメニューの方は外れたことにしよう、というようなことをやってました。
今回のネタで言えば、メニュー要素の下に透明なシールドが表示されていて、それ(メニューの外)をホバーするまではメニューを表示しっぱなしにする、そんな感じの作り方をして活用したりしてました。
(昔のjavascript tips 的なテクニックです)
つまり、透明にしていて見えないけど、シールド要素はクリックやマウスドラッグ選択を邪魔するだけじゃなくて、何らかのjavascriptを動作させるための【透明スイッチ】としても使える、と言うことです。
透明ではないけれど、今使われているものならば、いつのまにか画像もアップできるようになっている twitter や google の画像検索の詳細ウインドウ、他にはブログの拡大画像などを全画面で表示したりするようなもので、画像や詳細ボックスの外をクリックすれば、元の記事状態に戻る(拡大画像表示を消す)、というものも、この『シールド要素』(透明スイッチ)のクリック技で作れると思います。
オマエハナニヲイッテルンダ、とミルコさんに言われてしまいそうな『要素の上に別の要素を重ねる』というものも、活用ネタを知っておくと、何らかのアイデアと結び付けてもっと面白い使い方をしてもらえるのではないかと思い、紹介してみました。
【シールド要素】とか【透明スイッチ】などは原森が勝手に名付けているだけなので、
webネタとしてその単語を使っても誰にも通じないのでご注意ください。
ちなみに、【透明スイッチ】について、その活用方法を記事にする予定です。
以上、長い記事を最後まで読まれたみなさん、お疲れさまでした。
ページトップへ