タイトルにあるように、jQuery UIを使用せずにdivをドラッグ可能にしようとしています。
しかし、私は以下のコードにこだわっています。コンテナdiv(divのドラッグ先)に対するマウスの位置を使用し、それらの値に関連するdivオフセットを設定することを理解しています。
方法がわかりません。手がかりはありますか?
このコードは(もちろん)動作しません:
var X, Y;
$(this).mousedown(function() {
$(this).offset({
left: X,
top: Y
});
});
$("#containerDiv").mousemove(function(event) {
X = event.pageX;
Y = event.pageY;
});
以下にreally簡単な例を示します。
$(document).ready(function() {
var $dragging = null;
$(document.body).on("mousemove", function(e) {
if ($dragging) {
$dragging.offset({
top: e.pageY,
left: e.pageX
});
}
});
$(document.body).on("mousedown", "div", function (e) {
$dragging = $(e.target);
});
$(document.body).on("mouseup", function (e) {
$dragging = null;
});
});
コンテナdiv(divのドラッグ先)に対するマウスの位置を使用し、それらの値に関連するdivオフセットを設定することを理解しています。
それについてはよくわかりません。ドラッグアンドドロップでは、alwaysがドキュメントに対する要素のオフセットを使用したいと思うようです。
特定の領域へのドラッグを制限したい場合、それはより複雑な問題です(それでも実行可能です)。
別の更新されたコードは次のとおりです。
$(document).ready(function() {
var $dragging = null;
$('body').on("mousedown", "div", function(e) {
$(this).attr('unselectable', 'on').addClass('draggable');
var el_w = $('.draggable').outerWidth(),
el_h = $('.draggable').outerHeight();
$('body').on("mousemove", function(e) {
if ($dragging) {
$dragging.offset({
top: e.pageY - el_h / 2,
left: e.pageX - el_w / 2
});
}
});
$dragging = $(e.target);
}).on("mouseup", ".draggable", function(e) {
$dragging = null;
$(this).removeAttr('unselectable').removeClass('draggable');
});
});
デモ:http://jsfiddle.net/tovic/Jge9z/31/
このスレッドに簡単なプラグインを作成しました。
// Simple JQuery Draggable Plugin
// https://plus.google.com/108949996304093815163/about
// Usage: $(selector).drags();
// Options:
// handle => your dragging handle.
// If not defined, then the whole body of the
// selected element will be draggable
// cursor => define your draggable element cursor type
// draggableClass => define the draggable class
// activeHandleClass => define the active handle class
//
// Update: 26 February 2013
// 1. Move the `z-index` manipulation from the plugin to CSS declaration
// 2. Fix the laggy effect, because at the first time I made this plugin,
// I just use the `draggable` class that's added to the element
// when the element is clicked to select the current draggable element. (Sorry about my bad English!)
// 3. Move the `draggable` and `active-handle` class as a part of the plugin option
// Next update?? NEVER!!! Should create a similar plugin that is not called `simple`!
(function($) {
$.fn.drags = function(opt) {
opt = $.extend({
handle: "",
cursor: "move",
draggableClass: "draggable",
activeHandleClass: "active-handle"
}, opt);
var $selected = null;
var $elements = (opt.handle === "") ? this : this.find(opt.handle);
$elements.css('cursor', opt.cursor).on("mousedown", function(e) {
if(opt.handle === "") {
$selected = $(this);
$selected.addClass(opt.draggableClass);
} else {
$selected = $(this).parent();
$selected.addClass(opt.draggableClass).find(opt.handle).addClass(opt.activeHandleClass);
}
var drg_h = $selected.outerHeight(),
drg_w = $selected.outerWidth(),
pos_y = $selected.offset().top + drg_h - e.pageY,
pos_x = $selected.offset().left + drg_w - e.pageX;
$(document).on("mousemove", function(e) {
$selected.offset({
top: e.pageY + pos_y - drg_h,
left: e.pageX + pos_x - drg_w
});
}).on("mouseup", function() {
$(this).off("mousemove"); // Unbind events from document
if ($selected !== null) {
$selected.removeClass(opt.draggableClass);
$selected = null;
}
});
e.preventDefault(); // disable selection
}).on("mouseup", function() {
if(opt.handle === "") {
$selected.removeClass(opt.draggableClass);
} else {
$selected.removeClass(opt.draggableClass)
.find(opt.handle).removeClass(opt.activeHandleClass);
}
$selected = null;
});
return this;
};
})(jQuery);
デモ:http://tovic.github.io/dte-project/jquery-draggable/index.html
これが私の貢献です。
http://jsfiddle.net/g6m5t8co/1/
<!doctype html>
<html>
<head>
<style>
#container {
position:absolute;
background-color: blue;
}
#elem{
position: absolute;
background-color: green;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}
</style>
<script>
var mydragg = function(){
return {
move : function(divid,xpos,ypos){
divid.style.left = xpos + 'px';
divid.style.top = ypos + 'px';
},
startMoving : function(divid,container,evt){
evt = evt || window.event;
var posX = evt.clientX,
posY = evt.clientY,
divTop = divid.style.top,
divLeft = divid.style.left,
eWi = parseInt(divid.style.width),
eHe = parseInt(divid.style.height),
cWi = parseInt(document.getElementById(container).style.width),
cHe = parseInt(document.getElementById(container).style.height);
document.getElementById(container).style.cursor='move';
divTop = divTop.replace('px','');
divLeft = divLeft.replace('px','');
var diffX = posX - divLeft,
diffY = posY - divTop;
document.onmousemove = function(evt){
evt = evt || window.event;
var posX = evt.clientX,
posY = evt.clientY,
aX = posX - diffX,
aY = posY - diffY;
if (aX < 0) aX = 0;
if (aY < 0) aY = 0;
if (aX + eWi > cWi) aX = cWi - eWi;
if (aY + eHe > cHe) aY = cHe -eHe;
mydragg.move(divid,aX,aY);
}
},
stopMoving : function(container){
var a = document.createElement('script');
document.getElementById(container).style.cursor='default';
document.onmousemove = function(){}
},
}
}();
</script>
</head>
<body>
<div id='container' style="width: 600px;height: 400px;top:50px;left:50px;">
<div id="elem" onmousedown='mydragg.startMoving(this,"container",event);' onmouseup='mydragg.stopMoving("container");' style="width: 200px;height: 100px;">
<div style='width:100%;height:100%;padding:10px'>
<select id=test>
<option value=1>first
<option value=2>second
</select>
<INPUT TYPE=text value="123">
</div>
</div>
</div>
</body>
</html>
クリックの中心にあるドラッグ可能なオブジェクトを作成する別の方法
http://jsfiddle.net/pixelass/fDcZS/
function endMove() {
$(this).removeClass('movable');
}
function startMove() {
$('.movable').on('mousemove', function(event) {
var thisX = event.pageX - $(this).width() / 2,
thisY = event.pageY - $(this).height() / 2;
$('.movable').offset({
left: thisX,
top: thisY
});
});
}
$(document).ready(function() {
$("#containerDiv").on('mousedown', function() {
$(this).addClass('movable');
startMove();
}).on('mouseup', function() {
$(this).removeClass('movable');
endMove();
});
});
CSS
#containerDiv {
background:#333;
position:absolute;
width:200px;
height:100px;
}
最も基本的なドラッグ可能なコードは次のとおりです。
Element.prototype.drag = function(){
var mousemove = function(e){ // document mousemove
this.style.left = ( e.clientX - this.dragStartX ) + 'px';
this.style.top = ( e.clientY - this.dragStartY ) + 'px';
}.bind(this);
var mouseup = function(e){ // document mouseup
document.removeEventListener('mousemove',mousemove);
document.removeEventListener('mouseup',mouseup);
}.bind(this);
this.addEventListener('mousedown',function(e){ // element mousedown
this.dragStartX = e.offsetX;
this.dragStartY = e.offsetY;
document.addEventListener('mousemove',mousemove);
document.addEventListener('mouseup',mouseup);
}.bind(this));
this.style.position = 'absolute' // fixed might work as well
}
そして、使用法(非jquery):
document.querySelector('.target').drag();
またはjqueryで:
$('.target')[0].drag();
注意:ドラッグされた要素にはposition:absolute
または position:fixed
動作する左、上の動きに適用されます...
以下のコードペンには、さらに「高度な」機能があります:dragStart、dragStopコールバック、ドラッグ中に他の要素のテキスト選択を削除するcssクラス、およびドロップ機能...
次のcodepenをチェックアウトします。
http://codepen.io/anon/pen/VPPaEK
基本的に、ドラッグする必要がある要素に「mousedown」イベントを設定し、移動を処理するためにドキュメントのmousemoveをバインドおよびバインド解除します。
要素にドラッグ可能なハンドルを設定するため
Element.prototype.drag = function( setup ){
var setup = setup || {};
var mousemove = function(e){ // document mousemove
this.style.left = ( e.clientX - this.dragStartX ) + 'px';
this.style.top = ( e.clientY - this.dragStartY ) + 'px';
}.bind(this);
var mouseup = function(e){ // document mouseup
document.removeEventListener('mousemove',mousemove);
document.removeEventListener('mouseup',mouseup);
}.bind(this);
var handle = setup.handle || this;
handle.addEventListener('mousedown',function(e){ // element mousedown
this.dragStartX = e.offsetX;
this.dragStartY = e.offsetY;
document.addEventListener('mousemove',mousemove);
document.addEventListener('mouseup',mouseup);
handle.classList.add('dragging');
}.bind(this));
handle.classList.add('draggable');
this.style.position = 'absolute' // fixed might work as well
}
上記のコードは次のように使用されます。
var setup = {
handle : document.querySelector('.handle')
};
document.querySelector('.box').drag(setup);
ここでの問題は、ドラッグするときに、ドラッグ可能な要素内のテキストが迷惑なように無駄に選択されていることです...
これが、draggable
およびdragging
クラスを要素に追加した理由です。この不要な動作をキャンセルし、移動カーソルを追加して、この要素がドラッグ可能であることを表示します
.draggable{
cursor: move;
position: fixed;
}
.draggable.dragging{
user-select: none;
}
ドラッグ可能な要素ができたので、ときどきさまざまなイベントを呼び出す必要があります。
setup.ondraginit // this is called when setting up the draggable
setup.ondragstart // this is called when mouse is down on the element
setup.ondragend // this is called when mouse is released (after dragging)
setup.ondrag // this is called while the element is being dragged
それぞれが元のマウスイベントを特定のハンドラーに渡します
最後に、これは私たちが得るものです...
Element.prototype.drag = function( setup ){
var setup = setup || {};
var mousemove = function(e){ // document mousemove
this.style.left = ( e.clientX - this.dragStartX ) + 'px';
this.style.top = ( e.clientY - this.dragStartY ) + 'px';
setup.ondrag && setup.ondrag(e); // ondrag event
}.bind(this);
var mouseup = function(e){ // document mouseup
document.removeEventListener('mousemove',mousemove);
document.removeEventListener('mouseup',mouseup);
handle.classList.remove('dragging');
setup.ondragend && setup.ondragend(e); // ondragend event
}.bind(this);
var handle = setup.handle || this;
handle.addEventListener('mousedown',function(e){ // element mousedown
this.dragStartX = e.offsetX;
this.dragStartY = e.offsetY;
document.addEventListener('mousemove',mousemove);
document.addEventListener('mouseup',mouseup);
handle.classList.add('dragging');
setup.ondragstart && setup.ondragstart(e); // ondragstart event
}.bind(this));
handle.classList.add('draggable');
setup.ondraginit && setup.ondraginit(e); // ondraginit event
}
そしてこれを使用するには:
var setup = {
handle : document.querySelector('.handle'),
ondragstart : e => { console.log('drag has started!'); },
ondrag : e => { console.log('drag!'); },
ondragend : e => { console.log('drag has ended!'); }
};
document.querySelector('.box').drag(setup);
ご了承ください e.target
は、ドラッグ可能な要素への参照です
JQueryUIのようにドラッグ: JsFiddle
奇妙なセンタリングなしで、任意のポイントから要素をドラッグできます。
$(document).ready(function() {
var $body = $('body');
var $target = null;
var isDraggEnabled = false;
$body.on("mousedown", "div", function(e) {
$this = $(this);
isDraggEnabled = $this.data("draggable");
if (isDraggEnabled) {
if(e.offsetX==undefined){
x = e.pageX-$(this).offset().left;
y = e.pageY-$(this).offset().top;
}else{
x = e.offsetX;
y = e.offsetY;
};
$this.addClass('draggable');
$body.addClass('noselect');
$target = $(e.target);
};
});
$body.on("mouseup", function(e) {
$target = null;
$body.find(".draggable").removeClass('draggable');
$body.removeClass('noselect');
});
$body.on("mousemove", function(e) {
if ($target) {
$target.offset({
top: e.pageY - y,
left: e.pageX - x
});
};
});
});
これは私のものです。 http://jsfiddle.net/pd1vojsL/
div内の3つのドラッグ可能なボタン、divによって制約されたドラッグ。
<div id="parent" class="parent">
<button id="button1" class="button">Drag me</button>
<button id="button2" class="button">Drag me</button>
<button id="button3" class="button">Drag me</button>
</div>
<div id="log1"></div>
<div id="log2"></div>
JQueryが必要(のみ):
$(function() {
$('.button').mousedown(function(e) {
if(e.which===1) {
var button = $(this);
var parent_height = button.parent().innerHeight();
var top = parseInt(button.css('top')); //current top position
var original_ypos = button.css('top','').position().top; //original ypos (without top)
button.css({top:top+'px'}); //restore top pos
var drag_min_ypos = 0-original_ypos;
var drag_max_ypos = parent_height-original_ypos-button.outerHeight();
var drag_start_ypos = e.clientY;
$('#log1').text('mousedown top: '+top+', original_ypos: '+original_ypos);
$(window).on('mousemove',function(e) {
//Drag started
button.addClass('drag');
var new_top = top+(e.clientY-drag_start_ypos);
button.css({top:new_top+'px'});
if(new_top<drag_min_ypos) { button.css({top:drag_min_ypos+'px'}); }
if(new_top>drag_max_ypos) { button.css({top:drag_max_ypos+'px'}); }
$('#log2').text('mousemove min: '+drag_min_ypos+', max: '+drag_max_ypos+', new_top: '+new_top);
//Outdated code below (reason: drag contrained too early)
/*if(new_top>=drag_min_ypos&&new_top<=drag_max_ypos) {
button.css({top:new_top+'px'});
}*/
});
$(window).on('mouseup',function(e) {
if(e.which===1) {
//Drag finished
$('.button').removeClass('drag');
$(window).off('mouseup mousemove');
$('#log1').text('mouseup');
$('#log2').text('');
}
});
}
});
});
上で見たものは複雑です.....
参照できるコードは次のとおりです。
$("#box").on({
mousedown:function(e)
{
dragging = true;
dragX = e.clientX - $(this).position().left;
//To calculate the distance between the cursor pointer and box
dragY = e.clientY - $(this).position().top;
},
mouseup:function(){dragging = false;},
//If not set this on/off,the move will continue forever
mousemove:function(e)
{
if(dragging)
$(this).offset({top:e.clientY-dragY,left:e.clientX-dragX});
}
})
dragg、dragX、dragYは、グローバル変数として配置できます。
この問題に関する簡単なショーですが、この方法にはいくつかのバグがあります。
それが今あなたの必要であれば、ここにあります ここに例
$(document).ready(function() {
var $startAt = null;
$(document.body).live("mousemove", function(e) {
if ($startAt) {
$("#someDiv").offset({
top: e.pageY,
left: $("#someDiv").position().left-$startAt+e.pageX
});
$startAt = e.pageX;
}
});
$("#someDiv").live("mousedown", function (e) {$startAt = e.pageX;});
$(document.body).live("mouseup", function (e) {$startAt = null;});
});