Making a 'div' go in a circle - javascript

I am working on a bit of code to have a dot circle around your cursor on a webpage, but I am having trouble getting the 'div' to follow the path I want; in fact, the object is not moving at all and I cannot figure out why my code does not work. Here is the code that is causing me trouble from what I've narrowed down:
<!DOCTYPE HTML>
<head>
<title>TEST SPACE</title>
<script src="jquery-1.10.2.min.js"></script>
</head>
<body>
<div id="test"></div>
<style>
#test {
background-color: black;
height: 10px;
width: 10px;
border-radius: 100%;
position: absolute;
top: 50%;
left: 50%;
}
</style>
<script>
const omega = Math.PI / 2000;
function dotRotation() {
var time = 0;
var x = 20*(Math.sin(omega*time));
var y = 20*(Math.cos(omega*time));
document.getElementById("test").style.marginLeft = x;
document.getElementById("test").style.marginTop = y;
time += 25;
};
$(document).ready(function() {
setInterval('dotRotation()',25);
});
</script>
</body>
JSFiddle

Two things are wrong
You need to move your time variable outside of the function
You need to give a unit to the value you pass to the margins so add +'px' after the variables .marginTop = y + 'px';
So altogether
const omega = Math.PI / 2000;
var time = 0;
function dotRotation() {
var x = 20*(Math.sin(omega*time));
var y = 20*(Math.cos(omega*time));
var style = document.getElementById("test").style;
style.marginLeft = x +'px';
style.marginTop = y +'px';
time += 25;
};
Demo at http://jsfiddle.net/mWC63/
Also you can cache references to the dom to avoid the searching

Your fiddle is set to run onload, it should be set up to run in the head. [drop down on left under jQuery selection.]
time is declared inside of the function so it is reset back to zero every single time it is called. Move it outside of dotRotation
var time = 0;
function dotRotation() {
var x = 20*(Math.sin(omega*time));
var y = 20*(Math.cos(omega*time));
$("#test").css({"marginLeft" : x + "px", "marginTop" : y + "px"});
time += 25;
};
$(function() {
setInterval(dotRotation,25);
});

Related

CircleType text remove whitespace after rotateY

I'm having this code:
<div id="curvy">
This is the curved text
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/circletype#2.2.0/dist/circletype.min.js"></script>
<script>
const circleType = new CircleType(document.getElementById('curvy'));
circleType.dir(-1).radius(1100);
$( document ).ready(function() {
var counter = 1;
var deg = -40;
$($($('#curvy div').find('span')).get().reverse()).each(function (index, value ) {
/* var css = $(this).css('transform');
css = css + ' rotateY(-50deg)'; */
if(counter > 5) {
var text = $(this).html();
$(this).html('');
$(this).css('display','flex');
$(this).css('vertical-align','top');
console.log(text);
//$(this).html('');
var newElem = $('<span></span>').append(text);
newElem.appendTo($(this));
/* newElem.css('position','relative');
newElem.css('z-index',counter); */
newElem.css('vertical-align','top');
newElem.css('transform','rotateY('+ deg +'deg)');
deg = deg - 2.5;
}
//console.log(value);
counter = counter + 1;
});
});
</script>
<style>
html, body {
font-size: 30px;
}
</style>
This is working fine but after I start rotating each letter using rotateY in its own span, the parent span seems to add a white space in between that I want to get rid of.
Check jsfiddle
Well I was approaching it totally incorrectly.
The issue wasnt the spans, the padding or any margins but the translateX or rotate value.
Since CircleType was using the initial size of the letter when rendering the effect, the manipulations that I did through jQuery later weren't taken into account by it.
I had to save the matrix and then decide if I would go for an increment on the rotate value or on the translateX value. I chose the latter because it felt less complicated to play with. Since I need that the rotation will begin after a specific amount of character, I use the appropriate checks.
<div id="curvy">
Curved text
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/circletype#2.2.0/dist/circletype.min.js"></script>
<script>
const circleType = new CircleType(document.getElementById('curvy'));
circleType.dir(-1).radius(900);
$( document ).ready(function() {
var counter = 1;
var deg = -40;
var padding = 0;
$($($('#curvy div').find('span')).get().reverse()).each(function (index, value ) {
var css = $(this).css('transform').replace(/[^0-9\-.,]/g, '').split(',');
var x = css[12] || css[4];
var y = css[13] || css[5];
var a = css[0];
var b = css[1];
var angle = Math.atan2(b, a) * (180/Math.PI);
if(counter > 5) {
if(counter >= 12) {
padding = padding + 6 ;
} else
padding = padding + 4 ;
var text = $(this).html();
$(this).html('');
$(this).css('display','flex');
x = parseFloat(x) + padding;
$(this).css('transform', 'translateX('+x+'px) rotate('+angle+'deg)');
var newElem = $('<span></span>').append(text);
newElem.appendTo($(this));
newElem.css('transform','rotateY('+ deg +'deg)');
deg = deg - 2.5;
}
counter = counter + 1;
});
});
</script>
<style>
html, body {
font-size: 30px;
top: 50%;
left: 50%;
position: absolute;
}
</style>
Updated jsFiddle

update .style attributes with setInterval

I'm trying to move the position of a div element at set intervals however the setInterval method executes once and then stops. setInterval() doesn't update .style.transform repeatedly every 200 milliseconds as intended.
<!DOCTYPE html>
<html>
<head>
<title>Snake game</title>
<style type="text/css">
.container {
width: 500px;
height: 500px;
border: 2px solid black;
}
#snakehead {
width: 5px;
height: 5px;
background: pink;
position: relative;
left: 0px;
}
</style>
<script type="text/javascript" src="snake.js"></script>
</head>
<body>
<div class="container">
<div id="snakehead"></div>
</div>
</body>
</html>
Javascript: Ideally I'd also like to be able to move the snakehead in any direction with vx and vy. Anyway to put those values into .style.transform = translateX()?
function snakepos() {
var x = 0;
var y = 0;
var vx = 1;
var vy = 0;
return {
move: function() {
x += vx;
y += vy;
var snakehead = document.querySelector("#snakehead");
snakedhead.style.left = "5px";
}
};
}
window.onload = function() {
console.log("hi");
var container = document.querySelector(".container");
var snake = snakepos();
setInterval(function() {
snake.move();
}, 200);
}
I know this can be done much easier in jQuery with .css but I'd to how this can be done in vanilla javascript. Thank you in advance.
snakehead.style.left = (snakedhead.style.left + "5px");
or
snakehead.style.left = (snakedhead.style.left - "5px");
I'd recommend something in a style a bit more familiar to me:
function snakepos() {
this.x = 0;
this.y = 0;
this.vx = 1;
this.vy = 1;
this.snakehead = document.querySelector("#snakehead");
var me = this;
this.move = function() {
me.x += me.vx;
me.y += me.vy;
me.snakehead.style.top = me.y + "px";
me.snakehead.style.left = me.x + "px";
};
return this;
}
console.log("hi");
var container = document.querySelector(".container");
var snake = new snakepos();
setInterval(function() {
snake.move();
}, 200);
See fiddle: https://jsfiddle.net/theredhead/td8opb0b/1/

Draggable Columns With Pure JavaScript

I'm trying to build a draggable column based layout in JavaScript and having a bit of hard time with it.
The layout comprises of 3 columns (divs), with two dragable divs splitting each. The idea is that they are positioned absolutely and as you drag the draggers, the columns' respective widths, and left values are updated.
The three columns should always span the full width of the browser (the right most column is 100% width), but the other two should remain static by default when the browser is resized (which is why i'm using px, not %).
My code isn't working as of yet, I'm relatively new to JavaScript (which is why I don't want to use jQuery).
Having said that, there must be a more efficient (and cleaner) way of achieving this with less code that works (without reaching for the $ key).
If anyone with some awesome JS skills can help me out on this I'd be super-appreciative.
Here's the fiddle I'm working on http://jsfiddle.net/ZFwz5/3/
And here's the code:
HTML
<!-- colums -->
<div class="col colA"></div>
<div class="col colB"></div>
<div class="col colC"></div>
<!-- draggers -->
<div class="drag dragA" style="position: absolute; width: 0px; height: 100%; cursor: col-resize; left:100px;"><div></div></div>
<div class="drag dragB" style="position: absolute; width: 0px; height: 100%; cursor: col-resize; left: 300px;"><div></div></div>
CSS:
body {
overflow:hidden;
}
.col {
position: absolute;
height:100%;
left: 0;
top: 0;
overflow: hidden;
}
.colA {background:red;width:100px;}
.colB {background:green; width:200px; left:100px;}
.colC {background:blue; width:100%; left:300px;}
.drag > div {
background: 0 0;
position: absolute;
width: 10px;
height: 100%;
cursor: col-resize;
left: -5px;
}
and my terrible JavaScript:
//variabe columns
var colA = document.querySelector('.colA');
var colB = document.querySelector('.colB');
var colC = document.querySelector('.colC');
//variable draggers
var draggers = document.querySelectorAll('.drag');
var dragA = document.querySelector(".dragA");
var dragB = document.querySelector(".dragB");
var dragging = false;
function drag() {
var dragLoop;
var t = this;
var max;
var min;
if (dragging = true) {
if (this == dragA) {
min = 0;
max = dragB.style.left;
} else {
min = dragA.style.left;
max = window.innerWidth;
}
dragLoop = setInterval(function () {
var mouseX = event.clientX;
var mouseY = event.clientY;
if (mouseX >= max) {
mouseX = max;
}
if (mouseY <= min) {
mouseY = min;
}
t.style.left = mouseX;
updateLayout();
}, 200);
}
}
function updateLayout() {
var posA = dragA.style.left;
var posB = dragB.style.left;
colB.style.paddingRight = 0;
colA.style.width = posA;
colB.style.left = posA;
colB.style.width = posB - posA;
colC.style.left = posB;
colC.style.width = window.innerWidth - posB;
}
for (var i = 0; i < draggers.length; i++) {
draggers[i].addEventListener('mousedown', function () {
dragging = true;
});
draggers[i].addEventListener('mouseup', function () {
clearInterval(dragLoop);
dragging = false;
});
draggers[i].addEventListener('mouseMove', function () {
updateLayout();
drag();
});
}
I see a couple of things wrong here. First of all, the mousemove event only fires on an element when the mouse is over that element. You might have better luck registering a mousemove listener on the parent of your div.drag elements, then calculating the mouse's position inside that parent whenever a mouse event happens, then using that position to resize your columns and your draggers.
Second, I'm not quite sure what you're trying to do by registering a function with setInterval. You're doing pretty well with registering event listeners; why not continue to use them to change the state of your DOM? Why switch to a polling-based mechanism? (and the function you pass to setInterval won't work anyway - it refers to a variable named event, which in that context is undefined.)
This is just a little example... I hope it can help you :)
window.onload = function() {
var myDiv = document.getElementById('myDiv');
function show_coords(){
var monitor = document.getElementById('monitor');
var x = event.clientX - myDiv.clientWidth / 2;
var y = event.clientY - myDiv.clientWidth / 2;
monitor.innerText = "X: " + x + "\n" + "Y: " + y;
myDiv.style.left = x + "px";
myDiv.style.top = y + "px";
}
document.onmousemove = function(){
if(myDiv.innerText == "YES"){show_coords();}
}
myDiv.onmousedown = function(){
myDiv.innerText = "YES";
}
myDiv.onmouseup = function(){
myDiv.innerText = "NO";
}
}

Why does my setInterval function not work second time? (JavaScript)

I made a div and I want to make it animate in a specific direction every 1 second. In the code that I have provided there's a function called resetPosition() don't worry about that, it's from my other js file that I linked in the head section(That works perfectly). I just want to know why setInterval() doesn't work correctly?
Here's my code:-
<!DOCTYPE html>
<html>
<head>
<title>Animtion</title>
<link rel="icon" href="http://3.bp.blogspot.com/-xxHZQduhqlw/T-cCSTAyLQI/AAAAAAAAAMw/o48rpWUeg2E/s1600/html-logo.jpg" type="image/jpg">
<script src="easyJs.js"></script>
<style type="text/css">
div{height:100px; width:100px; background:cyan;}
</style>
</head>
<body onload="">
<div id="demo"></div>
</body>
<script type="text/javascript">
setInterval(function(){var x = new element('demo');
x.resetPosition('absolute', '100px', '10px');}, 1000);
</script>
</html>
Here's easyJs:-
function element(elementId){
this.myElement = document.getElementById(elementId);
this.resetColor = changeColor;
this.resetSize = changeSize;
this.resetBackground = changeBackground;
this.resetPosition = changePosition;
this.resetBorder = changeBorder;
this.resetFontFamily = changeFont;
this.resetFontSize = changeFontSize;
this.resetFontStyle = changeFontStyle;
this.resetZindex = changeZindex;
this.resetClass = changeClass;
this.resetTitle = changeTitle;
this.resetMarginTop = changeMarginTop;
this.resetMarginLeft = changeMarginLeft;
this.resetSource = changeSource;
this.resetInnerHTML = changeInnerHTML;
this.resetHref = changeHref;
this.resetTextDecoration = changeTextDecoration;
this.resetFontWeight = changeFontWeight;
this.resetCursor = changeCursor;
this.resetPadding = changePadding;
this.getValue = getTheValue;
this.getName = getTheName;
this.getHeight = getTheHeight;
}
function changeColor(color){
this.myElement.style.color = color;
}
function changeSize(height, width){
this.myElement.style.height = height;
this.myElement.style.width = width;
}
function changeBackground(color){
this.myElement.style.background = color;
}
function changePosition(pos, x, y){
this.myElement.style.position = pos;
this.myElement.style.left = x;
this.myElement.style.top = y;
}
function changeBorder(border){
this.myElement.style.border = border;
}
function changeFont(fontName){
this.myElement.style.fontFamily = fontName;
}
function changeFontSize(size){
this.myElement.style.fontSize = size;
}
function changeZindex(indexNo){
this.myElement.style.zIndex = indexNo;
}
function changeClass(newClass){
this.myElement.className = newClass;
}
function changeTitle(newTitle){
this.myElement.title = newTitle;
}
function changeMarginTop(top){
this.myElement.style.marginTop = top;
}
function changeMarginLeft(left){
this.myElement.style.marginLeft = left;
}
function changeSource(newSource){
this.myElement.src = newSource;
}
function changeHref(newHref){
this.myElement.href = newHref;
}
function changeInnerHTML(newHTML){
this.myElement.innerHTML = newHTML;
}
function changeTextDecoration(decoration){
this.myElement.style.textDecoration = decoration;
}
function changeFontWeight(weight){
this.myElement.style.fontWeight = weight;
}
function changeFontStyle(style){
this.myElement.style.fontStyle = style;
}
function changeCursor(cursor){
this.myElement.style.cursor = cursor;
}
function changePadding(padding){
this.myElement.style.padding = padding;
}
function getTheValue(){
var theValue = this.myElement.value;
return theValue;
}
function getTheName(){
var theName = this.myElement.name;
return theName;
}
function getTheHeight(){
var theHeight = this.myElement.offsetHeight;
return theHeight;
}
This might help you see what and how. (Scroll down to bottom of code):
Fiddle
// Create a new EasyJS object
var el = new element('demo');
// x and y position of element
var x = 0, y = 0;
// Interval routine
setInterval(function(){
x = x + 1; // Increment x by 1
y = y + 1; // Increment y by 1
// Move element to position xy
el.resetPosition('absolute', x + 'px', y + 'px');
// Add text inside element showing position.
el.resetInnerHTML(x + 'x' + y);
// Run five times every second
}, 1000 / 5);
Explanation of original code:
setInterval(function() {
// Here you re-declare the "x" object for each iteration.
var x = new element('demo');
// Here you move the div with id "demo" to position 100x10
x.resetPosition('absolute', '100px', '10px');
// Once every second
}, 1000);
The HTML div element demo initially has no positioning styling (CSS). As such it is rendered in the default position according to the browser defaults.
In first iteration you change the style option position to absolute. That means you can move it anywhere. Secondly you move it to offset 100x10.
On the second and every iteration after that the element has position set to absolute, and it reside at 100x10. Then you say it should be moved to 100x10 – as in same place as it is.
If you do not change either x or y position (left / top), it will stay at 100x10, no mather how many times you run the loop. Run it 100 times a second for a year and it will still be at 100x10 ;-)
Think about it. Everytime the interval runs, it creates a new instance of element "demo".
This demo variable has all the default values your elements object sets it to (if any), and runs the same function each time. That's why it only moves once.
Hoist your element higher and you won't be re-declaring each interval.
<script type="text/javascript">
var x = new element('demo');
setInterval(function(){
x.resetPosition('absolute', '100px', '10px');}, 1000);
</script>
The problem isn't in the setInterval, because a copypasta'd fiddle of the same expression worked properly, so it's probably either an issue with resetPosition or maybe easyJS, though I doubt the latter.
Also, it's unclear whether demo appears on-page, as it's not added anywhere visibly.
EDIT:
If demo is appended somewhere behind the scenes, it's still piling a new demo on that spot every second

why do I need to set style in js initially rather than use existing style?

I'm learning how to drag-and-drop-move DIV's around the document in javascript. Here is a live demo:
http://jsfiddle.net/BBANc/
This works fine in Firefox and I'm not currently developing with any other browser. However, if you change set_coords_in_js to false, the demo fails.
Using Firebug to set some breakpoints, you'll notice that this line fails:
var div_left = parseInt( mov_div_1.style.left, 10 );
There is no value for mov_div_1.style.left at this point. So javascript has no idea what the existing value is, and sets div_left to 'NaN'. This style is set, and appears to be valid in the document, but there is no value in the DOM!
If you set set_coords_in_js back to true, then the above has a value and everything works perfectly as it should.
Why?
If you want to play with this locally, copy-and-paste this into your local demo file. To see the values (or lack thereof) in Firebug, set your breakpoint on line 39 or 40 and step through, hovering your mouse over the things in the line. Make sure you set set_coords_in_js to false to see the problem.
drag_move_div.html:
<!DOCTYPE html>
<html>
<head>
<title>drag move div demo</title>
<style type='text/css'>
.movDiv {
position: absolute;
left: 80px;
top: 80px;
cursor: move;
border: 1px dashed green;
padding: 1em;
}
.coordinates_display { font-weight: bold; }
</style>
<script type='text/javascript'>
window.onload = function() {
mov_div_1 = document.getElementById('mov_div_1');
set_coords_in_js = true;
function update_coordinates( newX, newY ) {
document.getElementById('coordinate_x').innerHTML = newX;
document.getElementById('coordinate_y').innerHTML = newY;
}
// why do I need to set these here in javascript when they are set in css?
if( set_coords_in_js ) {
mov_div_1.style.left = '80px';
mov_div_1.style.top = '80px';
}
update_coordinates( mov_div_1.style.left, mov_div_1.style.top );
mov_div_1.onmousedown = function(e){
mov_div_1.style.backgroundColor = 'black';
mov_div_1.style.color = 'white';
var div_left = parseInt( mov_div_1.style.left, 10 );
var div_top = parseInt( mov_div_1.style.top, 10 );
var startX = e.clientX;
var startY = e.clientY;
mov_div_1.onmousemove = function(e){
var newX = ( div_left + e.clientX - startX );
var newY = ( div_top + e.clientY - startY );
mov_div_1.style.left = newX + 'px';
mov_div_1.style.top = newY + 'px';
update_coordinates( mov_div_1.style.left, mov_div_1.style.top );
};
};
mov_div_1.onmouseup = function(){
mov_div_1.onmousemove = null;
mov_div_1.style.backgroundColor = '';
mov_div_1.style.color = '';
};
};
</script>
</head>
<body>
<div class='movDiv' id='mov_div_1'>[ Click & Drag Me Around (slowly) ]</div>
<p>Coordinates:
<span id='coordinate_x' class='coordinates_display'></span> x
<span id='coordinate_y' class='coordinates_display'></span></p>
</body>
</html>
See this related question. When you access element.style, you're not accessing the computed style (which includes stylesheet declarations), you're accessing the "style" attribute on the element itself. So when you try to get a value from mov_div_1.style, no style attribute is available, and it will come back as an empty string.
To fix this, you need to use either element.currentStyle (older IE versions, I think) or element.getComputedStyle() (modern browsers):
var computedStyle = mov_div_1.currentStyle || getComputedStyle(mov_div_1);
var div_left = parseInt( computedStyle.left, 10 );
var div_top = parseInt( computedStyle.top, 10 );
See the working jsFiddle here.

Categories