しぃぶろぐ。

仕事とか技術関係のこと。

マウスオーバーしたまま数秒後になんらかの処理をしたい

あけてます。

今年もよろしくお願いいたします。

今月中にはvue.js+d3.jsをまとめたいのですが、できるかどうかは私のやる気にかかっています。

(この時点で無理な気がする……)

マウスオーバーN秒後に処理を発火させたい

まぁ、昔からよくありますよね、こういう実装。

今回の要件は以下。

  • 要素マウスオーバーしたらサーバーと通信してメッセージ持ってきてツールチップとして表示したい。
  • でもマウスオーバーする度に通信してらんない。→からN秒静止したら取ってきて。
  • メッセージはすぐに変わっちゃうから都度取りたい(埋め込んでられない)。
  • Vue.jsね(はーと)
  • 一応タブレットとかスマホとかのタッチデバイスでも出るようにしてね。

問題点

N秒後に発火はいいんだけど、N秒以内にカーソル外れたら処理を中断しないといけない。

とりあえずgoogle先生に聞いてみる。

先生が教えてくれた結果

先生いろんな方法教えてくれたけど、結局使えたのは以下の方法。

// setTimeoutを宣言しておく(例は1秒後)
let sampleTimer = setTImeout(function(){
 // N秒後に処理したい内容
},1000);

//マウスが離れた時に以下の処理
clearTimeout( sampleTimer );

Vue.jsのv-onには mouseover(マウスがのっかったときに発火)と mouseleave(マウスが離れたときに発火)があるので、これでいけそう。

と思ったら。

スコープ違うからmouseleaveのメソッド内でmouseoverで宣言したsetTimeoutをリセットできない(´・ω・`)

そんならグローバルにしてやんよ!

というわけでグローバルで宣言しちゃいました(てへ

知識がない故の苦肉の策なので真似しないほうが多分よいと思います。

// グローバル(Vueの範囲外)で中身空っぽで宣言
var sampleSetTimeout = setTimeout(function(){},1000);

// 親Vueに通信するメソッドを用意(以下全体的にすごい略してるので適宜補ってください)
let vue = new Vue({
    data:{},
    methods:{
         getMessage:function(){
            return new Promise(function(resolve,reject){
                //なんかサーバーと通信してメッセージ持ってくる処理
            });
         },
    },
});

// コンポーネントのメソッドにmouseover時とmouseleave時の処理をそれぞれ用意
Vue.component("sample-component",{
    methods:{
        mouseOn:function(){
            // mouseover時に呼び出されるメソッド。
            // mouseleaveの反応が悪いので、ここでもクリアしちゃう。
            clearTimeout( sampleSetTimeout );
            // なんかいろいろ必要なら処理する
            sampleSetTimeout = setTimeout(function(){
                // ここでN秒後に発火させたい処理
                vue.getMessage()
                    .then(function(message){
                        //メッセージをツールチップで表示させる(略)
                    });
            },1000);
        },
        mouseLeave:function(){
            // mouseleave 時に呼び出されるメソッド
            clearTimeout( sampleSetTimeout );
            sampleSetTimeout = setTimeout(function(){},1000);
            // あと、ツールチップを消す処理
        },
});

ちなみに

マウスオーバーイベントって、タブレットだとロングタップで発火するんですね。知らんかった。。。