Calculate div number with distance - javascript

I'm making a carousel like a casino roulette but i can't find the way to know which div number is when i make the animation. I'm trying to calculate by distance when i make the animation loop but i doesn't work
Here's my example
https://codepen.io/anon/pen/xXbpJr?page=1&
var giftamount = 10;
var gw = $('.gift').outerWidth(true);
var giftcenter = gw/2;
var cycle = 7;
var containercenter = $('.boxwrapper').outerWidth(true)/2;
for(var i = 0; i <=5; i++)
{
var giftduplicate = $('.giftwrapper').children().clone(true,true);
$('.giftwrapper').append(giftduplicate);
}
$('.button').click(function(){
var btn = $(this);
btn.hide();
var randomgift = Math.floor((Math.random() * 10) + 1);
var distance = giftamount * gw * cycle + containercenter + (randomgift*gw) - giftcenter;
console.log(distance);
$( ".giftwrapper" ).css({left: "0"});
$('.giftwrapper').animate({left: "-="+distance},10000,function(){
alert('You Won Gift' + randomgift);
btn.show();
});
});
i get the wrong number of div, i tried a lot of combination but it doesn't work

You can try and substitute this for the distance
var distance = giftamount * cycle * gw + (randomgift*gw) - containercenter -24;
The idea is the following: with distance=- containercenter; you would move to be left-aligned with the center of the container.
To that you add a certain number of cycles giftamount * cycle * gw and finally a random number of gift elements ((randomgift*gw)).
I could not figure out where the constant -24 comes from. I hard-coded and it needs to be better defined but I guess it might depend on some margins/approximations/jQuery/CSS/??
Now you should see that the animation always stops at the same point within the gift element (in the middle). To add a random deviation you could ad a small deviation dev (that lets you stay within the gift element) like this:
var dev = Math.random()*(giftcenter+1);
var distance = giftamount * cycle * gw + (randomgift*gw) - containercenter -24 +dev;
Updated demo: https://codepen.io/anon/pen/RLNeBX

If you want to get the prize that is underneath the pointer (the vertical red bar), you actually do not have to compute the distance. Instead, you can make use of a really handy but somewhat less known DOM API method known as elementFromPoint(x, y), where you can obtain a reference to the topmost DOM node under the x,y coordinate of the page.
In order for this to work, x and y will have to correspond to the visual center of the pointer, which can we can simply calculate by using:
var $pointer = $('.rafflebox .pointer');
var pointerX = $pointer.offset().left + $pointer.width() * 0.5;
var pointerY = $pointer.offset().top + $pointer.height() * 0.5;
In jQuery's animation callback, you simply can retrieve the element (aka the prize) underneath this coordinate:
// Hide pointer first, otherwise it will be returned as the topmost element
$pointer.hide();
// Get element from pointer's visual center
var prize = document.elementFromPoint(pointerX, pointerY);
// Show it again
$pointer.show();
Now you have the correct reference to the DOM node, it is up to you to decide what kind of metadata you want to store in the "prize" DOM node. For example, you can embed a HTML5 data- attribute in your HAML:
%img{:src => "http://placehold.it/125x125?text=Prize+#{i}", :data => {:prize => "Prize #{i}"}}
...which simply stores the text Prize (n) (where n is the prize number) in the attribute data-prize, and we can access it later using:
var prize = document.elementFromPoint(pointerX, pointerY);
console.log($(prize).data('prize'));
When we replace part of your code with what I have suggested, you get this:
// Get visual center of pointer
var $pointer = $('.rafflebox .pointer');
var pointerX = $pointer.offset().left + $pointer.width() * 0.5;
var pointerY = $pointer.offset().top + $pointer.height() * 0.5;
$( ".giftwrapper" ).css({left: "0"});
$('.giftwrapper').animate({left: "-="+distance},10000,function(){
// Hide pointer first, otherwise it will be returned as the topmost element
$pointer.hide();
// Get element from pointer's visual center
var prize = document.elementFromPoint(pointerX, pointerY);
// Show it again
$pointer.show();
alert('You Won Gift ' + $(prize).data('prize'));
btn.show();
});
Here is your updated pen with a working example: https://codepen.io/terrymun/pen/dVPdMg
Updated example
There is a very small chance that the pointer will land in between prizes. To prevent this, you will want to use padding instead of margin on the .gift element:
.gift {
// Change margin to padding
padding: 0px 4px;
}
...and perform additional checks on the returned prize node:
// Hide pointer first, otherwise it will be returned as the topmost element
$pointer.hide();
// Get element from pointer's visual center
var $prize = $(document.elementFromPoint(pointerX, pointerY));
// If prize lands on the .gift element instead
if(!$prize.is('img'))
$prize = $prize.find('img')
// Show it again
$pointer.show();
alert('You Won Gift' + $prize.data('prize'));
btn.show();
The pen here is simply a fork of the original solution, but with exaggerated horizontal padding to increase the chance of the pointer landing in between iamges: https://codepen.io/terrymun/pen/rGaJmY

Related

Multistage of svg transform animation with Snap SVG

I'm building a small UI which provides users progress of downloading or loading certain information. Here is the codes so far
http://jsfiddle.net/pge1wukj/4/
var s = Snap("svg");
var movepath = s.select("#movePath").attr({
"fill":"none"
});
var dapath = s.select("#dapath").attr({
stroke: "#cdcdcd",
"stroke-width": 5,
});
var dapoints = [242,334.5, 372,334.5, 372,390, 320.5,390.5 ,308.5,421.5 ,293.5,391.5 ,242,391]
var circle = s.select("circle");
var poly = s.select("polygon");
$("a").click(function(){
circle.animate({
opacity: 0
},100);
poly.polyAnimate(dapoints,100,mina.linear,function(){
moveAlongPath(poly,{x:308,y:421},s.halfArc(308,421,135,382,50,0),100);
});
dapath.animate({
d:"M135,382.5c0,52.159,85,79.031,170.001,79.498 C 390.3,462.466,475.598,436.344,475,382.5",
},100,function(){
dapath.animate({d:"M135,382.5c0,0,85.999-0.467,171,0c85.299,0.468,169,0,169,0"
},100,function(){
dapath.animate({
d:"M135,382.292c0,0,85.999-22.759,171-22.292c85.299,0.468,169,22.292,169,22.292"
},100,function(){
dapath.animate({
d:"M136,382.415c0,0,90.999,13.118,176,13.585c85.299,0.468,164-13.585,164-13.585"
},100,function(){
dapath.animate({
d:"M135,382.5c0,0,85.999-0.467,171,0c85.299,0.468,169,0,169,0"
},500,mina.bounce,function(){
var pathclone = dapath.clone().attr({
stroke: "blue",
strokeDashoffset: 500,
strokeDasharray: 500
});
var datext = s.text(100,330,"90").attr("style","text-align: center");
var banner = s.group(poly,datext);
moveAlongPath(banner,{x:136,y:382.415},movepath,3600);
var tick = 0;
var interval = setInterval(function(){
tick += 1;
var red = Math.random()*255;
var blue = Math.random()*255;
var green = Math.random()*255;
var hex = Snap.rgb(red,green,blue);
var dadatext = $("text").text(tick+" %")
if(tick % 10 == 0){
dadatext.attr({"font-size":"30px","fill":hex});
};
if (tick >= 100){clearTimeout(interval)};
},36);
pathclone.animate({
"stroke-dashoffset":0,
},5300);
var paths = Snap.set().push(dapath,pathclone);
paths.animate({
d:"M135,382.5c0,0,30,17,42,17c10,0.208,298-17,298-17"
},300,function(){
paths.animate({
d:"M135,382.5c0,0,287,17.208,297,17c12,0,43-17,43-17"
},2900,function(){
paths.animate({d:"M135,382.5c0,0,287,17.208,297,17c12,0,43-17,43-17"},100,function(){
paths.animate({
d:"M135,382.5c0,0,85.999-0.467,171,0c85.299,0.468,169,0,169,0"
},200,function(){
$("a").off("click");
/* End of animation */
/* Ready for next transformation*/
banner.animate({
transform: "rotate(180deg)"
},200);
})
})
});
})
});
});
})
})
});
});`
At the end of the animation, the banner should rotate 180 deg on the sharp point. However it doesn't animate as i expected. Is there any solution to this ? transforming animation is intimidating and i don't fully understand it....
I think what you are missing is that you need to provide the original transform to include, otherwise it will assume you are just replacing that transform.
So with this line...
banner.animate({ transform: 'rotate(180)' },200);
What this really means is, I'm going to overwrite any current transforms and animate to a new one of rotate(180).
What you probably want is...keep any existing transforms, and now rotate(180) as well.
So you probably want something more like this...transform() with no parameters will give us the existing transform. So we can combine.
transform -> existingtransform then apply additional transform
This would look like the following.
banner.animate({ transform: banner.transform() + " s-1,1" },200);
I'm not quite sure of the rotation effect you are after (did you mean it to go upside down or back to front?), but 's-1,1' may have been what you were thinking of.
jsfiddle example
Edit: jsfiddle with alternate rotation.
Note, for this, you need to take into account 'where' the polygon is, in relation to the group, as its offset as you have moved it (and then also moved the group).
Edit: The rotation center point is quite difficult, as we have the polygon points offset (not centred around 0) and then translated. Also the group they are in is translated, so you've kinda of got 3 things going on.
To try and help understand getting the actual points, I have rewritten the rotation animation.
banner.animate({ transform: banner.transform() + "r180," + banner.getBBox(1).cx + ',' + banner.getBBox(1).y2 },200);
We get the bounding box, which calculates the centre for us. The pivot point is mid length cx, and the lowest y point is y2.
I suspect there is an easier way to get the whole thing working to reduce the transform complexity in the overall code, but there's a bit too much to break down for a question here.
jsfiddle with getBBox

My script for page loading bar, returns differently everytime of F5

I got a free source progress bar, and I wrote a script for it.
the script is here,
var nanobar = new Nanobar( options );
var loaded = 0;
var number_of_media = $("body img").length;
doProgress();
// function for the progress bar
function doProgress() {
$("img").load(function() {
loaded++;
var newWidthPercentage = (loaded / number_of_media) * 100;
nanobar.go(newWidthPercentage);
document.getElementById("showing").innerHTML = newWidthPercentage;
})
};
});
This. I think,
Loaded <-- (which gets + 1 every time an image finished loaded)
divided by
Number of total body images,,
and then multiplied by 100
So that this can make the percentage number of loading process.
Then I put that percentage number into the box of,
A Loading bar's destination point. (which is : nanobar.go( here ))
But the bar moves werid,
everytime I click the menu, it returns different.
so I made a box to display the percentage number ( in the red box you can see in the picture )
I don't understand how this kind of random numbers are coming out every time.
Please advice.
Consider....
6/7 = 0.8571428571;
0.8571428571 * 100 = 85.71428571;
So if you want to 'tidy' these long decimals, then you need to truncate the float. http://www.w3schools.com/jsref/jsref_tofixed.asp
var num = 0.8571428571 * 100;
var n = num.toFixed(2);
Then n == 85.71
I hope this helps.

Constrain jquery draggable to stay only on the path of a circle

So Im trying to make something where the user is able to drag planets along their orbits and it will continuously update the other planets. Ideally I would like this to work with ellipses too.
So far I can drag an image node with jquery and check/change the coordinates, but i cannot update the position reliably while the user is dragging the object. I know there is an axis and a rectangle containment for draggable but this doesn't really help me.
I have a site for calculating planetary orbits http://www.stjarnhimlen.se/comp/ppcomp.html and a formula i think should help me if i can figure out how to constrain the draggable object with coordinate checks Calculating point on a circle's circumference from angle in C#?
But it seems like there should be an easier way to have a user drag a sphere along a circular track while it updates coords for other spheres
here's what i have so far. It's not much
http://jsfiddle.net/b3247uc2/2/
Html
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
Js
var $newPosX = 100,
$newPosY = 100;
//create image node
var x = document.createElement("IMG");
x.src = "http://upload.wikimedia.org/wikipedia/commons/a/a4/Sol_de_Mayo_Bandera_Argentina.png";
x.width = 100;
x.height = 100;
x.id = "sun";
x.hspace = 100;
x.vspace = 100;
document.body.appendChild(x);
//coords
var text = document.createTextNode($newPosX + " " + $newPosY);
document.body.appendChild(text);
//make sun draggable and update coords
$("#sun").draggable({
drag: function (event, ui) {
$newPosX = $(this).offset().left;
$newPosY = $(this).offset().top;
}
});
//0 millisecond update for displayed coords
setInterval(check, 0);
function check() {
//tries to constrain movement, doesn't work well
/*
if ($newPosX > 300) {
$("#sun").offset({
left: 200
});
}
*/
text.nodeValue = ($newPosX + " " + $newPosY);
}
Edit:
I found this and am trying to modify it to suit my purposes but have so far not had luck.
http://jsfiddle.net/7Asn6/
Ok so i got it to drag
http://jsfiddle.net/7Asn6/103/
This is pretty close to what I want but can be moved without being clicked on directly
http://jsfiddle.net/7Asn6/104/
Ok final edit on this question. This one seems to work well and have fixed my problems. I would still very much like to hear peoples implementation ideas or ideas to make it work smoother.
http://jsfiddle.net/7Asn6/106/

Articulated animation

I am trying to figure out how to sequence the train animation so I can offset and rotate each wagon in turn around curves, for example, in Route_51 (click Test>Run[twice]) in this display. Needs Chrome or other HTML5 compliant browser.
Here is my so far 'non-complying' code (using KineticJs):
function animate(nr,path,incr,train,dirX,dirY){
var steps,offsetX,offsetY,count,a;
steps = Math.round(path[nr][2] / incr);
offsetX = path[nr][2]/steps;
offsetY = path[nr][3]/steps;
count = 0;
stage.onFrame(function(frame){
layer = train[0].getLayer();
if(count < steps){
for(a=0; a<train.length; a+=1){
incrX = train[a].getX() + offsetX * -dirX;
incrY = train[a].getY() - offsetY * -dirY;
train[a].setX(incrX);
train[a].setY(incrY);
}
layer.draw();
count += 1;
}
else{
stage.stop();
nr += 1;
if(path[nr]){
animate(nr,path,incr,train,dirX,dirY);
}
}
});
stage.start();
}
I don't seem to be able to grasp the logic (getting old).
All help appreciated. Thanks.
It seems a certain amount of time has to pass before some kind of logic emerges.
In this case it was that each loco/wagon needed its own fully incremented path for the starts and optionally finishes to be staggered. Here is a screenshot of the train in motion with the "normal" scale view inset. Room for improvement of course especially with curve coordinates.
For the animation visit http://glasier.hk and follow the KJS link.

Scale Image from current size and not from original size

Basically i am trying to scale an img with an id="room" according to a parameter wich will be +1 or -1 (and its a constant that i want to scale +-10%)
this is how i am trying
function scalar(scaleP100){ /* scaleP100 is +1 or -1 (no other posible value)*/
var addX = $('#room').width()*10*scaleP100/100;
var addY = $('#room').height()*10*scaleP100/100;
var newW = $('#room').width()+ addX;
var newH = $('#room').height() + addY;
$('img#room').css({'width':newW,'height':newH});
console.log(newW +','+ newH+':'+$('img#room').length);
return false;
}
This is inside a mouswheel detection,
So it has two stages: +10% from original size, and -10% from original size. I just don't know why it doesn't scale acording the current size (instead of the original size)
what am i doing wrong?
If you want to see what i probably didn't explain well, please check http://toniweb.us/m/3d/adam.html (but mousewheel outside the image only)
Thanks
you have two elements with same id:
<div id="room"> and <img id="room">
This should work, but I suggest you to make your html cleaner..
function scalar(scaleP100){ /* scaleP100 is +1 or -1 (no other posible value)*/
var addX = $('img#room').width()*10*scaleP100/100;
var addY = $('img#room').height()*10*scaleP100/100;
var newW = $('img#room').width()+ addX;
var newH = $('img#room').height() + addY;
$('img#room').css({'width':newW,'height':newH});
console.log(newW +','+ newH+':'+$('img#room').length);
return false;
}

Categories

Resources