Mouse speed on JavaScript - javascript

The code snippet below calculates the speed of the mouse cursor on the screen. It appears to work correctly, however, I have some questions about how it works.
var div = document.body.children[0],
isOverElem, cX, cY, pX, pY, cTime, pTime;
div.addEventListener('mouseover', function(event) {
if (isOverElem) return;
isOverElem = true;
pX = event.pageX;
pY = event.pageY;
pTime = Date.now();
this.addEventListener('mousemove', move);
});
div.addEventListener('mouseout', function(event) {
if ( event.relatedTarget && !this.contains(event.relatedTarget) ) {
isOverElem = false;
this.removeEventListener('mousemove', move);
this.innerHTML = '';
}
});
function move(event) {
var speed;
cX = event.pageX;
cY = event.pageY;
cTime = Date.now();
if (pTime == cTime) return; // mouseover with mousemove
speed = Math.sqrt( Math.pow(pX - cX, 2) + Math.pow(pY - cY, 2) ) / (cTime - pTime);
this.innerHTML = 'Mouse speed: ' + speed;
setTimeout(function() {
pX = cX;
pY = cY;
pTime = cTime;
}, 10);
}
div {
width: 80%;
height: 200px;
padding: 10px;
line-height: 200px;
font-size: 1.5em;
border: 2px solid red;
}
<div></div>
I don't understand the following line:
speed = Math.sqrt( Math.pow(pX - cX, 2) + Math.pow(pY - cY, 2) ) / (cTime - pTime);
Why can't this just use (pX - cX)/(cTime - pTime)? Why does it require a more complicated equation that includes Math.sqrt and Math.pow? I am interested in the algorithm and whether the script is correct.

(pX - cX) / (cTime - pTime) would be the horizontal speed.
(pY - cY) / (cTime - pTime) would be the vertical speed.
If you go horizontally and then vertically, you would travel more distance then if you would have gone straight from X to Y.
So, to get the minimal distance between X and Y, you have to use the distance formula.

Related

How to limit this move function on zoomed image without exceed the image, I make limits at 0x,0y and I need the same at x,y max limits

How can I limit this move function on zoomed image without exceed the image, I make limits at 0x,0y and I need the same at x,y max limits
var scale = 1,
panning = false,
pointX = 0,
pointY = 0,
start = { x: 0, y: 0 },
zoom = document.getElementById("zoom");
function setTransform() {
zoom.style.transform = "translate(" + pointX + "px, " + pointY + "px) scale(" + scale + ")";
}
function centerMap() {
if(pointY>=0){
pointY = 0;
}
if(pointX>=0){
pointX = 0;
}
var offX= document.getElementById("img").offsetWidth
var offY = document.getElementById("img").offsetHeight
}
zoom.onmousedown = function (e) {
e.preventDefault();
start = { x: e.clientX - pointX, y: e.clientY - pointY };
panning = true;
}
zoom.onmouseup = function (e) {
panning = false;
}
zoom.onmousemove = function (e) {
console.log(e);
e.preventDefault();
if (!panning) {
return;
}
pointX = (e.clientX - start.x);
pointY = (e.clientY - start.y);
centerMap();
console.log(pointX,pointY, e.clientY,scale,);
setTransform();
}
zoom.onwheel = function (e) {
e.preventDefault();
var xs = (e.clientX - pointX) / scale,
ys = (e.clientY - pointY) / scale,
delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);
(delta > 0) ? (scale += 0.2) : (scale -= 0.2);
if(scale<1){
scale=1;
}
pointX = e.clientX - xs * scale;
pointY = e.clientY - ys * scale;
centerMap();
setTransform();
}
This is the JS code.
In function centerMap I move the image auto to not seeing the white background, but in right and bottom I didn't find the solve, I tried to make calculations with image coords, but I need a resolvation in any resolutions
Ex: https://shorturl.at/jlpw2

Drawing lines JavaScript - Click Issue

Im having issues with this code created. The problem im having is when i click to stop the line from drawing its has a 50% chance it will work first time However It only seems work correctly if you are doing straight lines only, but i want it to work from any direction and im not 100% sure why its not working line that.
(Im using 1.12.4 jquery as im adding this into WordPress thats what is runs off)
$(function() {
var x1 = null,
y1 = null;
var offsetX = 0,
offsetY = 0;
var moveLineId = "moveLine";
function createLine(x1, y1, x2, y2, id) {
var length = Math.sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
var angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
var transform = 'rotate(' + angle + 'deg)';
offsetX = (x1 > x2) ? x2 : x1;
offsetY = (y1 > y2) ? y2 : y1;
var line = $('<div>')
.appendTo('#demo')
.addClass('line')
.css({
'position': 'absolute',
'-webkit-transform': transform,
'-moz-transform': transform,
'transform': transform
})
.width(length)
.offset({
left: offsetX,
top: offsetY
});
if(id != null) line.attr('id', id);
return line;
}
$('#demo').click(function(event) {
$(".line").removeAttr('id');
var x = event.pageX,
y = event.pageY;
if (x1 == null) {
x1 = x;
y1 = y;
} else {
x1 = y1 = null;
}
})
.delegate('.line', 'click', function(event) {
event.preventDefault();
$(this).toggleClass('active');
x1 = y1 = null;
return false;
});
$('#demo').mousemove(function(event) {
var x = event.pageX,
y = event.pageY;
if (x1 != null) {
$("#" + moveLineId).remove();
createLine(x1, y1, x, y, moveLineId)
} else {
x1 = y1 = null;
}
})
});
div.line {
transform-origin: 0 100%;
height: 3px;
/* Line width of 3 */
background: #000;
/* Black fill */
}
#demo {
border: 1px dashed #ccc;
height: 400px;
}
div.transforming-on-corner {
transform-origin: 0% 0%;
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js"
integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
crossorigin="anonymous"></script>
<h3> click two point to draw a line :</h3>
<div id="demo" class="wide">
</div>
Instead of click events, listen to mousedown and mouseup events to start / stop drawing the line.
$(function() {
var x1 = null,
y1 = null;
var offsetX = 0,
offsetY = 0;
var moveLineId = "moveLine";
// Use "mousedown" here so the start of a line is registered as soon as you press the mouse button.
$('#demo').on("mousedown", function(event) {
$(".line").removeAttr('id');
var x = event.pageX,
y = event.pageY;
if (x1 == null) {
x1 = x;
y1 = y;
} else {
x1 = y1 = null;
}
})
.delegate('.line', 'mouseup', function(event) {
// Use "mouseup" here so the start of a line is registered as soon as you release the mouse button.
event.preventDefault();
$(this).toggleClass('active');
x1 = y1 = null;
return false;
});
$('#demo').mousemove(function(event) {
var x = event.pageX,
y = event.pageY;
if (x1 != null) {
$("#" + moveLineId).remove();
createLine(x1, y1, x, y, moveLineId)
} else {
x1 = y1 = null;
}
});
function createLine(x1, y1, x2, y2, id) {
var length = Math.sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
var angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
var transform = 'rotate(' + angle + 'deg)';
offsetX = (x1 > x2) ? x2 : x1;
offsetY = (y1 > y2) ? y2 : y1;
var line = $('<div>')
.appendTo('#demo')
.addClass('line')
.css({
'position': 'absolute',
'-webkit-transform': transform,
'-moz-transform': transform,
'transform': transform
})
.width(length)
.offset({
left: offsetX,
top: offsetY
});
if (id != null) line.attr('id', id);
return line;
}
});
div.line {
transform-origin: 0 100%;
height: 3px;
background: #000;
}
#demo {
border: 1px dashed #ccc;
height: 400px;
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<div id="demo" class="wide"></div>

How do you zoom into a specific point (no canvas)?

The goal is simple, using a mousewheel, zoom into a specific point (where the mouse is). This means after zooming the mouse will be in the same roughly the same spot of the picture.
(Purely illustrative, I don't care if you use dolphins, ducks or madonna for the image)
I do not wish to use canvas, and so far I've tried something like this:
HTML
<img src="whatever">
JS
function zoom(e){
var deltaScale = deltaScale || -e.deltaY / 1000;
var newScale = scale + deltaScale;
var newWidth = img.naturalWidth * newScale;
var newHeight = img.naturalHeight * newScale;
var x = e.pageX;
var y = e.pageY;
var newX = x * newWidth / img.width;
var newY = y * newHeight / img.height;
var deltaX = newX - x;
var deltaY = newY - y;
setScale(newScale);
setPosDelta(-deltaX,-deltaY);
}
function setPosDelta(dX, dY) {
var imgPos = getPosition();
setPosition(imgPos.x + dX, imgPos.y + dY);
}
function getPosition() {
var x = parseFloat(img.style.left);
var y = parseFloat(img.style.top);
return {
x: x,
y: y
}
}
function setScale(n) {
scale = n;
img.width = img.naturalWidth * n;
img.height = img.naturalHeight * n;
}
What this attempts to do is calculate the x,y coordinates of the dolphin's eye before and after the zoom, and after calculating the distance between those two points, substracts it from the left,top position in order to correct the zoom displacement, with no particular success.
The zoom occurs naturally extending the image to the right and to the bottom, so the correction tries to pull back to the left and to the top in order to keep the mouse on that damn dolphin eye! But it definitely doesn't.
Tell me, what's wrong with the code/math? I feel this question is not too broad, considering I couldn't find any solutions besides the canvas one.
Thanks!
[EDIT] IMPORTANT
CSS transform order matters, if you follow the selected answer, make sure you order the transition first, and then the scale. CSS transforms are executed backwards (right to left) so the scaling would be processed first, and then the translation.
Here is an implementation of zooming to a point. The code uses the CSS 2D transform and includes panning the image on a click and drag. This is easy because of no change in scale.
The trick when zooming is to normalize the offset amount using the current scale (in other words: divide it by the current scale) first, then apply the new scale to that normalized offset. This keeps the cursor exactly where it is independent of scale.
var scale = 1,
panning = false,
xoff = 0,
yoff = 0,
start = {x: 0, y: 0},
doc = document.getElementById("document");
function setTransform() {
doc.style.transform = "translate(" + xoff + "px, " + yoff + "px) scale(" + scale + ")";
}
doc.onmousedown = function(e) {
e.preventDefault();
start = {x: e.clientX - xoff, y: e.clientY - yoff};
panning = true;
}
doc.onmouseup = function(e) {
panning = false;
}
doc.onmousemove = function(e) {
e.preventDefault();
if (!panning) {
return;
}
xoff = (e.clientX - start.x);
yoff = (e.clientY - start.y);
setTransform();
}
doc.onwheel = function(e) {
e.preventDefault();
// take the scale into account with the offset
var xs = (e.clientX - xoff) / scale,
ys = (e.clientY - yoff) / scale,
delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);
// get scroll direction & set zoom level
(delta > 0) ? (scale *= 1.2) : (scale /= 1.2);
// reverse the offset amount with the new scale
xoff = e.clientX - xs * scale;
yoff = e.clientY - ys * scale;
setTransform();
}
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#document {
width: 100%;
height: 100%;
transform-origin: 0px 0px;
transform: scale(1) translate(0px, 0px);
}
<div id="document">
<img style="width: 100%"
src="https://i.imgur.com/fHyEMsl.jpg"
crossOrigin="" />
</div>
This is an implementation that is closer to your original idea using top and left offsets and modifying the width attribute of the image instead of using the css transform in my other answer.
var scale = 1.0,
img = document.getElementById("image"),
deltaX = 0,
deltaY = 0;
// set the initial scale once the image is loaded
img.onload = function() {
scale = image.offsetWidth / image.naturalWidth;
}
img.onwheel = function(e) {
e.preventDefault();
// first, remove the scale so we have the native offset
var xoff = (e.clientX - deltaX) / scale,
yoff = (e.clientY - deltaY) / scale,
delta = (e.wheelDelta ? e.wheelDelta : -e.deltaY);
// get scroll direction & set zoom level
(delta > 0) ? (scale *= 1.05) : (scale /= 1.05);
// limit the smallest size so the image does not disappear
if (img.naturalWidth * scale < 16) {
scale = 16 / img.naturalWidth;
}
// apply the new scale to the native offset
deltaX = e.clientX - xoff * scale;
deltaY = e.clientY - yoff * scale;
// now modify the attributes of the image to reflect the changes
img.style.top = deltaY + "px";
img.style.left = deltaX + "px";
img.style.width = (img.naturalWidth * scale) + "px";
}
window.onresize = function(e) {
document.getElementById("wrapper").style.width = window.innerWidth + "px";
document.getElementById("wrapper").style.height = window.innerHeight + "px";
}
window.onload = function(e) {
document.getElementById("wrapper").style.width = window.innerWidth + "px";
document.getElementById("wrapper").style.height = window.innerHeight + "px";
}
html,
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
div {
overflow: hidden;
}
<div id="wrapper" style="position:relative;">
<img id="image" style="width:100%;position:absolute;top:0px;left:0px;"
src="https://i.imgur.com/fHyEMsl.jpg"
crossOrigin="" />
</div>
I liked the both posts from fmacdee. I factored the code he created out to be a reusable version that can be called on any image.
just call:
var imageScaler = new ImageScaler(document.getElementById("image"));
imageScaler.setup();
and include this code somewhere in your project:
var ImageScaler = function(img)
{
this.img = img;
this.scale = this.getImageScale();
this.panning = false;
this.start = {x: 0, y: 0};
this.delta = {x: 0, y: 0};
};
ImageScaler.prototype =
{
constructor: ImageScaler,
setup: function()
{
this.setupEvents();
},
setupEvents: function()
{
var img = this.img;
var callBack = this.onScale.bind(this);
var touchDown = this.touchDown.bind(this),
touhcMove = this.touchMove.bind(this),
touchUp = this.touchUp.bind(this);
img.onwheel = callBack;
img.onmousedown = touchDown;
img.onmousemove = touhcMove;
img.onmouseup = touchUp;
},
getImageScale: function()
{
var img = this.img;
return img.offsetWidth / img.naturalWidth;
},
getMouseDirection: function(e)
{
return (e.wheelDelta ? e.wheelDelta : -e.deltaY);
},
getOffset: function(e)
{
var scale = this.scale,
delta = this.delta;
// first, remove the scale so we have the native offset
return {
x: (e.clientX - delta.x) / scale,
y: (e.clientY - delta.y) / scale
};
},
scaleElement: function(x, y, scale)
{
var img = this.img;
img.style.top = y + "px";
img.style.left = x + "px";
img.style.width = (img.naturalWidth * scale) + "px";
},
minScale: 0.2,
updateScale: function(delta)
{
// get scroll direction & set zoom level
var scale = (delta > 0) ? (this.scale *= 1.05) : (this.scale /= 1.05);
// limit the smallest size so the image does not disappear
if (scale <= this.minScale)
{
this.scale = this.minScale;
}
return this.scale;
},
touchDown: function(e)
{
var delta = this.delta;
this.start = {x: e.clientX - delta.x, y: e.clientY - delta.y};
this.panning = true;
},
touchMove: function(e)
{
e.preventDefault();
if (this.panning === false)
{
return;
}
var delta = this.delta,
start = this.start;
delta.x = (e.clientX - start.x);
delta.y = (e.clientY - start.y);
console.log(delta, start)
this.scaleElement(delta.x, delta.y, this.scale);
},
touchUp: function(e)
{
this.panning = false;
},
onScale: function(e)
{
var offset = this.getOffset(e);
e.preventDefault();
// get scroll direction & set zoom level
var delta = this.getMouseDirection(e);
var scale = this.updateScale(delta);
// apply the new scale to the native offset
delta = this.delta;
delta.x = e.clientX - offset.x * scale;
delta.y = e.clientY - offset.y * scale;
this.scaleElement(delta.x, delta.y, scale);
}
};
I made a fiddle to view the results: http://jsfiddle.net/acqo5n8s/12/

Div isn't at right position

I am using this color wheel picker, and I'm trying to add a div as the dragger instead of having it embedded in the canvas.
I created an outer div (a wrapper), and inserted a div (dragger), then the canvas. I made the dragger div's position to absolute. Then in the redraw(e) function, I set the left and top to the following:
dragger.style.left = currentX + 'px';
dragger.style.top = currentY + 'px';
This works i.e. the dragger moves when it should, but the it's at the wrong position.
How can I get the dragger to be at the same position as the cursor?
JSFiddle
var b = document.body;
var c = document.getElementsByTagName('canvas')[0];
var a = c.getContext('2d');
var wrapper = document.getElementById('wrapper');
var dragger = document.createElement('div');
dragger.id = 'dragger';
wrapper.appendChild(dragger);
wrapper.insertBefore(dragger, c);
document.body.clientWidth; // fix bug in webkit: http://qfox.nl/weblog/218
(function() {
// Declare constants and variables to help with minification
// Some of these are inlined (with comments to the side with the actual equation)
var doc = document;
doc.c = doc.createElement;
b.a = b.appendChild;
var width = c.width = c.height = 400,
label = b.a(doc.c("p")),
input = b.a(doc.c("input")),
imageData = a.createImageData(width, width),
pixels = imageData.data,
oneHundred = input.value = input.max = 100,
circleOffset = 10,
diameter = 380, //width-circleOffset*2,
radius = 190, //diameter / 2,
radiusPlusOffset = 200, //radius + circleOffset
radiusSquared = radius * radius,
two55 = 255,
currentY = oneHundred,
currentX = -currentY,
wheelPixel = 16040; // circleOffset*4*width+circleOffset*4;
// Math helpers
var math = Math,
PI = math.PI,
PI2 = PI * 2,
sqrt = math.sqrt,
atan2 = math.atan2;
// Setup DOM properties
b.style.textAlign = "center";
label.style.font = "2em courier";
input.type = "range";
// Load color wheel data into memory.
for (y = input.min = 0; y < width; y++) {
for (x = 0; x < width; x++) {
var rx = x - radius,
ry = y - radius,
d = rx * rx + ry * ry,
rgb = hsvToRgb(
(atan2(ry, rx) + PI) / PI2, // Hue
sqrt(d) / radius, // Saturation
1 // Value
);
// Print current color, but hide if outside the area of the circle
pixels[wheelPixel++] = rgb[0];
pixels[wheelPixel++] = rgb[1];
pixels[wheelPixel++] = rgb[2];
pixels[wheelPixel++] = d > radiusSquared ? 0 : two55;
}
}
// Bind Event Handlers
input.onchange = redraw;
c.onmousedown = doc.onmouseup = function(e) {
// Unbind mousemove if this is a mouseup event, or bind mousemove if this a mousedown event
doc.onmousemove = /p/.test(e.type) ? 0 : (redraw(e), redraw);
}
// Handle manual calls + mousemove event handler + input change event handler all in one place.
function redraw(e) {
// Only process an actual change if it is triggered by the mousemove or mousedown event.
// Otherwise e.pageX will be undefined, which will cause the result to be NaN, so it will fallback to the current value
currentX = e.pageX - c.offsetLeft - radiusPlusOffset || currentX;
currentY = e.pageY - c.offsetTop - radiusPlusOffset || currentY;
// Scope these locally so the compiler will minify the names. Will manually remove the 'var' keyword in the minified version.
var theta = atan2(currentY, currentX),
d = currentX * currentX + currentY * currentY;
// If the x/y is not in the circle, find angle between center and mouse point:
// Draw a line at that angle from center with the distance of radius
// Use that point on the circumference as the draggable location
if (d > radiusSquared) {
currentX = radius * math.cos(theta);
currentY = radius * math.sin(theta);
theta = atan2(currentY, currentX);
d = currentX * currentX + currentY * currentY;
}
label.textContent = b.style.background = hsvToRgb(
(theta + PI) / PI2, // Current hue (how many degrees along the circle)
sqrt(d) / radius, // Current saturation (how close to the middle)
input.value / oneHundred // Current value (input type="range" slider value)
)[3];
dragger.style.left = currentX + 'px';
dragger.style.top = currentY + 'px';
// Reset to color wheel and draw a spot on the current location.
a.putImageData(imageData, 0, 0);
// Draw the current spot.
// I have tried a rectangle, circle, and heart shape.
/*
// Rectangle:
a.fillStyle = '#000';
a.fillRect(currentX+radiusPlusOffset,currentY+radiusPlusOffset, 6, 6);
*/
/*
// Circle:
a.beginPath();
a.strokeStyle = '#000';
a.arc(~~currentX+radiusPlusOffset,~~currentY+radiusPlusOffset, 4, 0, PI2);
a.stroke();
*/
// Heart:
a.font = "1em arial";
a.fillText("♥", currentX + radiusPlusOffset - 4, currentY + radiusPlusOffset + 4);
}
// Created a shorter version of the HSV to RGB conversion function in TinyColor
// https://github.com/bgrins/TinyColor/blob/master/tinycolor.js
function hsvToRgb(h, s, v) {
h *= 6;
var i = ~~h,
f = h - i,
p = v * (1 - s),
q = v * (1 - f * s),
t = v * (1 - (1 - f) * s),
mod = i % 6,
r = [v, q, p, p, t, v][mod] * two55,
g = [t, v, v, q, p, p][mod] * two55,
b = [p, p, t, v, v, q][mod] * two55;
return [r, g, b, "rgb(" + ~~r + "," + ~~g + "," + ~~b + ")"];
}
// Kick everything off
redraw(0);
/*
// Just an idea I had to kick everything off with some changing colors…
// Probably no way to squeeze this into 1k, but it could probably be a lot smaller than this:
currentX = currentY = 1;
var interval = setInterval(function() {
currentX--;
currentY*=1.05;
redraw(0)
}, 7);
setTimeout(function() {
clearInterval(interval)
}, 700)
*/
})();
#wrapper {
width: 400px;
height: 400px;
position: relative;
}
#dragger {
background-color: orange;
width: 15px;
height: 15px;
border-radius: 50%;
position: relative;
}
<div id='wrapper'>
<canvas id="c"></canvas>
</div>
I got it pretty close by manipulating the currentX and currentY coordinates. The commenter above is close to the solution; ~50% of the height and width must be added to the relative position. I also recommend using the z-index property on the dragger, if you want the heart to be on top and the dragger between it and the color wheel.
Final and correct version with proper offset: Fiddle
If the dragger is reduced in size from 15px to 5px, add 7 and 4px respectively:
https://jsfiddle.net/6n9zwahL/ (fixed amounts) or https://jsfiddle.net/mak3Lace/ (non-fixed, programmatic solution).
dragger.style.left = (currentX + radiusPlusOffset + (radiusPlusOffset/30)) + 'px';
dragger.style.top = (currentY + radiusPlusOffset+(radiusPlusOffset/40)) + 'px';
Preserved historical responses until I have time to edit:
Forked Fiddle
code - here it is being done manually in pixels but I'd create a variable and set it to a more accurate value by querying the browser for width:
dragger.style.left = currentX + 210 + 'px';
dragger.style.top = currentY +195 + 'px';
New Fiddle, with dragger exactly aligned to heart
New Positions:
dragger.style.left = currentX + 204 + 'px';
dragger.style.top = currentY +199 + 'px';
Added a pointer for improved ux: https://jsfiddle.net/4cLpvu2m/
To elaborate further, use the code you have for heart position:
currentX + radiusPlusOffset - 4, currentY + radiusPlusOffset + 4
and query browser for position of your dragger div. Then simply subtract x from x-dragger and y from y-dragger to get the difference. Add the difference to your dragger.style.left and so on (it happens that those numbers are ~204 and 199).
Another fork with alerts indicating x/y position values
Fork of Jessica's update, removing +/-4 to align elements:
https://jsfiddle.net/hf5k2ecg/
Just add radiusPlusOffset here:
dragger.style.left = currentX + radiusPlusOffset + 'px';
dragger.style.top = currentY + radiusPlusOffset + 'px';
https://jsfiddle.net/qsvmyh3z/1/
Also adjust/subtract the height & width of the the dragger to pin point at the right location.

Position DIV elements in circle

I need to position these 5 elements in circle. And my trigonometry knowledge is too poor to come up with a solution.
http://jsbin.com/acOSeTE/1/edit
Whoever helps please give some explanation on the math formula or forward me to a link with info about it.
I do not need a jQuery solution, since I want to learn what is behind the frameworks.
Thanks.
You'll almost certainly need CSS to position the divs with that kind of precision.
The general formula you're looking for is that for any given radian position on the circle (there are 2π radians in a circle), the x and y are:
x = originX + (Math.cos(radians) * radius);
y = originY + (Math.sin(radians) * radius);
Example: Live Copy | Live Source
CSS (you could use inline styles, I suppose):
#target {
position: absolute;
border: 1px solid black;
width: 1px;
height: 1px;
}
HTML:
<input type="button" id="theButton" value="Start/Stop">
<div id="target"></div>
JavaScript:
(function() {
var radians, maxRadians, target, radius, originX, originY, inc, timer;
radius = 50;
originX = 100;
originY = 100;
radians = 0;
maxRadians = 2 * Math.PI;
inc = 10 / 360;
target = document.getElementById("target");
positionTarget();
function positionTarget() {
var x, y;
x = originX + (Math.cos(radians) * radius);
y = originY + (Math.sin(radians) * radius);
console.log(x + "," + y);
target.style.left = x + "px";
target.style.top = y + "px";
radians += inc;
if (radians > maxRadians) {
radians -= maxRadians;
}
timer = setTimeout(positionTarget, 30);
}
document.getElementById("theButton").onclick = function() {
if (timer) {
clearTimeout(timer);
timer = 0;
}
else {
timer = setTimeout(positionTarget, 30);
}
};
})();

Categories