I'm trying to build a jQuery plugin that allows you to drag and draw a rectangle (or a div with a border) but I'm not sure how to do it. I don't know of any that currently have this ability so I don't know where to look for an example of how to do this.
How can I implement drag and draw in jQuery?
The basics for something like this are quite simple, when you think about it:
Listen for mousedown events on some container (possible the entire document);
Place an absolutely positioned element at the position of the mouse, using the mouse coordinates from the event object (e.pageX and e.pageY);
Start listening to mousemove events to change the width and height object (based on the mouse coordinates);
Listen for the mouseup event to detach the mousemove event listener.
The aforementioned absolute placed element is, e.g., a <div> with a border and background: transparent.
Update: here is an example:
$(function() {
var $container = $('#container');
var $selection = $('<div>').addClass('selection-box');
$container.on('mousedown', function(e) {
var click_y = e.pageY;
var click_x = e.pageX;
$selection.css({
'top': click_y,
'left': click_x,
'width': 0,
'height': 0
});
$selection.appendTo($container);
$container.on('mousemove', function(e) {
var move_x = e.pageX,
move_y = e.pageY,
width = Math.abs(move_x - click_x),
height = Math.abs(move_y - click_y),
new_x, new_y;
new_x = (move_x < click_x) ? (click_x - width) : click_x;
new_y = (move_y < click_y) ? (click_y - height) : click_y;
$selection.css({
'width': width,
'height': height,
'top': new_y,
'left': new_x
});
}).on('mouseup', function(e) {
$container.off('mousemove');
$selection.remove();
});
});
});
Demo: http://jsbin.com/ireqix/226/
$("#YOUR_ELEMENT_ID").on("mousedown", function (e) {
var click_x = e.pageX;
var click_y = e.pageY;
/* Posição do objeto */
var x = parseFloat($(this).css("left").replace("px", "")),
y = parseFloat($(this).css("top").replace("px", ""));
/* Calcula distância no eixo x */
var distanc_x = Math.abs(x - click_x);
var distanc_y = Math.abs(y - click_y);
$("#YOUR_ELEMENT_ID")
.on("mousemove", function (e) {
var new_x = e.pageX - distanc_x;
var new_y = e.pageY - distanc_y;
$(this).css({
top: new_y,
left: new_x,
});
}).on("mouseup", function (e) {
$(this).off("mousemove");
});
});
Related
I am trying to draw shape in div element. The code below draws a shape in correct starting point if not transform scale. But if transform scale, the line is not in the correct position when drawing the shape. How to fix the code below if the div is transform scale in (0.7, 0.7)? Thank you in advance.
$(function() {
var $container = $('#container');
var $selection = $('<div>').addClass('selection-box');
$container.on('mousedown', function(e) {
var click_y = e.pageY,
click_x = e.pageX;
$selection.css({
'top': click_y,
'left': click_x,
'width': 0,
'height': 0
});
$selection.appendTo($container);
$container.on('mousemove', function(e) {
var move_x = e.pageX,
move_y = e.pageY,
width = Math.abs(move_x - click_x),
height = Math.abs(move_y - click_y),
new_x, new_y;
new_x = (move_x < click_x) ? (click_x - width) : click_x;
new_y = (move_y < click_y) ? (click_y - height) : click_y;
$selection.css({
'width': width,
'height': height,
'top': new_y,
'left': new_x
});
}).on('mouseup', function(e) {
$container.off('mousemove');
$selection.remove();
});
});
});
I have a selection on a canvas, that I can drag and resize when it´s there.
I also can make it visible when I drag on the empty canvas.
But how do I make it visible and instantly have the bottom-right corner "in my hand" (for resizing); i.e. can I pass the drag event from the canvas to a resize event on the selection?
Is there a way with jQuery or do I have to make my own?
<div id="canvas" style="position:relative;width:500px;height:500px"
draggable="true" onDragStart="initSelection(event)">
<div id="selection" style="border:1px dashed gray;position:absolute;display:none"></div>
</div>
$('#selection').draggable({containment:'parent'}).resizable({containment:'parent'});
function initSelection(e){
if ('none'==$('#selection').css('display'))
{
var q=$('#canvas').offset();
$('#selection')
.css('left', e.clientX-q.left)
.css('top', e.clientY-q.top)
.css('width',10).css('height',10)
.css('display','block')
;
}
}
I think I see what you're trying to do.
Testing here: jsfiddle.net/Twisty/vkLjn0gL
I think you need to take one route or the other, not both at once.
resize the div with CSS based on the mousedown / mouseup events and
mouse x and y.
make it resizable up front and enable/start the resize
event tied to the mousemove until done and then make it draggable
I got this far when you posted that you found an answer: https://jsfiddle.net/Twisty/vkLjn0gL/5/
$(function() {
$("#canvas").on("dragstart", initSelection);
$("#canvas").on("mousemove", resize);
$("#canvas").on("mouseup", function() {
allowResize = false;
});
var allowResize = false;
/*
$('#selection').draggable({
containment: 'parent'
}).resizable({
containment: 'parent'
});
*/
function initSelection(e) {
if ('none' == $('#selection').css('display')) {
var q = $('#canvas').offset();
$('#selection')
.css('left', e.clientX - q.left)
.css('top', e.clientY - q.top)
.css('width', '10px').css('height', '10px')
.css('display', 'block');
allowResize = true;
}
}
function resize(e) {
if (allowResize) {
//console.log("MouseMove: ", e);
var w = $("#selection").width(),
h = $("#selection").height(),
q = $("#canvas").offset(),
px = 0,
py = 0;
px = e.clientX - q.left;
py = e.clientY - q.top;
console.log("Width: ", (w + px), " Height: ", (h + py));
$("#selection").css({
width: (w + px) + "px",
height: (h + py) + "px"
});
}
}
});
Update 1
Few fixes to mouse tracking:
https://jsfiddle.net/Twisty/vkLjn0gL/6/
function resize(e) {
if (allowResize) {
//console.log("MouseMove: ", e);
$("#canRes").html(allowResize);
$("#cx").html(e.clientX - $("#canvas").offset().left);
$("#cy").html(e.clientY - $("#canvas").offset().top);
$("#ox").html($("#selection").width());
$("#oy").html($("#selection").height());
var w = $("#selection").width(),
h = $("#selection").height(),
q = $("#canvas").offset(),
o = $("#selection").position();
px = 0,
py = 0;
if (w > $("#canvas").width() + q.left) {
return false;
}
if (h > $("#canvas").height() + q.top) {
return false;
}
px = e.clientX - q.left - o.left;
py = e.clientY - q.top - o.top;
$("#selection").css({
width: px + "px",
height: py + "px"
});
}
}
Update 2
I think this will do all that you wanted if you're still looking: https://jsfiddle.net/Twisty/vkLjn0gL/7/
Updated to selection after mouseup
$("#canvas").on("mouseup", function() {
allowResize = false;
$("#canRes").html(allowResize);
$("#selection").draggable({
containment: 'parent'
})
.resizable({
containment: 'parent'
});
});
Update 3
Added the drag handle on initial sizing: https://jsfiddle.net/Twisty/vkLjn0gL/10/
I have div that can be placed anywhere inside another div. I am able to do this with jquery mousemove event. However it is not quite working. I am trying to get the mouse cursor to be in the center of the moving div. I set these css attributes inline with jquery 'top': relY + 30,'left': relX + 10 but no luck. As mention I am trying to get the cursor in the middle of the div. The user can only place the moving inside the parent div called middle-side empty. JSFIDDLE
I am trying to accomplish something similar to this: http://jsfiddle.net/Lqebpaov/
Jquery:
$('#button').click(function (e) {
$('<div />', {
class: 'draggable ui-widget-content',
text: $('textarea').val(),
appendTo: '.middle-side',
draggable: {
containment: 'parent'
}
}).addClass('placement');
$('.middle-side').parent().mousemove(function(e){
var offset = $(this).offset();
var relX = e.pageX - offset.left;
var relY = e.pageY - offset.top;
$('.placement').css({'top': relY + 30,'left': relX + 10, 'position': 'absolute'});
})
});
$('.middle-side').on('click', function(e){
var offset = $(this).offset();
var relX = e.pageX - offset.left;
var relY = e.pageY - offset.top;
$('.placement').css({'top': relY,'left': relX, 'position': 'absolute' });
$(this).off("mousemove").find('.placement').removeClass('placement')
});
HTML
<div>
<div class="middle-side empty"></div>
</div>
This was a fun question. I updated a lot of your Javascript, and set up my own JSFIDDLE.
With this setup you should be able to resize the boxes to any height/width combination and it will work as expected. You can check out the JSFIDDLE link, but here is the updated Javascript also:
$('#button').click(function (e) {
$('<div />', {
class: 'draggable ui-widget-content',
text: $('textarea').val(),
appendTo: '.middle-side',
draggable: {
containment: 'parent'
}
}).addClass('placement');
$('.middle-side').parent().mousemove(function(e){
var offset = $(this).offset(),
relX = e.pageX,
relY = e.pageY,
$dvPlacement = $('.placement'),
pWidth = $dvPlacement.outerWidth(),
pHeight = $dvPlacement.outerHeight(),
$dvOutBox = $('.middle-side'),
oWidth = $dvOutBox.outerWidth(),
oHeight = $dvOutBox.outerHeight(),
centerY = relY - pHeight / 2,
centerX = relX - pWidth / 2,
topBorder = $dvOutBox.offset().top,
bottomBorder = $dvOutBox.offset().top + oHeight,
leftBorder = $dvOutBox.offset().left,
rightBorder = $dvOutBox.offset().left + oWidth;
$dvPlacement.css({'top': centerY + pHeight > bottomBorder ? bottomBorder - pHeight :
centerY < topBorder ? topBorder :
centerY,
'left': centerX + pWidth > rightBorder ? rightBorder - pWidth :
centerX < leftBorder ? leftBorder :
centerX,
'position': 'absolute'
});
})
});
$('.middle-side').on('click', function(e){
$(this).off("mousemove").find('.placement').removeClass('placement')
});
Change the placement offset to
$('.placement').css({'top': relY + 30,'left': relX - 75 , 'position': 'absolute'});
Demo
I am trying to have a div in a container which when the user clicks and drags somewhere in the document area, the .room element pans around inside the .viewport element by holding down the middle click button.
Here is the issue: (Hold right click for this one, middle click didn't work for some reason)
http://jsfiddle.net/JeZj5/2/
JS
var mouseX = 0;
var mouseY = 0;
var scale = 1.0;
$(document).mousemove(function (e) {
var offset = $('.room').offset();
//relative mouse x,y
mouseX = parseFloat((e.pageX - offset.left) / scale, 2);
mouseY = parseFloat((e.pageY - offset.top) / scale, 2);
//absolute mouse x,y
mouseXRaw = e.pageX;
mouseYRaw = e.pageY;
$(".room").html(mouseX + ', ' + mouseY + '<br />Right click document and pan');
switch (e.which) {
case 3:
$('.room').css({
left: mouseX,
top: mouseY
});
break;
}
return true;
});
$(document).on('contextmenu', function () {
return false;
});
This should be more along the lines of what you're looking for. Key change:
delta.x = e.pageX - drag.x;
delta.y = e.pageY - drag.y;
Using the delta to change the position. The .room's position should be moving with respect to it's current location, minus the mouse drag position (not the other way around).
http://jsfiddle.net/X2PZP/3/
On the following page I have a popup that is supposed to show beside the image, depending on the window size the pop-up displays further/closer to the mouse. I don't understand what is wrong with the code, that makes the pop-up not display in the same proximity to the mouse?
http://www.hughgrice.com/test/
jQuery(document).mousemove(function (e) {
mouseX = e.pageX;
mouseY = e.pageY;
follow();
});
function follow(){
d = document.getElementById("thumbTT");
if(openToolTip){
d.style.display = "block";
d.style.left = mouseX+5 + "px";
d.style.top = mouseY-100 + "px";
}else{
d.style.display = "none";
}
}
http://www.hughgrice.com/test/
This should work:
var $elem = $( '#thumbTT' );
$( document ).on( 'mousemove', function ( e ) {
follow( e.pageX, e.pageY );
});
function follow ( x, y ) {
if( openToolTip ) {
$elem.css({ left: x + 5, top: y - 100 }).show();
} else {
$elem.hide();
}
}
I'm assuming that the #thumbTT element is static, so I'm caching the reference to it beforehand.
As your wrapper DIV is relative positioned that's why it is not positioned correctly. Either you have to remove the position:relative from your wrapper div or you have to write your mousemove function like
jQuery(document).mousemove(function (e) {
var offset = jQuery(this).css('offset');
mouseX = offset.left;
mouseY = offset.top;
follow();
});
maybe you have to adjust your code