I am looking at this slider http://jsfiddle.net/sCanr/1/.
(function () {
var $container = $('#container');
var $slider = $('#slider');
var sliderW2 = $slider.width()/2;
var sliderH2 = $slider.height()/2;
var radius = 200;
var deg = 0;
var elP = $('#container').offset();
var elPos = { x: elP.left, y: elP.top};
var X = 0, Y = 0;
var mdown = false;
$('#container')
.mousedown(function (e) { mdown = true; })
.mouseup(function (e) { mdown = false; })
.mousemove(function (e) {
if (mdown) {
var mPos = {x: e.clientX-elPos.x, y: e.clientY-elPos.y};
var atan = Math.atan2(mPos.x-radius, mPos.y-radius);
deg = -atan/(Math.PI/180) + 180; // final (0-360 positive) degrees from mouse position
X = Math.round(radius* Math.sin(deg*Math.PI/180));
Y = Math.round(radius* -Math.cos(deg*Math.PI/180));
$slider.css({ left: X+radius-sliderW2, top: Y+radius-sliderH2 });
// AND FINALLY apply exact degrees to ball rotation
$slider.css({ WebkitTransform: 'rotate(' + deg + 'deg)'});
$slider.css({ '-moz-transform': 'rotate(' + deg + 'deg)'});
//
// PRINT DEGREES
$('#test').html('angle deg= '+deg);
}
});
})();
What i want to do it turn this into a time line control for a html5 video. However, i am having some trouble with calculating the math behind this.
Try this:
http://jsfiddle.net/phdphil/Zv4K7/#base
It works by keeping global variables for the current position and last angle (you should change this setup to construct a specific dial with its own state). Each movement then calculates the delta (modulo 360, which requires a proper modulus function) and assumes that movements of < 180 degrees are forward movements, and > 180 degrees (remember -1 modulo 360 is 359) are negative movements. This then updates the cumulative total position:
var current = 0;
var lastAngle = 0;
// ... inside the handler
var delta = 0;
var dir = 0;
var rawDelta = mod(deg-lastAngle,360.0);
if(rawDelta < 180) {
dir = 1;
delta = rawDelta;
} else {
dir = -1;
delta = rawDelta-360.0;
}
current += delta;
lastAngle = deg;
$('#test').html('angle deg= '+current); // current instead of deg
Just for clarity, the dir variable holds the direction of this movement, which could be used to update a >> or << indicator onscreen.
The real modulus function, taken from this SO answer:
function mod(x,n) {
return ((x%n)+n)%n;
}
Related
Seen a few similar questions on here but most seem to refer to zooming and panning images, I can't find anything that answers my problem.
I'm looking to create something like https://timmywil.com/panzoom/demo/, but I want to have a DOM element zoom on click, then pan around on mouse move.
I've been able to come up with something that's very nearly there, example here. https://jsfiddle.net/kevngibsn/5okxr8n3/29/
For this I'm using Zoomooz to handle the zoom, and jQuery Pan to take care of the panning. The issue with this example is that jQuery Pan works out the size of the DOM element on page load and doesn't take into account the increased size after zoom, so mouse move doesn't pan to the edges.
Here's the code from jQuery Pan:
(function( $ ){
var getSize = function($element) {
return {
'width': $element.width(),
'height': $element.height()
};
};
var toCoords = function(x, y) {
return {'x': x, 'y': y};
};
var vectorsEqual = function(v1, v2) {
return v1.x == v2.x && v1.y == v2.y;
}
$.fn.pan = function(options) {
//Container is element this plugin is applied to;
//we're pan it's child element, content
var container = this;
var content = this.children(':first');
//Precalculate the limits of panning - offset stores
//the current amount of pan throughout
var offset = toCoords(
Number(content.css('left').replace('px', '')) | 0,
Number(content.css('top').replace('px', '')) | 0
);
var containerSize = getSize(container);
var contentSize = getSize(content);
var minOffset = toCoords(
-contentSize.width + containerSize.width,
-contentSize.height + containerSize.height
);
var maxOffset = toCoords(0, 0);
//By default, assume mouse sensitivity border
//is 25% of the smallest dimension
var defaultMouseEdge = 0.25 * Math.min(
containerSize.width,
containerSize.height
);
var settings = $.extend( {
'autoSpeedX' : 0,
'autoSpeedY' : 0,
'mouseControl' : 'kinetic',
'kineticDamping' : 0.8,
'mouseEdgeSpeed' : 5,
'mouseEdgeWidth' : defaultMouseEdge,
'proportionalSmoothing' : 0.5,
'updateInterval' : 50,
'mousePan' : null
}, options);
//Mouse state variables, set by bound mouse events below
var mouseOver = false;
var mousePanningDirection = toCoords(0, 0);
var mousePosition = toCoords(0, 0);
var dragging = false;
var lastMousePosition = null;
var kineticVelocity = toCoords(0, 0);
//Delay in ms between updating position of content
var updateInterval = settings.updateInterval;
var onInterval = function() {
if (container.hasClass('pan-off')) return false; //Temporarily disabling pan add/remove class pan-off
var mouseControlHandlers = {
'edge' : updateEdge,
'proportional' : updateProportional,
'kinetic' : updateKinetic
};
var currentHandler = settings.mouseControl;
if(!mouseControlHandlers[currentHandler]()) {
//The handler isn't active - just pan normally
offset.x += settings.autoSpeedX;
offset.y += settings.autoSpeedY;
}
//If the previous updates have take the content
//outside the allowed min/max, bring it back in
constrainToBounds();
//If we're panning automatically, make sure we're
//panning in the right direction if the content has
//moved as far as it can go
if(offset.x == minOffset.x) settings.autoSpeedX = Math.abs(settings.autoSpeedX);
if(offset.x == maxOffset.x) settings.autoSpeedX = -Math.abs(settings.autoSpeedX);
if(offset.y == minOffset.y) settings.autoSpeedY = Math.abs(settings.autoSpeedY);
if(offset.y == maxOffset.y) settings.autoSpeedY = -Math.abs(settings.autoSpeedY);
//Finally, update the position of the content
//with our carefully calculated value
content.css('left', offset.x + "px");
content.css('top', offset.y + "px");
}
var updateEdge = function() {
if(!mouseOver) return false;
//The user's possibly maybe mouse-navigating,
//so we'll find out what direction in case we need
//to handle any callbacks
var newDirection = toCoords(0, 0);
//If we're in the interaction zones to either
//end of the element, pan in response to the
//mouse position.
if(mousePosition.x < settings.mouseEdgeWidth) {
offset.x += settings.mouseEdgeSpeed;
newDirection.x = -1;
}
if (mousePosition.x > containerSize.width - settings.mouseEdgeWidth) {
offset.x -= settings.mouseEdgeSpeed;
newDirection.x = 1;
}
if(mousePosition.y < settings.mouseEdgeWidth) {
offset.y += settings.mouseEdgeSpeed;
newDirection.y = -1;
}
if (mousePosition.y > containerSize.height - settings.mouseEdgeWidth) {
offset.y -= settings.mouseEdgeSpeed;
newDirection.y = 1;
}
updateMouseDirection(newDirection);
return true;
}
var updateProportional = function() {
if(!mouseOver) return false;
var rx = mousePosition.x / containerSize.width;
var ry = mousePosition.y / containerSize.height;
targetOffset = toCoords(
(minOffset.x - maxOffset.x) * rx + maxOffset.x,
(minOffset.y - maxOffset.y) * ry + maxOffset.y
);
var damping = 1 - settings.proportionalSmoothing;
offset = toCoords(
(targetOffset.x - offset.x) * damping + offset.x,
(targetOffset.y - offset.y) * damping + offset.y
)
return true;
}
var updateKinetic = function() {
if(dragging) {
if(lastMousePosition == null) {
lastMousePosition = toCoords(mousePosition.x, mousePosition.y);
}
kineticVelocity = toCoords(
mousePosition.x - lastMousePosition.x,
mousePosition.y - lastMousePosition.y
);
lastMousePosition = toCoords(mousePosition.x, mousePosition.y);
}
offset.x += kineticVelocity.x;
offset.y += kineticVelocity.y;
kineticVelocity = toCoords(
kineticVelocity.x * settings.kineticDamping,
kineticVelocity.y * settings.kineticDamping
);
//If the kinetic velocity is still greater than a small threshold, this
//function is still controlling movement so we return true so autopanning
//doesn't interfere.
var speedSquared = Math.pow(kineticVelocity.x, 2) + Math.pow(kineticVelocity.y, 2);
return speedSquared > 0.01
}
var constrainToBounds = function() {
if(offset.x < minOffset.x) offset.x = minOffset.x;
if(offset.x > maxOffset.x) offset.x = maxOffset.x;
if(offset.y < minOffset.y) offset.y = minOffset.y;
if(offset.y > maxOffset.y) offset.y = maxOffset.y;
}
var updateMouseDirection = function(newDirection) {
if(!vectorsEqual(newDirection, mousePanningDirection)) {
mousePanningDirection = newDirection;
if(settings.mousePan) {
settings.mousePan(mousePanningDirection);
}
}
}
this.bind('mousemove', function(evt) {
mousePosition.x = evt.pageX - container.offset().left;
mousePosition.y = evt.pageY - container.offset().top;
mouseOver = true;
});
this.bind('mouseleave', function(evt) {
mouseOver = false;
dragging = false;
lastMousePosition = null;
updateMouseDirection(toCoords(0, 0));
});
this.bind('mousedown', function(evt) {
dragging = true;
return false; //Prevents FF from thumbnailing & dragging
});
this.bind('mouseup', function(evt) {
dragging = false;
lastMousePosition = null;
});
//Kick off the main panning loop and return
//this to maintain jquery chainability
setInterval(onInterval, updateInterval);
return this;
};
})( jQuery );
I'd at about my limit on this one, any advice on how to get that panning the whole element?
i'm trying to make dot that follows mouse cursor. It was all working, but when i rotated it a bit it all messed up, because bounding box has changed.
I was using this:
http://en.wikipedia.org/wiki/Rotation
(That's why i initially negated y, and than negated new value again)
I will need to read how far that dot is from center and it's angle (but related to the initial "0" rotation state)
I have to add something to rPX based on angle, but i don't know how to calculate it. Can anyone relate?
Inner div is only for creating center of coordinate system.
https://jsfiddle.net/jre86rdd/14/
var currentMousePosition = {
x:0,
y:0
}
var angle = Math.PI/6
document.addEventListener("mousemove",function(event){
currentMousePosition.x = event.clientX;
currentMousePosition.y = event.clientY;
applyMovement(event)
})
function applyMovement(event){
var rPX = event.clientX - getElementOffSetFromParentLeft(document.getElementById("light").parentNode) - 5;
var rPY = -(event.clientY - getElementOffSetFromParentTop(document.getElementById("light").parentNode) - 5);
var XinCircle = rPX*Math.cos(angle)-rPY*Math.sin(angle)
var YinCircle = rPX*Math.sin(angle)+rPY*Math.cos(angle)
if(XinCircle > -70 && XinCircle < 70)
document.getElementById("light").style.left = XinCircle + "px";
if(rPY > -70 && rPY < 70)
document.getElementById("light").style.top = -YinCircle + "px";
//console.log(rPX + " X " + XinCircle )
//console.log(rPY + " Y " + YinCircle )
}
var getElementOffSetFromParentLeft = function (htmlElement) {
var parentRect = htmlElement.parentNode.getBoundingClientRect(),
bodyRect = document.body.getBoundingClientRect();
console.log(parentRect.left)
//I need to add something here, it's 75 for 30, i have no idea how i have calculated it
return parentRect.left - bodyRect.left + 75;
}
var getElementOffSetFromParentTop = function (htmlElement) {
var parentRect = htmlElement.parentNode.getBoundingClientRect(),
bodyRect = document.body.getBoundingClientRect();
return parentRect.top - bodyRect.top;
}
For the mouse movement, it's a very simplified code using jQuery:
$('.wrapper, .outer').mousemove(function(e){
$('#light').css('left', e.pageX);
$('#light').css('top', e.pageY);
});
https://jsfiddle.net/jre86rdd/30/
Tell me if this was what you wanted.
Edit: Also you need to move the light div outside of the wrapper class because it is affected by your CSS
With your new comment, this is my answer:
HTML:
<div class="wrapper">
<div class="outer">
<div class="inner">
</div>
</div>
</div>
<div class="dot" id="light"></div>
JS:
var timeout;
var down = false;
var inside = 0; //Not a boolean because .outer can trigger false when .wrapper is true
$(document).mousedown(function() {
down = true;
}).mouseup(function() {
down = false;
}).mouseleave(function() {
down = false;
});
$('.wrapper, .outer').mouseenter(function(){
inside++;
}).mouseleave(function() {
inside--;
});
$('#light').mousedown(function () {
var x, y;
timeout = setInterval(function () {
if(down){
$(document).mousemove(function(event) {
x = event.pageX;
y = event.pageY;
});
if (inside > 0){
$('#light').css('left', x - 5);
$('#light').css('top', y - 5);
}
}
else
{
clearTimeout(timeout);
}
}, 20);
});
https://jsfiddle.net/jre86rdd/124/
Everything was going smoothly until now. I want to have this hor() function reverse after 20 seconds. The original hor() function grabs an image offscreen and moves it horizontally from the left to the center of the page. I'd like to create a function that does the opposite after 20 seconds. The "after 20 seconds" part is giving me the most grief. If you could show me what a new function would look like or an 'else' addition to the current function that would be great. Thanks.
<script language="JavaScript" type="text/JavaScript">
var x = -500;
var y = 100;
function hor(val) {
if (x <= 500){
x = x + val;
document.getElementById("pos").style.left = x + "px";
setTimeout("hor(5)", 10);
}
}
</script>
<style type="text/css">
<!--
#pos {
position: absolute;
left: -500px;
top: 100px;
z-index: 0;
}
</style>
<body onLoad="setTimeout('hor(5)',5000)">
<div id="pos">
<img src="image.jpg">
</div>
Perhaps you could try changing the script to this:
// Define variables
var x = -500,
y = 100,
direction = 1;
// Function which moves "pos" element
function hor(val) {
// Move by specified value multiplied by direction
x += val * direction;
if(x > 500){
x = 500;
// Reverse direction
direction = -1;
} else if(x < -500){
x = -500;
// Reverse direction, once again
direction = 1;
}
// Move element
document.getElementById("pos").style.left = x + "px";
// Continue loop
setTimeout("hor("+val+")", 10);
}
This code will continue moving the pos element by the specified value until x greater than 500, at which point it will switch direction, then continue until x reaches -500, and so on.
EDIT:
This code will fix that issue with 20 seconds (I had thought that the 500 pixel thing computed to 20 seconds, lol).
// Define variables
var x = -500,
y = 100,
direction = 1;
firstCall = true;
timeElapsed = 0;
// Function which moves "pos" element
function hor(val) {
// Don't let the first call count!
if(!firstCall)timeElapsed += 10;
else firstCall = false;
if(timeElapsed >= 2000){
// Reverse direction
direction *= -1;
timeElapsed = 0;
}
// Move by specified value multiplied by direction
x += val * direction;
// Move element
document.getElementById("pos").style.left = x + "px";
// Continue loop
setTimeout("hor("+val+")", 10);
}
Try this. Here the img is moved horizontally and after sometime it is reverted back to its original position.
<script>
var x = -500;
var y = 100;
var op;
function hor(val) {
if (x <= 500 && x>=-500) {
x = x + val;
document.getElementById("pos").style.left = x + "px";
setTimeout(function(){hor(val);},10);
}
}
$(document).ready(function(){
setTimeout(function(){hor(5);},1000);
setInterval(function(){
setTimeout(function(){hor(-5);},1000);
},2000);
});
</script>
I have changed the timings for testing purpose only, you can change it back.
So I am making a little game where you have to press Ctrl to stop a div from jumping randomly.
However I can't get it working...
The jumpRandom function works fine, until i put the randomJump(){return false;}; inside the if (event.ctrlKey) {}. What should I do to get it working?
js:
$(document).ready(function() {
function randomFromTo(from, to){
return Math.floor(Math.random() * (to - from + 1) + from);
}
$( "#goal" ).bind('mouseenter keypress', function(event) {
if (event.ctrlKey) {
randomJump(){return false;};
}
});
$('#goal').mouseenter(randomJump);
function randomJump(){
/* get Window position and size
* -- access method : cPos.top and cPos.left*/
var cPos = $('#pageWrap').offset();
var cHeight = $(window).height() - $('header').height() - $('footer').height();
var cWidth = $(window).width();
// get box padding (assume all padding have same value)
var pad = parseInt($('#goal').css('padding-top').replace('px', ''));
// get movable box size
var bHeight = $('#goal').height();
var bWidth = $('#goal').width();
// set maximum position
maxY = cPos.top + cHeight - bHeight - pad;
maxX = cPos.left + cWidth - bWidth - pad;
// set minimum position
minY = cPos.top + pad;
minX = cPos.left + pad;
// set new position
newY = randomFromTo(minY, maxY);
newX = randomFromTo(minX, maxX);
$('#goal').fadeOut(50, function(){
$('#goal').fadeIn(700);
});
$('#goal').animate({
left: newX,
top: newY,
duration: 500
});
}
});
Try this:
$("#goal").bind('mouseenter keypress', function (e) {
randomJump(e);
});
function randomJump(e) {
if (!e.ctrlKey) {
//do normal stuff
} else {
//depending on how permanent you need this to be...
//$("#goal").unbind('mouseenter keypress');
}
return !e.ctrlKey;
}
I want to calculate the top-right position of div , i can calculate it, if it is not rotated with:
$("div").offset().top + $("div").width();
But when we rotate div then , how we can calculte top-right position ?
Rotate code:
$("div").slider({
slide: function(e,u){
$(this).rotate({ angle : u.value});
}
});
You can try this:
JavaScript
$(".slider").slider({
min: 0,
max: 180,
slide: function(e,u){
$(this).rotate({ angle : u.value});
calculateTopLeft(u.value);
}
});
var pointer = $('.pointer');
var slider = $('.slider');
var center = { top: slider.offset().top, left: slider.offset().left + slider.width() / 2 };
var offset = slider.offset();
function calculateTopLeft(angle) {
var radius = slider.width() / 2,
radians = (angle * Math.PI) / 180;
pointer.css({
left: center.left + radius * Math.cos(radians),
top: center.top + radius * Math.sin(radians)
});
}
//Equation of the circle
//x = a + r * cos(t);
//y = b + r * sin(t);
And here is an example: http://jsfiddle.net/zFRwM/2/
Probably you'll need a little correction but I think that the idea is clear.
use this in your javascript
function getPosition(obj){
var topValue= 0,leftValue= 0;
while(obj){
leftValue+= obj.offsetLeft;
topValue+= obj.offsetTop;
obj= obj.offsetParent;
}
finalvalue = leftValue + "," + topValue;
return finalvalue;
}
var d = document.getElementById('divname');
getPosition(d);
Then try this,it use .position() function in jquery use this
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
var p = $("div");
var position = p.position();
$("div").text( "Right: " + position.right + ", top: " + position.top );
</script>
Remove transform, retrieve offset, put transform back:
$.fn.offsetNoTransform = function(e)
{
var m = this.css('transform');
this.css('transform', '');
var off = this.offset();
this.css('transform', m);
return off;
}