JDBな人生  専門的なことから日常的なことまで~ まぁ自由きままに書いていきます。
2017年04月 / 03月<< 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 >>05月

アクセスランキング

[ジャンルランキング]
コンピュータ
356位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
34位
アクセスランキングを見る>>

【改訂版】JSでドラッグ&ドロップを実装する(スマホ対応)

最近、久々にWEB関連の開発を少々やっています。今日は主にクライアントサイドのコーディングをしました。
さて、3年近く前に、DOM要素のドラッグ&ドロップのコードを紹介しましたが、わかりにくく、スマホにも対応していなかったので、書きなおしてみました。

参考:
要素のドラッグ(IE,FF,GC対応) - JDBな人生
http://jabnz.blog69.fc2.com/blog-entry-735.html

今回は、「初期化」「移動量の取得」「設定値の計算」「代入」等の処理を、それぞれはっきりと分けて書いてみました。
また、オブジェクト型を使ったクラス実装も使っています。

var DDHandler = (function(){
    var that = {};
    
    /* イベント情報からマウスポインタの座標を取得 */
    var getMousePosition = function(e){
        // 座標値取得のクロスブラウザ対応
        if (e) return [e.pageX, e.pageY];
            else if(window.event) return [event.clientX, event.clientY];
    }
    
    /* スタイル値(文字列)から数値を取得 */
    var getPixelValue = function(str){
        if (str && str.match(/^\d{1,}(\.\d{1,})*px$/)) return Number(str.replace(/px/g, ""));
            else return 0;
    }
    
    /* オブジェクトを引数の値分移動する */
    var moveElement = function(target, dx, dy){
        var obj = {}, l, r, t, b;
        if (document.defaultView && document.defaultView.getComputedStyle){
            obj = document.defaultView.getComputedStyle(target, "");
        } else if (target.currentStyle) {
            obj = target.currentStyle;
        }
        l = obj.left, r = obj.right, t = obj.top, b = obj.bottom;
        
        if (l + "" == "auto") target.style.right = (getPixelValue(r) - dx) + "px";
            else target.style.left = (getPixelValue(l) + dx) + "px";
        if (t + "" == "auto") target.style.bottom = (getPixelValue(b) - dy) + "px";
            else target.style.top = (getPixelValue(t) + dy) + "px";
    }
    
    /* オブジェクトへのハンドラの設定 */
    var setDragAndDropListener = function(target, handle){
        if (typeof target.draggable != "undefined") target.draggable = false; // ブラウザ実装のドラッグを禁止
        if (typeof target.unselectable != "undefined") target.unselectable = true; // 選択禁止
        if (typeof handle == "undefined") handle = target; // 掴む部分を指定していない場合全体とする
        
        var type = null;
        var regExp = null;
        var op = [];
        var start = function(e){
            if (type != null) return;
            if (e && e.type.match(/touch/g))
                type = "touch";
            else
                type = "mouse";
            if (e && e.targetTouches) e = e.targetTouches[0];
            regExp = new RegExp(type, "g");
            op = getMousePosition(e);
        }
        
        var move = function(e){
            if (!type) return;
            if (e && !e.type.match(regExp)) return;
            if (e && e.targetTouches) e = e.targetTouches[0];
            var np = getMousePosition(e);
            var dx = np[0] - op[0], dy = np[1] - op[1];
            moveElement(target, dx, dy);
            op = np;
        }
        var end = function(e){
            if (!type) return;
            if (e && !e.type.match(regExp)) return;
            if (e && e.targetTouches) e = e.targetTouches[0];
            var np = getMousePosition(e);
            var dx = np[0] - op[0], dy = np[1] - op[1];
            moveElement(target, dx, dy);
            type = null;
        }
        
        if (document.addEventListener) {
            document.addEventListener("mouseup", end, false);
            document.addEventListener("touchmove", function(event){
                if (type == "touch") event.preventDefault();
                return false;
            }, false);
        } else {
            document.attachEvent("onmouseup", end)
        }
        
        // addEventListenerはイベントの伝播の処理が面倒なのでここでは直接代入
        handle.onmousedown = start;
        handle.onmousemove = move;
        handle.onmouseup = end;
        
        handle.ontouchstart = start;
        handle.ontouchmove = move;
        handle.ontouchend = end;
        
        /* 選択処理への対策 */
        handle.onselectstart = function() {
            return false;
        }
    }
    that.setDragAndDropListener = setDragAndDropListener;
    
    return that;
})();



使用法は、display: absolute;(fixed)な要素のインスタンスを取得して、DDHandlersetDragAndDropListener(対象オブジェクト);と実行するのみです。
サンプルもおいておきます。

要素ドラッグサンプル
141230.html


可読性や構造の簡潔さはだいぶ向上しているように思えます。(やっていることは同じですが)

過去に書いたコードと、現在書けるコードを見比べてみるのもなかなか面白いですね。
 


 
   JavaScript    TB(0)    CM(0)    EDIT    ページ↑

コメント投稿


 管理者だけに表示

コメント

トラックバック

この記事へのトラックバック:

プロフィール

JDB Luigi

Author:JDB Luigi
どこにでもいるようなありふれた人間・・・という訳でもなく、かと言って怪しい宗教を信仰する変人という訳でも無い。

基本的に掲載しているコード等は煮ていただいても焼いていただいても結構ですが、利用は自己責任にてお願いいします。
また、バグ・アドバイス等もしあればよろしくお願いします。