I don't know how to find the place part (one of 4 triangles) of a cursor in a rectangle.
This image is more efficient than my explication :s
Im in javascript (so the rectangle is a DIV, 0,0 placed)
I have those varaibles :
var cursor_x = e.clientX + $(document).scrollLeft()
var cursor_y = e.clientY + $(document).scrollTop()
var rect_w = $( rectangle ).width()
var rect_h = $( rectangle ).height()
I just want to know mathematically where is the cursor, in the triangle 1, 2, 3 or 4
What I think is the easiest way is to first normalize y so the computation is the same as for a square and then check for on which side of the diagonals you are...
var ynorm = y * w / h;
var s1 = x > ynorm ? 0 : 1;
var s2 = (w - x) > ynorm ? 0 : 1;
var area = s1*2 + s2;
the final area variable is a number between 0 and 3 telling in which of the four parts you are.
#6502: Thk you, its very helpful.
For more info, im working on an experimental light sortable jquery plugin, that can work with floating placement (top, left, right, bottom)
the code :
simply use $( ..selector.. ).sortable({ items: ..selector.. })
-
$.fn.sortable = function( o ) {
o.self = this;
o.helper = null;
$(document).bind('mouseup.sortable', function(e) {
if( o.sortable ) {
o.sortable.css({ opacity: ''});
if( o.target ) {
if( o.area == 's' ) {
o.sortable.css({ float: '' })
}
else if( o.area == 'n' ) {
o.sortable.css({ float: '' })
o.target.css({ float: '' })
}
else if( o.area == 'w' ) {
o.target.css({ float: 'left' })
o.sortable.css({ float: 'left' })
}
else if( o.area == 'e' ) {
o.target.css({ float: 'left' })
o.sortable.css({ float: 'left' })
}
o.target[ o.area == 's' || o.area == 'e' ? 'before':'after']( o.sortable );
o.target[0].style.setProperty( 'cursor', false , false);
o.target = null;
}
o.helper.remove();
o.sortable = null;
}
}).bind('mousemove.sortable', function(e) {
if( o.sortable ) {
o.ex = e.clientX + $(document).scrollLeft() + 10
o.ey = e.clientY + $(document).scrollTop() - o.sortable[0]._height - 10
o.helper.css({ left: o.ex, top: o.ey });
}
});
return $( this.selector ).delegate( o.items, 'mousemove.sortable', function(e) {
if( o.sortable && o.sortable[0] != this ) {
var self = $(this)
var x = e.clientX + $(document).scrollLeft() - self.offset().left
var y = e.clientY + $(document).scrollTop() - self.offset().top
var w = self.width()
var h = self.height()
var ynorm = y * w / h;
o.area = (w - x) > ynorm ? ( x > ynorm ? 's':'e' ) : ( x > ynorm ? 'w':'n' );
this.style.setProperty( 'cursor', o.area+'-resize', 'important');
o.target = self;
}
}).delegate( o.items, 'mousedown.sortable', function( e ) {
o.sortable = $(this).css({ opacity: 0.4 });
this._width = o.sortable.width();
this._height = o.sortable.height();
o.helper = o.sortable.clone().css({ position: 'absolute', left: -99999, top: 0 })
$('body').append( o.helper )
return false;
});
}
Related
I'm trying to understand how to add basic interactivity to specific elements. Here I'm hoping for the user to be able to press any arrow key and see the element rotate and translate accordingly. I'm not sure the difference between using the DOM vs Canvas for this, but being I know how to work with the DOM I chose that method here. My problem is the element isn't consistent in it's movements and I think its because I'm accidentally overwriting transform values with my functions.
Here is the snippet below. All arrow keys doing something besides the down key.
function rotate( e, n ) { //get current rotation and add n to it
var curTranslation = getTrans( e );
e.style.transform =
'rotate( ' + n + 'deg ) translateY(' + curTranslation + 'px )';
}
function translate( e, n ) { //get current translation and add n to it
var curRotation = getRot( e );
e.style.transform =
'rotate( ' + curRotation + 'deg ) translateY(' + n + 'px )';
}
function checkKey( e ) { //fire when a key on the keyboard is pressed.
var d = document,
triBx = d.getElementById( 'tri-bx' );
if ( e.keyCode == '38' ) { //up
countTrans = Math.abs( countTrans ) * -1.1;
translate( triBx, countTrans );
}
else if ( e.keyCode == '40' ) { //down
body.innerHTML = 'down';
}
else if ( e.keyCode == '37' ) { //left
countRot = Math.abs( countRot ) * -1.1;
rotate( triBx, countRot );
}
else if ( e.keyCode == '39' ) { //right
countRot = Math.abs( countRot ) * 1.1;
rotate( triBx, countRot );
}
}
function start() { //call first function
var d = document,
triBx = d.getElementById( 'tri-bx' );
window.addEventListener( 'keydown', checkKey );
}
//prevent entire window from scrolling
window.addEventListener("keydown", function(e) {
// space and arrow keys
if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
e.preventDefault();
}
}, false);
start();
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
.tri-bx {
transform: rotate( 0 );
transition: transform 1s;
}
.tri {
width: 0;
height: 0;
border-left: 1rem solid transparent;
border-right: 1rem solid transparent;
border-bottom: 1rem solid black;
transform: scaleX( 0.5 );
}
<div id="tri-bx" class="tri-bx">
<div id="tri" class="tri"></div>
</div>
<p style="position:absolute; bottom: 0;">use arrow keys</p>
<script>
var countRot = 1, //keep track of how many times the keys are pressed for rotation
countTrans = 1; //Same for translation
function getRot( e ) { //get rotation angle of element
var st = window.getComputedStyle( e, null ),
tr = st.getPropertyValue( 'transform' ) || 'FAIL',
values = tr.split( '(' )[ 1 ].split( ')' )[ 0 ].split( ',' ),
a = values[ 0 ],
b = values[ 1 ],
c = values[ 2 ],
d = values[ 3 ],
scale = Math.sqrt( a * a + b * b ),
sin = b / scale,
angle = Math.round( Math.atan2( b, a ) * ( 180 / Math.PI ) );
return angle;
}
function getTrans( e ) { //get translation value of element
var st = window.getComputedStyle( e, null ),
tr = st.getPropertyValue( 'transform' ) || 'FAIL',
values = tr.split( '(' )[ 1 ].split( ')' )[ 0 ].split( ',' ),
f = values[ 5 ];
return f;
}
</script>
My question is why does the object skip around the screen and how can I avoid overwriting the transforms to get this working properly. Ideas?
You are using transform for something it was not intended to do.
The element is being transformed always from it's original position. That's why after you translate it and then change its rotation, it rotates a bunch (that's probably not what you where expecting to happen). If you think about it, it rotates in degrees, so the further you take the triangle from the "middle", or where it started from, the more distance it'll move.
I suggest you either use canvas for this (there are great game libraries that makes it easier than you'd think). Remember that CSS was created for styling, not interaction.
I'm attempting to output on a page multiple 'labels' over an image using absolute positioned divs. Each of these divs has a unique number and are placed according to an x and y position on the map (these are percentage based so the image may be scaled).
As some of these labels may overlap, I need a way to either stop them from overlapping, or to essentially 'bump' them off eachother so they no longer overlap. (At this point, it doesn't matter if they are not in their correct position as long as they are near enough as there is a separate 'Pin' view).
They need to stay within the confines of their container and not overlap with eachother.
HTML:
<div id="labelzone">
<div class="label" style="left:0%;top:8%">001</div>
<div class="label" style="left:0%;top:11%">002</div>
<div class="label" style="left:1%;top:10%">003</div>
</div>
CSS:
#labelzone{
float:left;
width:500px;
height:500px;
border: 1px solid black;
position: relative;
}
.label{
position:absolute;
border:1px solid black;
background-color:white;
}
Jsfiddle: https://jsfiddle.net/79cco1oy/
There's a simple example of what I have as an output, these pins could be placed anywhere and there is no limit to how many is on the page, however there shouldn't be any occasion where there are too many to fit in the area.
I'm toying around with doing some form of collision detection and currently attempting to figure out an algorithm of some sort to get them to no longer overlap, and ensure they also don't overlap another item.
My solution is a bit more object oriented.
One object (LabelPool) will contain labels and will be in charge of storing and accomodating them so that they don't collide. You can customize the x/y values that you want to add/substract of the Label's positions in order to avoid their collision. The other object (Label) defines a Label and has some convenient methods. The collision algorithm that I used in LabelPool was taken from this post
var Label = function ($el) {
var position = $el.position(),
width = $el.outerWidth(true),
height = $el.outerHeight(true);
this.getRect = function () {
return {
x: position.left,
y: position.top,
width: width,
height: height
};
};
this.modifyPos = function (modX, modY) {
position.top += modY;
position.left += modX;
updatePos();
};
function updatePos() {
$el.css({
top: position.top,
left: position.left
});
}
};
var LabelPool = function () {
var labelPool = [];
function collides(a, b) {
return !(((a.y + a.height) < (b.y)) || (a.y > (b.y + b.height)) || ((a.x + a.width) < b.x) || (a.x > (b.x + b.width)));
}
function overlaps(label) {
var a = label.getRect();
return labelPool.some(function (other) {
return collides(a, other.getRect());
});
}
this.accomodate = function (label) {
while (labelPool.length && overlaps(label)) {
label.modifyPos(0, 1);// You can modify these values as you please.
}
labelPool.push(label);
};
};
var labelPool = new LabelPool;
$(".label").each(function (_, el) {
labelPool.accomodate(new Label($(el)));
});
Here's the fiddle.
Hope it helps.
Using js and jquery, you can find a basic collision engine based on left/top abs position and size of the label.
https://jsfiddle.net/Marcassin/79cco1oy/6/
Every time you want to add a Label, you check if the positionning is overlaping any existing div, in this case, you translate the new Label to position. This operation may not be the most beautiful you can find, there can be a long process time in case of lots of labels.
$(document).ready (function () {
addLabel (0, 8);
addLabel (0, 11);
addLabel (1, 10);
addLabel (2, 7);
});
function addLabel (newLeft, newTop)
{
var newLab = document.createElement ("div");
newLab.className = "label";
$(newLab).css({"left": newLeft+"%", "top": newTop + "%"});
var labels = $("#labelzone > div");
newLab.innerHTML = "00" + (labels.length + 1); // manage 0s
$("#labelzone").append (newLab);
var isCollision = false;
var cpt = 1;
do
{
isCollision = false;
$(labels).each (function () {
if (! isCollision && collision (this, newLab))
isCollision = true;
});
if (isCollision)
$(newLab).css({"left": (newLeft + cpt++) + "%",
"top": (newTop + cpt++) + "%"});
} while (isCollision);
}
function isInside (pt, div)
{
var x = parseInt($(div).css("left"));
var y = parseInt($(div).css("top"));
var w = $(div).width () + borderWidth;
var h = $(div).height ();
if (pt[0] >= x && pt[0] <= x + w &&
pt[1] >= y && pt[1] <= y + h)
return true;
return false;
}
function collision (div1, div2)
{
var x = parseInt($(div1).css("left"));
var y = parseInt($(div1).css("top"));
var w = $(div1).width () + borderWidth;
var h = $(div1).height ();
var pos = [x, y];
if (isInside (pos, div2))
return true;
pos = [x + w, y];
if (isInside (pos, div2))
return true;
pos = [x + w, y + h];
if (isInside (pos, div2))
return true;
pos = [x, y + h];
if (isInside (pos, div2))
return true;
return false;
}
Here's another implementation of collision detection close to what you asked for. The two main goals being:
move vertically more than horizontally (because boxes are wider than tall)
stay within a reasonable range from the origin
Here goes:
function yCollision($elem) {
var $result = null;
$('.label').each(function() {
var $candidate = $(this);
if (!$candidate.is($elem) &&
$candidate.position().top <= $elem.position().top + $elem.outerHeight() &&
$candidate.position().top + $candidate.outerHeight() >= $elem.position().top) {
$result = $candidate;
console.log("BUMP Y");
}
});
return $result;
}
function xCollision($elem) {
var $result = null;
$('.label').each(function() {
$candidate = $(this);
if (!$candidate.is($elem) &&
yCollision($elem) &&
yCollision($elem).is($candidate) &&
$candidate.position().left <= $elem.position().left + $elem.outerWidth() &&
$candidate.position().left + $candidate.outerWidth() >= $elem.position().left) {
$result = $candidate;
console.log("BUMP X");
}
});
return $result;
}
function fuzzyMoveY($elem, direction) {
var newTop = $elem.position().top + $elem.outerHeight() / 4 * direction;
// stay in the canvas - top border
newTop = (newTop < 0 ? 0 : newTop);
// stay in the canvas - bottom border
newTop = (newTop + $elem.outerHeight() > $("#labelzone").outerHeight() ? $("#labelzone").outerHeight() - $elem.outerHeight() : newTop);
// stay close to our origin
newTop = (Math.abs(newTop - $elem.attr("data-origin-top")) > $elem.outerHeight() ? $elem.attr("data-origin-top") : newTop);
$elem.css({'top': newTop});
}
function fuzzyMoveX($elem, direction) {
var newLeft = $elem.position().left + $elem.outerWidth() / 4 * direction;
// stay in the canvas - left border
newLeft = (newLeft < 0 ? 0 : newLeft);
// stay in the canvas - right border
newLeft = (newLeft + $elem.outerWidth() > $("#labelzone").outerWidth() ? $("#labelzone").outerWidth() - $elem.outerWidth() : newLeft);
// stay close to our origin
newLeft = (Math.abs(newLeft - $elem.attr("data-origin-left")) > $elem.outerWidth() ? $elem.attr("data-origin-left") : newLeft);
$elem.css({'left': newLeft});
}
function bumpY($above, $below) {
if ($above.position().top > $below.position().top) {
$buff = $above;
$above = $below;
$below = $buff;
}
fuzzyMoveY($above, -1);
fuzzyMoveY($below, 1);
}
function bumpX($left, $right) {
if ($left.position().left > $right.position().left) {
$buff = $right;
$right = $left;
$left = $buff;
}
fuzzyMoveX($left, 1);
fuzzyMoveX($right, -1);
}
$('.label').each(function() {
$(this).attr('data-origin-left', $(this).position().left);
$(this).attr('data-origin-top', $(this).position().top);
});
var yShallPass = true;
var loopCount = 0;
while (yShallPass && loopCount < 10) {
yShallPass = false;
$('.label').each(function() {
var $this = $(this);
$collider = yCollision($this);
if ($collider) {
bumpY($this, $collider);
yShallPass = true;
}
});
loopCount++;
}
console.log("y loops", loopCount);
var xShallPass = true;
var loopCount = 0;
while (xShallPass && loopCount < 10) {
xShallPass = false;
$('.label').each(function() {
var $this = $(this);
$collider = xCollision($this);
if ($collider) {
bumpX($this, $collider);
xShallPass = true;
}
});
loopCount++;
}
console.log("x loops", loopCount);
This is not production code obviously but please report back if it helps.
I need make a element follow another element when dragging, but with delay in the animation, is similar to "Chat heads of facebook's messenger", you know, the bubbles on Android.
This is my jQuery plugin:
// Draggable plugin
(function($) {
$.fn.drag = function(options) {
options = $.extend({
handle: null,
cursor: 'move',
draggingClass: 'dragging',
heads: null
}, options);
var $handle = this,
$drag = this;
if( options.handle ) {
$handle = $(options.handle);
}
$handle
.css('cursor', options.cursor)
.on("mousedown", function(e) {
var x = $drag.offset().left - e.pageX,
y = $drag.offset().top - e.pageY,
z = $drag.css('z-index');
$drag.css('z-index', 100000);
$(document.documentElement)
.on('mousemove.drag', function(e) {
var chats = $($(options.heads).get().reverse());
chats.each(function(i) {
$(chats[i]).css({ left: $drag.position().left - (10*i)});
$(chats[i]).css({top: $drag.position().top});
});
$drag.offset({
left: x + e.pageX,
top: y + e.pageY
});
})
.one('mouseup', function() {
$(this).off('mousemove.drag');
$drag.css('z-index', z);
var window_width = $(window).width();
var window_height = $(window).height();
var head_wpostion = $(options.heads).position().left;
var head_hposition = $(options.heads).position().top;
if( head_wpostion > (window_width / 2) )
{
$(options.heads).animate({left: (window_width-40)+"px"}, 300 );
$(options.heads).animate({left: (window_width-50)+"px"}, 300 );
}
else
{
$(options.heads).animate({left: "-15px"}, 300 );
$(options.heads).animate({left: "-5px"}, 300 );
}
if( head_hposition > (window_height - 50) )
{
$(options.heads).animate({top: (window_height-75)+"px"}, 200 );
$(options.heads).animate({top: (window_height-65)+"px"}, 200 );
}
if( head_hposition < 0 )
{
$(options.heads).animate({top: "15px"}, 150 );
$(options.heads).animate({top: "5px"}, 150 );
}
});
// disable selection
e.preventDefault();
});
};
})(jQuery);
the only way you can do that is if you position the element you want to to be dragged along relevant to the drag-able element.
In my quest for learning more Javascript I'm trying to create a jQuery plugin that creates my own custom scrollbars. It is working fine for one scrollbar at a time but if I try to do two of them only the last one works.
JSFiddle: http://jsfiddle.net/JoelCool/K4mW7/1/
I've noticed the variable "scrolling" is not true on the first scrollbar in the HandleMouseMove() function so it seems like it might be a scoping thing?
HTML
Scrollbar Test
.scroller-bar {
background-color:#ccc;border:1px solid black;float:left;position:relative;cursor:pointer;
}
.noSelect
{
user-select:none;
-o-user-select:none;
-moz-user-select:none;
-khtml-user-select:none;
-webkit-user-select:none;
}
<div id="container" style="width:600px;height:300px;background-color:#ccc;overflow:hidden;position:relative;">
<div id="content" style="background-color:blue;width:800px;height:283px;position:relative;left:0;">
12345678901234567890123456789012345678901234567890
</div>
<div style="top:0;left:0;height:300px;width:100px;background-color:yellow;z-index:100;position:absolute;"></div>
<div id="scroll-track-h" style="position:absolute;bottom:0;right:0;height:17px;width:500px;background-color:cyan;"></div>
<div id="scroll-track-v" style="position:absolute;top:0;right:0;height:283px;width:17px;background-color:orange;"></div>
</div>
<br /><br />
<script src="jquery-2.1.0.min.js"></script>
<script src="scroller.js"></script>
<script>
$('#scroll-track-v').scroller();
$('#scroll-track-h').scroller();
//$('#scroll-track-v, #scroll-track-h').scroller();
</script>
Javascript
(function( $ ) {
$.fn.scroller = function( options ) {
options = $.extend( $.fn.scroller.defaults, options );
// Plugin code
return this.each(function () {
var $elem = $(this),
scrolling = false,
mouseStartPos = 0,
barPos = 0,
xy = $elem.width() > $elem.height() ? 'x' : 'y', // x = horizontal, y = vertical
trackLength = xy == 'x' ? $elem.width() : $elem.height(),
barLength = (trackLength * options.barPct / 100) - 2, // should make it figure out the border width
travelLength = trackLength - barLength - 2;
console.log($elem);
var $bar = $('<div class="scroller-bar"></div>')
.width( xy == 'x' ? barLength : $elem.innerWidth() - 2)
.height( xy == 'x' ? $elem.innerHeight() - 2 : barLength);
$elem.append($bar);
$elem.on('mousedown', function (evt) {
scrolling = true;
$("body").addClass("noSelect"); // turn off text selection while scrolling
mouseStartPos = xy == 'x' ? evt.pageX : evt.pageY;
barPos = xy == 'x' ? $bar.position().left : $bar.position().top;
$(document).on('mousemove', function (evt) { HandleMouseMove(evt); });
});
$(document).on('mouseup', function (evt) {
if (scrolling) {
$("body").removeClass("noSelect");
$(document).off('mousemove');
mouseStartPos = 0;
scrolling = false;
}
});
HandleMouseMove = function (evt) {
console.log(scrolling);
if (scrolling) {
var mouseMovedBy = xy == 'x' ? evt.pageX - mouseStartPos : evt.pageY - mouseStartPos,
newBarPos = barPos + mouseMovedBy;
if (newBarPos < 0) { newBarPos = 0; }
if (newBarPos > travelLength) { newBarPos = travelLength; }
$bar.css(xy == 'x' ? 'left' : 'top', newBarPos);
var pct = newBarPos / travelLength;
}
}
});
}
// Set up the default options.
$.fn.scroller.defaults = {
barPct : 25,
onScroll : null
};
})( jQuery );
$('#scroll-track-v').scroller();
$('#scroll-track-h').scroller();
I'm calling it on the vertical bar first and then the horizontal and only the horizontal works. If I switch them then only the vertical works.
Can anyone give me a clue? Am I doing it completely wrong?
Your function HandleMouseMove() was not binded to the Element. It was getting mixed values for the 'scrolling' Boolean value.
I just added $elem. before the function name. and made it as $elem.HandleMouseMove(event);
Check the code
(function( $ ) {
$.fn.scroller = function( options ) {
options = $.extend( $.fn.scroller.defaults, options );
// Plugin code
return this.each(function () {
var $elem = $(this),
scrolling = false,
mouseStartPos = 0,
barPos = 0,
xy = $elem.width() > $elem.height() ? 'x' : 'y', // x = horizontal, y = vertical
trackLength = xy == 'x' ? $elem.width() : $elem.height(),
barLength = (trackLength * options.barPct / 100) - 2, // should make it figure out the border width
travelLength = trackLength - barLength - 2;
console.log($elem);
var $bar = $('<div class="scroller-bar"></div>')
.width( xy == 'x' ? barLength : $elem.innerWidth() - 2)
.height( xy == 'x' ? $elem.innerHeight() - 2 : barLength);
$elem.append($bar);
$elem.on('mousedown', function (evt) {
scrolling = true;
$("body").addClass("noSelect"); // turn off text selection while scrolling
mouseStartPos = xy == 'x' ? evt.pageX : evt.pageY;
barPos = xy == 'x' ? $bar.position().left : $bar.position().top;
$(document).on('mousemove', function (evt) { $elem.HandleMouseMove(evt); });
});
$(document).on('mouseup', function (evt) {
if (scrolling) {
$("body").removeClass("noSelect");
$(document).off('mousemove');
mouseStartPos = 0;
scrolling = false;
}
});
$elem.HandleMouseMove = function (evt) {
console.log(scrolling);
if (scrolling) {
var mouseMovedBy = xy == 'x' ? evt.pageX - mouseStartPos : evt.pageY - mouseStartPos,
newBarPos = barPos + mouseMovedBy;
if (newBarPos < 0) { newBarPos = 0; }
if (newBarPos > travelLength) { newBarPos = travelLength; }
$bar.css(xy == 'x' ? 'left' : 'top', newBarPos);
var pct = newBarPos / travelLength;
}
}
});
}
// Set up the default options.
$.fn.scroller.defaults = {
barPct : 25,
onScroll : null
};
})( jQuery );
$('#scroll-track-v').scroller();
$('#scroll-track-h').scroller();
Check the Updated jsfiddle http://jsfiddle.net/shinde87sagar/K4mW7/3/
I've updated your code to work using data objects. When you have multiple DOM elements being worked on in a plugin, you should explicitly state which objects you're referring to. Keeping them global as you did makes it impossible for the mousemove and mouseup events to know which element to refer to. This way is cleaner and you only have to worry about the scope inside each event handler.
edit: this doesn't move the content pane yet, but this should give you an idea how to proceed correctly.
http://jsfiddle.net/ozzy_og_kush/K4mW7/2/
$.fn.scroller = function( options ) {
options = $.extend( $.fn.scroller.defaults, options );
// Plugin code
return this.each(function () {
var $elem = $(this);
var xy = ($elem.width() > $elem.height() ? 'x' : 'y');
var trackLength = (xy == 'x' ? $elem.width() : $elem.height());
var barLength = (trackLength * options.barPct / 100) - 2;
$elem.data({
'scrolling' : false,
'xy' : xy,
'barPos' : 0,
'mouseStartPos' : 0,
'trackLength' : trackLength,
'barLength' : barLength,
'travelLength' : trackLength - barLength - 2
});
console.log($elem);
var $bar = $('<div class="scroller-bar"></div>')
.width($elem.data('xy') == 'x' ?
$elem.data('barLength') :
$elem.innerWidth() - 2
)
.height($elem.data('xy') == 'x' ?
$elem.innerHeight() - 2 :
$elem.data('barLength')
);
$elem.append($bar).data('bar', $bar);
$elem.on('mousedown', { elem : $elem }, function(evt) {
evt.data.elem.data('scrolling', true);
$thisBar = evt.data.elem.data('bar');
$("body").addClass("noSelect");
evt.data.elem.data('mouseStartPos', (
evt.data.elem.data('xy') == 'x' ?
evt.pageX :
evt.pageY
));
evt.data.elem.data('barPos', (
evt.data.elem.data('xy') == 'x' ?
$thisBar.position().left :
$thisBar.position().top
));
$(document).on(
'mousemove',
{ elem : evt.data.elem },
HandleMouseMove
);
});
$(document).on('mouseup', { elem : $elem }, function(evt) {
if (evt.data.elem.data('scrolling') === true) {
$("body").removeClass("noSelect");
$(document).off('mousemove');
mouseStartPos = 0;
evt.data.elem.data('scrolling', false);
}
});
HandleMouseMove = function(evt) {
console.log(evt.data.elem.data('scrolling'));
if (evt.data.elem.data('scrolling') === true) {
var mouseMovedBy = (
evt.data.elem.data('xy') == 'x' ?
evt.pageX - evt.data.elem.data('mouseStartPos') :
evt.pageY - evt.data.elem.data('mouseStartPos')
),
newBarPos = evt.data.elem.data('barPos') + mouseMovedBy;
if (newBarPos < 0) { newBarPos = 0; }
if (newBarPos > evt.data.elem.data('travelLength')) {
newBarPos = evt.data.elem.data('travelLength');
}
evt.data.elem.data('bar').css(
(
evt.data.elem.data('xy') == 'x' ?
'left' :
'top'
),
newBarPos + "px"
);
//var pct = newBarPos / evt.data.elem.data('travelLength');
}
}
});
}
// Set up the default options.
$.fn.scroller.defaults = {
barPct : 25,
onScroll : null
};
$('#scroll-track-v').scroller();
$('#scroll-track-h').scroller();
how to .postion of jquery in mm rather tham px
$("#status_div").text("Offset Left:"+ui.offset.left.toFixed(0) + " Offset Top:" + ui.offset.top.toFixed(0)
+ " Position Left: "+ui.position.left.toFixed(0) +" Position Top: "+ui.position.top.toFixed(0) );
In order to get the position in millimeters rather than pixels, the first thing you'll have to do is find out how many pixels/millimeter there are in the user's display (in each dimension). You can do that by creating an element, positioning it absolutely in mm, and then getting its position from offset (which will give it to you in pixels). For example:
var div = $("<div>").css({
position: "absolute",
left: "100mm",
top: "100mm"
}).appendTo(document.body);
var pos = div.offset();
div.remove();
var pixelsPerMM = {
x: pos.left / 100,
y: pos.top / 100
};
Live Example | Live Source
Then you can use offset (or position if you want the number relative to the parent positioning element) and do the math.
EXTEND jQuery's position function, I used its jQuery's own code and added px to mm multiplier
Explanation :-
Extend jQuery's Position method.
To extend Download http://code.jquery.com/jquery-1.10.2.js.
copy line code from line number 9632 to 9680 and add some chnage to it
1 px = 0.264583333 mm
While returning the top & left multiply it by 0.264583333
$(function (){
var docElem = document.documentElement;
jQuery.fn.extend({
position: function() {
if ( !this[ 0 ] ) {
return;
}
var offsetParent, offset,
parentOffset = { top: 0, left: 0 },
elem = this[ 0 ];
var pxToMmMultiplier = 0.264583333;
if ( jQuery.css( elem, "position" ) === "fixed" ) {
// we assume that getBoundingClientRect is available when computed position is fixed
offset = elem.getBoundingClientRect();
} else {
// Get *real* offsetParent
offsetParent = this.offsetParent();
// Get correct offsets
offset = this.offset();
if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
parentOffset = offsetParent.offset();
}
// Add offsetParent borders
parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
}
return {
top: (offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true )) * pxToMmMultiplier,
left: (offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)) * pxToMmMultiplier
};
},
offsetParent: function() {
return this.map(function() {
var offsetParent = this.offsetParent || docElem;
while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
offsetParent = offsetParent.offsetParent;
}
return offsetParent || docElem;
});
}
});
$("#testPos").text(JSON.stringify(($("#testPos").position())));
$("#testPos2").text(JSON.stringify(($("#testPos2").position())));
});
JSFIDDLE DEMO