How to insert a button in a movable javascript element? - javascript

I would like to put the button in the movable element js; I do not know how to start, I'm a beginner and I wasnt able to find a solution.
How can I insert a button with a function call in a movable js element?
Here is a example:enter image description here
And some js code:
var pos = $('#center').position(),
radiusSat = $('#sat1').width() * 0.5,
radius = $('#center').width() * 0.5,
cx = pos.left + radius,
cy = pos.top + radius,
x, y, angle = 0, angles = [],
spc = 360 / 5,
deg2rad = Math.PI / 180,
i = 0;
for(;i < 5; i++) {
angles.push(angle);
angle += spc;
}
`/// space out radius`
radius += (radiusSat + 10);
loop();
function loop() {
for(var i = 0; i < angles.length; i++) {
angle = angles[i];
x = cx + radius * Math.cos(angle * deg2rad);
y = cy + radius * Math.sin(angle * deg2rad);
$('#sat' + i).css({left:x - radiusSat, top:y - radiusSat});
angles[i] = angles[i] + 1;
if (angles[i] > 360) angles[i] = 0;
}
requestAnimationFrame(loop);
}
http://jsfiddle.net/AbdiasSoftware/F8x4p/

You have to insert a button on the even sat elements.
After the buttons are in the DOM, you can select them and add event listeners. If you want to add the same listener for each button, you can follow my example. If you want a different listener, select the button by class $('.btn-' + index').
Working fiddle: http://jsfiddle.net/andreiTn/F8x4p/1360/

Just put a button inside the div tags or replace your divs with an a tag :)
<div id="sat0"><button>Hi</button></div>
<a class="link" href="#" id="sat1">Hi</a>
http://jsfiddle.net/Rakowu/F8x4p/1330/

Related

How to pause the animation on mouse hover on image

Please I need help to stop the animation on mouse hover and to continue on mouse out. Please see the url below to view the code. thanks
http://jsfiddle.net/AbdiasSoftware/F8x4p/
$(window).load(function(){
var pos = $('#center').position(),
radiusSat = $('#sat1').width() * 0.5,
radius = $('#center').width() * 0.5,
cx = pos.left + radius,
cy = pos.top + radius,
x, y, angle = 0,
angles = [],
spc = 360 / 25,
deg2rad = Math.PI / 180,
i = 0;
for(;i < 25; i++) {
angles.push(angle);
angle += spc;
}
/// space out radius
radius += (radiusSat + 25);
loop();
function loop() {
for(var i = 0; i < angles.length; i++) {
angle = angles[i];
x = cx + radius * Math.cos(angle * deg2rad);
y = cy + radius * Math.sin(angle * deg2rad);
$('#sat' + i).css({left:x - radiusSat, top:y - radiusSat});
angles[i] += 0.1;
if (angles[i] > 360) angles[i] = 0;
}
requestAnimationFrame(loop);
}
});
You could create a variable to keep track on whether the mouse is inside, and use events to change the variable.
Firstly, wrap your markup in a containing div so the event listener can easily be applied to all the elements:
<div class="container">
<div id="center"></div>
<div id="sat0"></div>
<div id="sat1"></div>
<div id="sat2"></div>
<div id="sat3"></div>
<div id="sat4"></div>
</div>
Then add a new variable, called mouseEntered, and set it to false.
Then create two event listeners - one to set the mouseEntered variable to true when the mouse enters the container, and one to set it to false when the mouse leaves.
document.querySelector('.container').addEventListener('mouseenter', function() {
mouseEntered = true
})
document.querySelector('.container').addEventListener('mouseleave', function() {
mouseEntered = false
})
Finally, wrap everything in your loop function, apart from requestAnimationFrame, in an if statement that checks if mouseEntered is false.
function loop() {
if (mouseEntered === false) {
for(var i = 0; i < angles.length; i++) {
angle = angles[i];
x = cx + radius * Math.cos(angle * deg2rad);
y = cy + radius * Math.sin(angle * deg2rad);
$('#sat' + i).css({left:x - radiusSat, top:y - radiusSat});
angles[i] = angles[i] + 1;
if (angles[i] > 360) angles[i] = 0;
}
}
requestAnimationFrame(loop);
}
Fiddle with the changes: http://jsfiddle.net/pbobbr5h/
try this-
var pos = $('#center').position(),
radiusSat = $('#sat1').width() * 0.5,
radius = $('#center').width() * 0.5,
cx = pos.left + radius,
cy = pos.top + radius,
x, y, angle = 0, angles = [],
spc = 360 / 5,
deg2rad = Math.PI / 180,
i = 0;
for(;i < 5; i++) {
angles.push(angle);
angle += spc;
}
stop();
/// space out radius
radius += (radiusSat + 10);
$("#center").mouseover(function(){
start();
});
$("#center").mouseout(function(){
stop();
});
var requestId;
function loop(time) {
requestId = undefined;
for(var i = 0; i < angles.length; i++) {
angle = angles[i];
x = cx + radius * Math.cos(angle * deg2rad);
y = cy + radius * Math.sin(angle * deg2rad);
$('#sat' + i).css({left:x - radiusSat, top:y - radiusSat});
angles[i] = angles[i] + 1;
if (angles[i] > 360) angles[i] = 0;
}
//requestAnimationFrame(loop);
stop();
}
function stop() {
if (!requestId) {
requestId = window.requestAnimationFrame(loop);
}
}
function start() {
if (requestId) {
window.cancelAnimationFrame(requestId);
requestId = undefined;
}
}
div {
border-radius:50%;
border:2px solid #000;
position:fixed;
}
#center {
width:200px;
height:200px;
left:100px;
top:100px;
}
#sat0, #sat1, #sat2, #sat3, #sat4 {
width:50px;
height:50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div id="center"></div>
<div id="sat0"></div>
<div id="sat1"></div>
<div id="sat2"></div>
<div id="sat3"></div>
<div id="sat4"></div>

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.

Making list items appear around the circle [duplicate]

I'm looking for a function to arrange some elements around a circle.
result should be something like :
Here's some code that should help you:
var numElements = 4,
angle = 0
step = (2*Math.PI) / numElements;
for(var i = 0; i < numElements.length; i++) {
var x = container_width/2 + radius * Math.cos(angle);
var y = container_height/2 + radius * Math.sin(angle);
angle += step;
}
It is not complete but should give you a good start.
Update: Here's something that actually works:
var radius = 200; // radius of the circle
var fields = $('.field'),
container = $('#container'),
width = container.width(),
height = container.height(),
angle = 0,
step = (2*Math.PI) / fields.length;
fields.each(function() {
var x = Math.round(width/2 + radius * Math.cos(angle) - $(this).width()/2),
y = Math.round(height/2 + radius * Math.sin(angle) - $(this).height()/2);
$(this).css({
left: x + 'px',
top: y + 'px'
});
angle += step;
});
Demo: http://jsfiddle.net/ThiefMaster/LPh33/
Here's an improved version where you can change the element count.
For an element around a centre at (x, y), distance r, the element's centre should be positioned at:
(x + r cos(2kπ/n), y + r sin(2kπ/n))
where n is the number of elements, and k is the "number" of the element you're currently positioning (between 1 and n inclusive).
I've combined ThiefMaster's fiddle with the jQuery pointAt plugin:
Demo: http://jsfiddle.net/BananaAcid/nytN6/
the code is somewhat like above.
might be interesting to some of you.
Arrange Elements In Circle (Javascript)
function arrangeElementsInCircle (elements, x, y, r) {
for (var i = 0; i < elements.length; i++) {
elements[i].scaleX = 1 / elements.length
elements[i].scaleY = 1 / elements.length
elements[i].x = (x + r * Math.cos((2 * Math.PI) * i/elements.length))
elements[i].y = (y + r * Math.sin((2 * Math.PI) * i/store.length))
}
}
Where x,y is point co-ordinates and elements is array of elements to be placed and r is radius.
Javascript only version of thiefmaster's answer
function distributeFields(deg){
deg = deg || 0;
var radius = 200;
var fields = document.querySelectorAll('.field'), //using queryselector instead of $ to select items
container = document.querySelector('#container'),
width = container.offsetWidth, //offsetWidth gives the width of the container
height = container.offsetHeight,
angle = deg || Math.PI * 3.5,
step = (2 * Math.PI) / fields.length;
console.log(width, height)
//using forEach loop on a NodeList instead of a Jquery .each,
//so we can now use "field" as an iterator instead of $(this)
fields.forEach((field)=>{
var x = Math.round(width / 2 + radius * Math.cos(angle) - field.offsetWidth/2);
var y = Math.round(height / 2 + radius * Math.sin(angle) - field.offsetHeight/2);
console.log(x, y)
field.style.left = x + 'px'; //adding inline style to the document (field)
field.style.top= y + 'px';
angle += step;
})
}
distributeFields();

Position different size circles around a circular path with no gaps

I'm creating a Canvas animation, and have managed to position x number of circles in a circular path. Here's a simplified version of the code I'm using:
var total = circles.length,
i = 0,
radius = 500,
angle = 0,
step = (2*Math.PI) / total;
for( i; i < total; i++ ) {
var circle = circles[i].children[0],
cRadius = circle[i].r,
x = Math.round(winWidth/2 + radius * Math.cos( angle ) - cRadius),
y = Math.round(winHeight/2 + radius * Math.sin( angle ) - cRadius);
circle.x = x;
circle.y = y;
angle += step;
}
Which results in this:
What I am trying to achieve is for all the circles to be next to each other with no gap between them (except the first and last). The circles sizes (radius) are generated randomly and shouldn't adjust to fit the circular path:
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
I expect there to be a gap between the first and last circle.
I'm struggling to get my head around this so any help would be much appreciated :)
Cheers!
Main creation loop :
• take a current radius
• compute the angles it cover ( = atan2(smallRadius/bigRadius) )
• move base angle by this latest angle.
http://jsfiddle.net/dj2v7mbw/9/
function CircledCircle(x, y, radius, margin, subCircleCount, subRadiusMin, subRadiusMax) {
this.x = x;
this.y = y;
this.radius = radius;
this.subCircleCount = subCircleCount;
var circles = this.circles = [];
// build top sub-circles
var halfCount = Math.floor(subCircleCount / 2);
var totalAngle = addCircles(halfCount);
// re-center top circles
var correction = totalAngle / 2 + Math.PI / 2;
for (var i = 0; i < halfCount; i++) this.circles[i].angle -= correction;
// build bottom sub-circles
totalAngle = addCircles(subCircleCount - halfCount);
// re-center bottom circles
var correction = totalAngle / 2 - Math.PI / 2;
for (var i = halfCount; i < subCircleCount; i++) this.circles[i].angle -= correction;
// -- draw this C
this.draw = function (angleShift) {
for (var i = 0; i < this.circles.length; i++) drawDistantCircle(this.circles[i], angleShift);
}
//
function drawDistantCircle(c, angleShift) {
angleShift = angleShift || 0;
var thisX = x + radius * Math.cos(c.angle + angleShift);
var thisY = y + radius * Math.sin(c.angle + angleShift);
ctx.beginPath();
ctx.arc(thisX, thisY, c.r, 0, 2 * Math.PI);
ctx.fillStyle = 'hsl(' + (c.index * 15) + ',75%, 75%)';
ctx.fill();
ctx.stroke();
}
//
function addCircles(cnt) {
var currAngle = 0;
for (var i = 0; i < cnt; i++) {
var thisRadius = getRandomInt(subRadiusMin, subRadiusMax);
var thisAngle = Math.atan2(2 * thisRadius + margin, radius);
var thisCircle = new subCircle(thisRadius, currAngle + thisAngle / 2, i);
currAngle += thisAngle;
circles.push(thisCircle);
}
return currAngle;
}
}
with
function subCircle(radius, angle, index) {
this.r = radius;
this.angle = angle;
this.index = index;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
use with
var myCircles = new CircledCircle(winWidth / 2, winHeight / 2, 350, 2, 24, 5, 50);
myCircles.draw();
animate with :
var angleShift = 0;
function draw() {
requestAnimationFrame(draw);
ctx.clearRect(0, 0, winWidth, winHeight);
myCircles.draw(angleShift);
angleShift += 0.010;
}
draw();
It's something like this, but you're gonna have to figure out the last circle's size:
http://jsfiddle.net/rudiedirkx/ufvf62yf/2/
The main logic:
var firstStep = 0, rad = 0, step = 0;
firstStep = step = stepSize();
for ( var i=0; i<30; i++ ) {
draw.radCircle(rad, step);
rad += step;
step = stepSize();
rad += step;
}
stepSize() creates a random rad between Math.PI/48 and Math.PI/48 + Math.PI/36 (no special reason, but it looked good). You can fix that to be the right sizes.
draw.radCircle(rad, step) creates a circle at position rad of size step (also in rad).
step is added twice per iteration: once to step from current circle's center to its edge and once to find the next circle's center
firstStep is important because you have to know where to stop drawing (because the first circle crosses into negative angle)
I haven't figured out how to make the last circle the perfect size yet =)
There's also a bit of magic in draw.radCircle():
var r = rRad * Math.PI/3 * 200 * .95;
The 200 is obviously the big circle's radius
The 95% is because the circle's edge length is slightly longer than the (straight) radius of every circle
I have no idea why Math.PI/3 is that... I figured it had to be Math.PI/2, which is 1 rad, but that didn't work at all. 1/3 for some reason does..... Explain that!
If you want to animate these circle sizes and keep them aligned, you'll have a hard time. They're all random now. In an animation, only the very first iteration can be random, and the rest is a big mess of cache and math =)

Arrange DIV in circle and rotate them facing outwards

Basically I've managed to layout my DIV elements into a circle shape but I've not managed to work out how to calculate the deg of rotation need to have them face OUTWARD from the center of the circle.
$(document).ready(function(){
var elems = document.getElementsByClassName('test_box');
var increase = Math.PI * 2 / elems.length;
var x = 0, y = 0, angle = 0;
for (var i = 0; i < elems.length; i++) {
var elem = elems[i];
// modify to change the radius and position of a circle
x = 400 * Math.cos(angle) + 700;
y = 400 * Math.sin(angle) + 700;
elem.style.position = 'absolute';
elem.style.left = x + 'px';
elem.style.top = y + 'px';
//need to work this part out
var rot = 45;
elem.style['-moz-transform'] = "rotate("+rot+"deg)";
elem.style.MozTransform = "rotate("+rot+"deg)";
elem.style['-webkit-transform'] = "rotate("+rot+"deg)";
elem.style['-o-transform'] = "rotate("+rot+"deg)";
elem.style['-ms-transform'] = "rotate("+rot+"deg)";
angle += increase;
console.log(angle);
}
});
does anyone have to knowledge on how I can do this.
Cheers -C
Note that rot depends on angle, except angle is in radians.
DRY, so either convert from angle to rot:
// The -90 (degrees) makes the text face outwards.
var rot = angle * 180 / Math.PI - 90;
Or just use angle when setting the style (but use radians as a unit), and drop rot's declaration:
// The -0.5*Math.PI (radians) makes the text face outwards.
elem.style.MozTransform = "rotate("+(angle-0.5*Math.PI)+"rad)";
Try this:
var rot = 90 + (i * (360 / elems.length));
Demo at http://jsfiddle.net/gWZdd/
I've added the 90 degrees at the start there to ensure the baseline of the divs face towards the centre, however you can adjust this to suit your needs.

Categories