CSS Triangle Flip On Click - javascript

Ok so i have this triangle div and when i click it, it only rotates 180deg. Ok so far so good but if i click it again it stays the same here is my code.
$('.Triangle').click(function()
{
var Location = $('.Triangle').offset().left;
$('#Account').css({"left" : Location});
$('#Account').slideToggle('fast');
$('.Triangle').css({"transform" : "rotate(180deg)"});
});

Transforms don't work that way (i.e. you can't apply it twice). You have to keep track of state:
$(".Triangle").on('click', function () {
if ($(this).data('flipped') {
$(this).data('flipped', false).css('transform', 'rotate(0deg)');
}

The 'transform' style sets the rotation of the element from it's original position. When you click it the first time, it rotates the element from 0deg to 180deg. When you click it again, it changes the rotation from 180deg to 180deg.
You need to keep a counter for the number of clicks and multiply that by your rate of rotation. Something like this should do the trick:
var count = 1;
$('.Triangle').click(function() {
var Location = $('.Triangle').offset().left;
$('#Account').css({"left" : Location});
$('#Account').slideToggle('fast');
$('.Triangle').css({"transform" : "rotate(" + (180 * count++) + "deg)"});
});`

var i = 0;
$('.Triangle').click(function() {
i++;
var Location = $('.Triangle').offset().left;
$('#Account').css({"left" : Location});
$('#Account').slideToggle('fast');
$('.Triangle').css({"transform" : "rotate(" + (i % 2 ? 0 : 180 + "deg)"});
});

Related

Find rotated div top position from left

I want find top position of rotated div from element, I can able find top position of element but I want top(Y pos) position from left(x) position.
I am used this
var degree = degree;
if (degree < 0) {
var sign = -1;
} else {
var sign = 1;
}
var numY = Math.abs(myElem.position().top + sign * ((myElem.outerHeight() / 2) - Math.sin(degree)));
var numX = 0
var bottom = myElem.position().top + myElem.outerHeight(true);
y = numY;
Thanks in Advance
Slope:20 deg, height: 20px,width:400px, left 150px i want find top position
I want to re arrange dragged items after rotation for that I am finding top position.
Please find the jsbin link drop weights into plank.
I think it makes more sense to add the draggable image into the rotated div and to let everything rotate together, rather than worrying about the position of the draggable image. Here is a jsfiddle with your code updated (I only implemented dropping on the right side): http://jsfiddle.net/brendaz/17wwtffz/
drop:
// ...
var offset = ui.draggable.offset();
var rotateOffset = $('.rotatableAra').offset();
// Take the weight out of it's parent div and add it to the rotatable area
ui.draggable.remove();
ui.draggable.addClass("dropped");
ui.draggable.addClass("rightPlankDropped");
$('.rotatableAra').append(ui.draggable);
ui.draggable.css("top", ($('.rightPlank').position().top- ui.draggable.height()).toString() + "px");
ui.draggable.css("left", (offset.left - rotateOffset.left).toString() + "px");
rightArray[ind] = $textval * pos;
// ...

Rotate element to click position

I have a project with a circle that, when clicked, rotates to a predefined position. It is almost there, but the last requirement is that it always rotates clockwise to the marker. I just can't seem to figure out how to get the right value so that when i set css transform:rotate(Xdeg), it will always go clockwise. Keeping the angle between 0 and 360 would also be a plus for another piece of this, but not necessary.
See this fiddle, javascript below as well Rotation
$(function () {
$('body').on('click', '#graph1', function (e) {
console.log('********************');
//get mouse position relative to div and center of div for polar origin
var pos = getMousePosAndCenter(e, 'graph1');
//get the current degrees of rotation from the css
var currentRotationDegrees = getCSSRotation('#graph1');
console.log('CSS Rotation Value: ' + currentRotationDegrees);
//current rotation in radians
var currentRotationRadians = radians(currentRotationDegrees);
//radians where clicked
var clickRadiansFromZero = Math.atan2(pos.y - pos.originY, pos.x - pos.originX);
//degrees the click is offset from 0 origin
var offsetDegrees = degrees(clickRadiansFromZero);
//how many degrees to rotate in css to put the mouse click at 0
var degreesToZero;
if (offsetDegrees >= 0)
degreesToZero = currentRotationDegrees - Math.abs(offsetDegrees);
else
degreesToZero = currentRotationDegrees + Math.abs(offsetDegrees);
console.log("Degrees to Zero: " + degreesToZero);
//distance in pixels from origin
var distance = calculateDistance(pos.originX, pos.originY, pos.x, pos.y);
console.log("Distance From Origin(px): " + distance);
$('#graph1').css('transform','rotate(' + degreesToZero + 'deg)')
});
});
function getMousePosAndCenter(e, id) {
var rect = document.getElementById(id).getBoundingClientRect();
return {
x: (((e.clientX - rect.left) / rect.width) * rect.width) + 0.5 << 0,
y: (((e.clientY - rect.top) / rect.height) * rect.height) + 0.5 << 0,
originY: (rect.height / 2),
originX: (rect.width / 2)
};
}
function radians(degrees) {
return degrees * Math.PI / 180;
};
function degrees(radians) {
return radians * 180 / Math.PI;
};
function calculateDistance(originX, originY, mouseX, mouseY) {
return Math.floor(Math.sqrt(Math.pow(mouseX - originX, 2) + Math.pow(mouseY - originY, 2)));
}
function getCSSRotation(id) {
var matrix = $(id).css('transform');
var values = matrix.split('(')[1],
values = values.split(')')[0],
values = values.split(',');
var a = values[0];
var b = values[1];
var c = values[2];
var d = values[3];
var cssRotation = degrees(Math.atan2(b, a));
return cssRotation;
}
Think out of the box:
We can CSS3 rotate an element with transform to i.e: 720° ...
it will make 2 clockwise turns. (OK, in our UI it can only do max a 359 turn but let's follow the math)
If we than animate it to 810°... it just means that it'll do a 90° clockwise move!
So all we need to do is always increase a degree variable to insanity!
HEY! If at some point you want to keep track of the current normalized 0-360 degree...
you can always retrieve that value doing ourCurrentInsanelyHighDegree % 360 = UIdegrees
Here's a jsBin demo
and this is all the JS you need.
function getCSSRotation( $el ) {
var matrix = $el.css('transform'),
v = matrix.split('(')[1].split(')')[0].split(','),
rds = Math.atan2(v[1], v[0]);
return rds*180/Math.PI <<0; // Degrees
}
var $EL = $("#graph1"),
w = $EL.width(),
r = w/2, // Radius
x = parseInt($EL.css("left"), 10),
y = parseInt($EL.css("top"), 10),
d = getCSSRotation( $EL ); // Initial degree (ONLY ONCE!)
$EL.on("click", function(e){
var mx = e.clientX-x-r, // Click coord X
my = e.clientY-y-r, // Click coord Y
rds = Math.atan2(-my, -mx), // Radians
md = (rds*180/Math.PI<<0) + 180; // Mouse Degrees
d += (360-md); // always increment to insanity!!
$(this).css({transform:"rotate("+ d +"deg)"});
});
#graph1 {
position:absolute;
top:10px; left:30px;
width:200px; height:200px;
background:url(//placehold.it/200x200&text=IMAGE);
transition:transform 2s ease;
transform:rotate(30deg);
transform-origin:50% 50%;
border-radius:50%;
}
#marker {
position: absolute;
top:110px;
left:230px;
border-top:1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="graph1"></div>
<div id="marker">Wherever you click, it rotates to here</div>
UPDATE:
Figuring it would be easy to do, I found it a little harder than I thought. The other answer with jQuery.animate works, but animate doesn't have the fluid framerate that css animation does (it runs on the GPU).
Here's a modified fiddle with a CSS solution: http://jsfiddle.net/2g17cjuL/2/
Keeping the angle between 0 and 360 would also be a plus
You cannot keep going forward (ie rotating by a positive number) and keep the rotation positive, however, in my fiddle offsetDegrees (the number of degrees additional rotated), or the remainder of totalDegreesdivided by 360 should give you what you need to use elsewhere.
Requrement: That it always rotates clockwise.
One thing: If you use CSS transitions, it'll calculate the shortest route for you. You want a bit more control over rotational direction, so I commented out the transition:transform 1s ease; in your CSS because we'll control this manually.
JAVASCRIPT
I borrowed this JQuery function and modified it so we can feed it a starting angle, and ending angle and it'll animate #graph1 for us. (Read the link to change duration, easing, and to use the complete callback)
$.fn.animateRotate = function(angle, start, duration, easing, complete) {
var args = $.speed(duration, easing, complete);
var step = args.step;
return this.each(function(i, e) {
args.complete = $.proxy(args.complete, e);
args.step = function(now) {
$.style(e, 'transform', 'rotate(' + now + 'deg)');
if (step) return step.apply(e, arguments);
};
$({deg: start}).animate({deg: angle}, args);
});
};
I also modified your JQuery so it won't rotate counter-clockwise: when currentRotationDegrees is greater than degreesToZero, it'll subtract 360, and then use this new value as the starting position for `animateRotate().
if(currentRotationDegrees > degreesToZero){
currentRotationDegrees -= 360;
}
$('#graph1').animateRotate(degreesToZero, currentRotationDegrees);
Here it is in action.
http://jsfiddle.net/q4nad31t/1/

Rotating a HTML element with the use of JavaScript and setTimeout to simulate a constantly moving object

I've spent a little time trying to figure this specific bit of Javascript out and why it seems to be so infuriating.
As it stands i currently have two functions. Which are shown as follows.
function startUpProc(id)
{
var log = window.document.getElementById(id);
log.style.transform = "rotate(0deg)";
var i = 10;
while ( i <= 360)
{
setTimeout('changeRotate(' + id + ',' + i + ')', 100);
i = i + 10;
}
}
function changeRotate(item, val)
{
item.style.transform = "rotate(" + val + "deg)";
item.style.webkitTransform = "rotate(" + val + "deg)";
item.style.mozTransform = "rotate(" + val + "deg)";
//alert(item.style.transform);
}
Relatively simple bit of Javascript that rotates a HTML element, in this case it's an image, this code is called with the use of a body onLoad handler as follows :
<body onLoad="startUpProc('logo');">
My intention as it stands is to have the image spin 360 degrees once which is regulated with the use of my while loop.
Where my confusion lies is in the fact that despite the timeout being set for this to take a total of 3.6 seconds to complete, it doesn't seem to even work, and there is no error being thrown, hence the alert that i placed in the function in an attempt to see what was occurring.
The alert was triggered 36 times, and visually i could see the image rotating on the page.
I found the following SO Q&A, but to no avail, the answer just wasn't applicable for the specific event i am trying to create, as the image is being rotated no matter what browser i attempt the code on, the only difference being, it only rotates when there is an alert or something in there to stop the flow of code...
Rotating a div element
Unfortunately for me, all other answers i find, seem to reference the use of JQuery, which for the moment i would like to stay away from and learn to proficiently develop in JavaScript without the use of third party extensions and plugins.
The issue is with the fact that the loop initiates the rotation 36 times, and after 100ms the rotation happens 36 times with i being set to "360".
Try something like this:
var STEP = 10;
function startUpProc(id)
{
var log = window.document.getElementById(id);
// initialized to 0 in changeRotate
makeCircle(log, 0);
}
function makeCircle(item, targetAngle) {
changeRotate(item, targetAngle);
if (targetAngle < 360) {
setTimeout(function (){
makeCircle(item, targetAngle + STEP);
}, 100);
}
}
This ensures that each rotation starts after the last one has finished.
Proof that it works
Your code initiates 36 timeouts that all fire off at once, and end up rotating the element full 360 degrees, so you might not even notice the result.
You can either fire a new timeout when the old one stops:
function changeRotate(item, val)
{
item.style.transform = "rotate(" + val + "deg)";
item.style.webkitTransform = "rotate(" + val + "deg)";
item.style.mozTransform = "rotate(" + val + "deg)";
val += 10;
setTimeout(function () {
changeRotate(item, i);
}, 100);
}
changeRotate(document.getElementById('foo'), 0);
Or you can use setInterval, which will repeat the same action every specified amount of milliseconds http://www.w3schools.com/jsref/met_win_setinterval.asp
var val = 0;
function changeRotate(item)
{
item.style.transform = "rotate(" + val + "deg)";
item.style.webkitTransform = "rotate(" + val + "deg)";
item.style.mozTransform = "rotate(" + val + "deg)";
val += 10;
}
setInterval(function () {
changeRotate(document.getElementById('foo'), 0);
}, 100);

Rotate an image without rotating element dimensions

I want to create an effect that when I click on an image element, it will rotate the content inside it but not the element's width and height(My img is 400x300). I want the element dimensions stay but the image rotate. Compressing the height or the width of the image based on the position is fine with me, as long as it does not rotate the element itself.
I have tried jQueryRotate but it seems it's only rotating the element, not the image inside it.
Is there any plugin or way for me to rotate the image without rotating the element itself?
EDIT:
My code:
$('#rotate-btn').click(function (e) {
value += 90;
if (value == 90) {
var img = document.getElementById('image_canv');
var width = img.clientWidth;
var height = img.clientHeight;
$('#image_canv').height(height);
$('#image_canv').width(width); {
animateTo: value
}
}
$('#image_canv').rotate(value);
});
});
It does rotate the image, but the position of the element moves, so it's not working out.
i take image with id myimg wrap it in div and then rotate it.
http://jsfiddle.net/D5Sz8/
Be carefull all styles applied to image maybe needed to apply on div if you dont want them to rotate along the image.
jQuery.fn.rotate = function(degrees) {
$(this).css({'-webkit-transform' : 'rotate('+ degrees +'deg)',
'-moz-transform' : 'rotate('+ degrees +'deg)',
'-ms-transform' : 'rotate('+ degrees +'deg)',
'transform' : 'rotate('+ degrees +'deg)'});
};
var i= $('img'), d= document.createElement('div'), rotation=0;
d.id='myimg'; i[0].id='';
i.wrap(d);
$('#myimg').css({'display':'inline-block', 'overflow':'hidden'});
ani();
function ani (){
i.rotate(++rotation);
requestAnimationFrame(ani);
}
Ok, so I'm assuming that you have a global variable defined as value
You can use the following code to rotate by 90 degree increments if that is what you want:
var value = 0;
$('#rotate-btn').click(function (e) {
var element = $("#image_canv");
var startDegree = value;
var endDegree = value + 90;
value += 90;
$({ i:startDegree }).animate({ i: endDegree }, {
step: function(now,fx) {
element.css({transform : 'rotate('+ now + 'deg)' });
},
duration: 1000
});
});
And here is an example of it working: http://jsfiddle.net/hQHhf/4/
If you need to rotate by some other increment, than the code will need to be changed slightly to fit those needs. But basically, your value variable should always end up being the same as endDegree so that the next rotation will start at the proper place for the image.
Here's an example of how to use it if you are wanting to do varying degrees of rotation, both positive and/or negative (For this, I changed id of rotate-btn to a class instead, and gave it its own function for rotating on any degrees):
var value = 0;
$('.rotate-btn').click(function (e) {
doRotate($(this).val(), 1000);
});
function doRotate(degrees, delay) {
var element = $("#image_canv");
var startDegree = value;
var endDegree = value + parseInt(degrees);
value = value + parseInt(degrees);
$({ i:startDegree }).animate({ i: endDegree }, {
step: function(now,fx) {
element.css({transform : 'rotate('+ now + 'deg)' });
},
duration: delay
});
}
And here is an example: http://jsfiddle.net/hQHhf/6/
Also made some minor edits to the HTML as well, like using <button> instead of <input> to send a proper value to the doRotate function and some other minor edits.
Hope this helps you get the jist of it and apply it for your needs. Also, because you are setting a width of 400, and a height of 300 on the images, while chrome does not seem effected by this, but some other browsers like firefox will be. For example, as the image rotates, the size rotates with it, this is because you don't have an equal size on both width and height of your image, so it won't look as tho its rotating naturally in all browsers. If you give both, width and height, the same size you won't have this problem.
You can use this javascript code so you can rotate your image easily. But you have only to change the image destination.
var looper;
var degrees = 0;
function rotateAnimation(el,speed){
var elem = document.getElementById(el);
if(navigator.userAgent.match("Chrome")){
elem.style.WebkitTransform = "rotate("+degrees+"deg)";
} else if(navigator.userAgent.match("Firefox")){
elem.style.MozTransform = "rotate("+degrees+"deg)";
} else if(navigator.userAgent.match("MSIE")){
elem.style.msTransform = "rotate("+degrees+"deg)";
} else if(navigator.userAgent.match("Opera")){
elem.style.OTransform = "rotate("+degrees+"deg)";
} else {
elem.style.transform = "rotate("+degrees+"deg)";
}
looper = setTimeout('rotateAnimation(\''+el+'\','+speed+')',speed);
degrees++;
if(degrees > 359){
degrees = 1;
}
document.getElementById("status").innerHTML = "rotate("+degrees+"deg)";
}
And now use the HTML code for the image:
<img id="exe" style='position:absolute;left:450px;height:300px;' src="images/example.png" alt="exe">
And it's about to finish just add another script tag:
rotateAnimation("exe",30);
This function above will move the image 30deg you can change it to 40,50... and the "exe" is the id of the image.

Why are my particles drifting? ( aka Is Math.random() broken or is it my algorithm? )

Using Javascript I'm crudely simulating Brownian motion of particles, but for some reason I don't understand my particles are drifting up and to the left.
The algorithm is pretty straight forward. Each particle is a div and I simply add or subtract a random number from each div's top and left position each round.
I read up on Math.random() a little, and I've tried to use a function that returns a random number from min to max inclussive:
// Returns a random integer between min and max
// Using Math.round() will give you a non-uniform distribution!
function ran(min, max)
{
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Here is the function for the movement of the particles:
var x, y, $elie, pos, nowX, nowY, i, $that;
function moveIt()
{
$("div.spec").each(function(i, v) {
x = ran(-5, 5);
y = ran(-5, 5);
$elie = $(v);
pos = $elie.position();
nowX = pos.left;
nowY = pos.top;
// The min and abs are to keep the particles within a box
// The drift occurs even if I remove min and abs
$elie.css("left", Math.min(Math.abs(nowX + x), 515));
$elie.css("top", Math.min(Math.abs(nowY + y), 515));
});
}
And here is how the particles are initially set up an the setInterval started.
$(function() {
$("body").append("<div/>").attr("id","box");
$elie = $("<div/>").attr("class","spec");
// Note that math random is inclussive for 0 and exclussive for Max
for (i = 0; i < 25; ++i)
{
$that = $elie.clone();
$that.css("top", ran(0, 495));
$that.css("left", ran(0, 495));
$("#box").append($that);
}
timer = setInterval(moveIt, 60);
$("input").toggle(function() {
clearInterval(timer);
this.value = " Start ";
}, function() {
timer = setInterval(moveIt, 60);
this.value = " Stop ";
});
});
My problem is that using the min and max from above ( -5, 5 ), all the particles drift up and to the left very fast.
jsFiddle example of drift (-5, 5)
Example of drift even with the removal of .min() and .abs().
To counteract this, I have to use a min and max of -1, 5.
jsFiddle example of no drift (-1, 5)
Here is the CSS for the div all the particles are contained in:
#box {
width:500px;
height:500px;
border:2px #000 solid;
position: relative; }
Here is the default CSS for each particle:
div.spec {
width:5px;
height:5px;
background-color:#00DDAA;
position:absolute; }
What is going on? Why does a min and max of -5 and 5 cause an upward and leftward drift?
A test of the random function ran() doesn't seem to show such a persistent negative drift.
jsFiddle example of testing ran()
The ran() function was taken from the MDC Math.random() page.
Your mistake is to use
pos = $elie.position();
rather than
pos = $elie.offset();
This wouldn't have made a difference had they been added to parent div, but your elements aren't properly added to a parent div, they're appended directly to the document body. So your other mistake is this:
$("body").append("<div/>").attr("id","box");
If you want the div to have id of 'box', the line should read:
$box = $("<div/>").attr("id","box");
$("body").append($box)
Otherwise you're actually giving "body" the id of "box"
EDIT:
The most efficient way to append the div would be the following (as noted by this post):
$(document.createElement('div')).appendTo('body').attr('id', 'box')
Instead of using .position(), try .offset() instead. Looks like it works.
Position.
Offset.
It works this way because you're setting the absolute 'left' and 'top' values in CSS. Instead, you can use this Example:
$elie.css("margin-left", nowX + x);
$elie.css("margin-top", nowY + y);

Categories