JavaScriptはマウスで要素の実例コードをドラッグすることを実現します。


はじめに
最初にマウスドラッグを実現する目的は、一つのページで多くの小さな丸い点をドラッグし、固定位置に使用し、そしてHTMLをコピーして、ページの開発コードに貼り付けるという機能です。何度も実現しましたが、全部できませんでした。どうしてもjQuery.fn.draggableプラグインを採用しました。今日はついにこのドラッグ機能を完璧にしました。以下はその実現を見にきます。
 二、設計の考え方
ドラッグ要素上でマウスをバインドしてイベントを押して、ドキュメントオブジェクト内でマウスをバインドして移動し、マウスがイベントを起こします。なぜ三つのイベントをドラッグ要素に結合しないのですか?マウスの移動が速すぎると、マウスの移動とポップアップイベントの処理が実行されなくなります。

$target.bind('mousedown', fn);

$(document)
.bind('mousemove', fn)
.bind('mouseup', fn);

三、ソース実現の詳細
ソースの実現には多くの注意すべき点があります。
1、まずマウスでイベントを押します。ドラッグをクリックすると、領域のテキストを選択するかもしれません。これは私達が必要とするものではありません。解決方法は以下の通りです。

// for chrome firefox ie9
e.preventDefault();
// for firefox ie9 || less than ie9
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
2、ドラッグ要素が画像(imgタグ)である場合、マウスがドラッグした画像の距離が短いと、禁止されている小さなヒントが表示されます。つまり、画像はもうドラッグできません。これはブラウザのデフォルト行動です。ブラウザのデフォルト行動を阻止すればいいです。

e.preventDefault();
3、境界(ドラッグ範囲の処理)に関する問題
最初に実現したコードは以下の通りです。

// x,y left,top ,limitObj , ,
// ,

if ( x >= limitObj._left && x <= limitObj._right ) {
    $target.css({ left: x + 'px' });
}
if ( y >= limitObj._top && y <= limitObj._bottom ) {
    $target.css({ top: y + 'px' });
}

さらに、なぜ上記の問題が発生したのかというと、変数xがlimitObj._より小さい可能性があるからです。leftまたはlimitObj.uより大きいナイト、変数yは同じですので、コードは下記のように処理します。

if (x < limitObj._left) {
    x = limitObj._left;
}
if (x > limitObj._right) {
    x = limitObj._right;
}
if (y < limitObj._top) {
    y = limitObj._top;
}
if (y > limitObj._bottom) {
    y = limitObj._bottom;
}
$target.css({ left: x + 'px', top: y + 'px' });
この問題を解決しましたが、cloudgamerはより良い書き方を示しました。

$target.css({
    left: Math.max( Math.min(x, limitObj._right),  limitObj._left) + 'px',
    top: Math.max( Math.min(y, limitObj._bottom),  limitObj._top) + 'px'
});
完全プログラムのソースコード:

$.fn.extend({
    /**
     *   Autor: yjh 2014/02/21
     */
    drag: function(options) {
        var dragStart, dragMove, dragEnd,
            $boundaryElem, limitObj;

        function _initOptions() {
            var noop = function(){}, defaultOptions;

            defaultOptions = { //
                boundaryElem: 'body' //
            };
            options = $.extend( defaultOptions, options || {} );
            $boundaryElem = $(options.boundaryElem);

            dragStart = options.dragStart || noop,
            dragMove = options.dragMove || noop,
            dragEnd = options.dragEnd || noop;
        }

        function _drag(e) {
            var clientX, clientY, offsetLeft, offsetTop,
                $target = $(this), self = this;

            limitObj = {
                _left: 0,
                _top: 0,
                _right: ($boundaryElem.innerWidth() || $(window).width()) - $target.outerWidth(),
                _bottom: ($boundaryElem.innerHeight() || $(window).height()) - $target.outerHeight()
            };

            //
            clientX = e.clientX;
            clientY = e.clientY;
            offsetLeft = this.offsetLeft;
            offsetTop = this.offsetTop;

            dragStart.apply(this, arguments);
            $(document).bind('mousemove', moveHandle)
                        .bind('mouseup', upHandle);

            //
            function moveHandle(e) {
                var x = e.clientX - clientX + offsetLeft;
                var y = e.clientY - clientY + offsetTop;

                $target.css({
                    left: Math.max( Math.min(x, limitObj._right),  limitObj._left) + 'px',
                    top: Math.max( Math.min(y, limitObj._bottom),  limitObj._top) + 'px'
                });

                dragMove.apply(self, arguments);
                // ( , , : )
                e.preventDefault();
            }

            //
            function upHandle(e) {
                $(document).unbind('mousemove', moveHandle);
                dragEnd.apply(self, arguments);
            }
        }

        _initOptions(); //

        $(this)
        .css({ position: 'absolute' })
        .each(function(){
            $(this).bind('mousedown', function(e){
                _drag.apply(this, [e]);
                // for chrome firefox ie9
                e.preventDefault();
                // for firefox ie9 || less than ie9
                window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
            });
        });
        return this;
    }
});

インスタンスコール:

//
(function(){
    $('.drag-elem').drag({
        boundaryElem: '#boundary',
        dragStart: function(){
            $(this).html('<span> </span>').css({ zIndex: 2 }).siblings().css({ zIndex: 1 });
        },
        dragMove: function(){
            var pos = $(this).position();
            $(this).html('<span> (' +  pos.left + ',' + pos.top + ')</span>' );
        },
        dragEnd : function(){
            $(this).html('<span> </span>');           
        }
    });
}());