I'm stuck using Raphael JS : I want to make a basic animation that draws concentric lines while loading some stuff.
So, I made this function :
function loadingButton(width, height) {
width = width ? width : 240;
height = height ? height : 240;
var loadingButton = Raphael("loading-button", width, height);
var center = 120,
xloc = center,
yloc = center,
R = 120,
imgW = 124,
imgH = 140;
var lines;
var percent = loadingButton.text(center, center, '0');
percent.attr({'font-size': 36, 'fill': '#fff'});
var count = 0;
var interval = setInterval(function(){
if( count <= 100){
var start_x = center+Math.round((center-30)*Math.cos(4*count*Math.PI/200));
var start_y = center+Math.round((center-30)*Math.sin(4*count*Math.PI/200));
var end_x = center+Math.round((center-10)*Math.cos(4*count*Math.PI/200));
var end_y = center+Math.round((center-10)*Math.sin(4*count*Math.PI/200));
lines = loadingButton.path("M"+start_x+" "+start_y+"L"+end_x+" "+end_y).attr({"stroke":"#FFF","stroke-width":"1"});
percent.attr({text: count});
count++;
}
else {
clearInterval(interval);
}
}, 50);
};
With live demo here : http://jsfiddle.net/rfuqjL65/
The thing is, as you can see on the fiddle, the animation is starting on the first quarter (90°), not on the top (0°).
And well, the problem is : I want the animation starts on the top.
Any ideas ?
I can't get your fiddle running, but:
You can add/substract Math.PI/2 to the angle argument (in radians) for Math.cos and Math.sin in your coordinate variables, that should do the trick!
http://jsfiddle.net/rfuqjL65/2/
I change your code. And this worked.
And also
var start_x = center+Math.round((center-30)*Math.sin(4*count*Math.PI/200));
var start_y = center-Math.round((center-30)*Math.cos(4*count*Math.PI/200));
var end_x = center+Math.round((center-10)*Math.sin(4*count*Math.PI/200));
var end_y = center-Math.round((center-10)*Math.cos(4*count*Math.PI/200));
Related
I am currently trying to rotate this div toward the mouse pointer, and it hasnt worked. I even tried going to a chat room about it. Currently, It sorta rotates toward the mouse...here is my code so far:
var x = 0;
var y = 0;
document.addEventListener("mousemove", function(event){
x = Number(event.pageX);
y = Number(event.pageY);
}, false);
setInterval(function(){
var boxX = document.getElementById('temp').style.left;
boxX = Number(boxX.substring(0, boxX.length - 1));
var boxX = screen.width * ((boxX)/100);
var boxY = document.getElementById('temp').style.top;
boxY = Number(boxY.substring(0, boxY.length - 1));
var boxY = screen.width * ((boxY)/100);
var slope = [Math.round(x - boxX),Math.round(y - boxY)];
//x,y
var angle = Math.round(Math.atan(slope[1]/slope[0]) *100) ;
document.getElementById('temp').style.transform = "translate(-50%,-50%) rotate(0deg)";
document.getElementById('temp').style.transform = "translate(-50%,-50%) rotate("+angle+"deg)";
}, 500);
I have a route like a vertical snake. (like this http://www.my-favorite-coloring.net/Images/Large/Animals-Reptiles-Snake-31371.png )
How I can move element (circle 10x10) on route by X and Y position on scroll?
Horizonal is ok :
var coin = $('#coin');
$(window).scroll(function(){
var coinTop = coin.css('top'),
cointLeft = coin.css('left');
if($(window).scrollTop() > 100 && $(window).scrollTop() < 600){
$("#coin").css({ "left": contLeft + 'px' });
};
});
But how I cat move it smoothly along the route?
I would suggest using a vector (SVG) library, namely raphael.js for the animation part.
In raphael.js you can define a path and then animate any object along the length of that path.
Please see the example and a corresponding stackoverflow thread for better understanding:
http://raphaeljs.com/gear.html
How to animate a Raphael object along a path?
Compared to the thread, you need to attach the animation on the onScroll event, as opposed to attaching it to a Interval.
Edit:
Adding the relevant code snippet from the link, as the commenter suggested:
HTML:
<div id="holder"></div>
JS:
var e;
var myPath;
var animation; //make the variables global, so you can access them in the animation function
window.onload = function() {
var r = Raphael("holder", 620, 420),
discattr = {
fill: "#666",
stroke: "none"
};
function curve(x, y, zx, zy, colour) {
var ax = Math.floor(Math.random() * 200) + x;
var ay = Math.floor(Math.random() * 200) + (y - 100);
var bx = Math.floor(Math.random() * 200) + (zx - 200);
var by = Math.floor(Math.random() * 200) + (zy - 100);
e = r.image("http://openclipart.org/image/800px/svg_to_png/10310/Odysseus_boy.png", x, y, 10, 10);
var path = [["M", x, y], ["C", ax, ay, bx, by, zx, zy]];
myPath = r.path(path).attr({
stroke: colour,
"stroke-width": 2,
"stroke-linecap": "round",
"stroke-opacity": 0.2
});
controls = r.set(
r.circle(x, y, 5).attr(discattr), r.circle(zx, zy, 5).attr(discattr));
}
curve(100,100,200,300,"red");
animation = window.setInterval("animate()", 10); //execute the animation function all 10ms (change the value for another speed)
};
var counter = 0; // a counter that counts animation steps
function animate(){
if(myPath.getTotalLength() <= counter){ //break as soon as the total length is reached
clearInterval(animation);
return;
}
var pos = myPath.getPointAtLength(counter); //get the position (see Raphael docs)
e.attr({x: pos.x, y: pos.y}); //set the circle position
counter++; // count the step counter one up
};
Update:
I've recently used pathAnimator for the same task. Be careful about the performance though, a complicated animation might be quite intensive.
I would like to draw a line starting on a given point and crossing two other points. To do this, I get the x and y coordinates of these points, and then I drawn. This is what my code should do :
JS:
function getPosition(element)
{
var left = 0;
var top = 0;
var e = document.getElementById(element);
while (e.offsetParent != undefined && e.offsetParent != null)
{
left += e.offsetLeft + (e.clientLeft != null ? e.clientLeft : 0);
top += e.offsetTop + (e.clientTop != null ? e.clientTop : 0);
e = e.offsetParent;
}
return new Array(left,top);
}
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var point1 = getPosition('firstGalaxy');
var point2 = getPosition('secondGalaxy');
var point3 = getPosition('lastGalaxy');
console.log(point1);
console.log(point2);
console.log(point3);
ctx.beginPath();
ctx.moveTo(point1[0], point1[1]);
ctx.lineTo(point2[0], point2[1]);
ctx.lineTo(point3[0], point3[1]);
ctx.stroke(2);
ctx.closePath();
HTML:
<canvas id="myCanvas" style="position:absolute;" class="constellation">
The values printed in my console seems to be good, but the result is a mess.
Here is a picture of the result
The grey square on the right is the result, and the red line is what I would like to get.
I don't even know why I get a square because I am using "stroke()".
Can anyone tell me what is wrong with my code?
Change ctx.stroke(2) to ctx.stroke(), add ctx.strokeStyle="red" to change the line's color. And, add </canvas> to the HTML.
HTML:
<canvas id="myCanvas" style="position:absolute;" class="constellation"></canvas>
Javascript:
function getPosition(element)
{
var left = 0;
var top = 0;
var e = document.getElementById(element);
while (e.offsetParent != undefined && e.offsetParent != null)
{
left += e.offsetLeft + (e.clientLeft != null ? e.clientLeft : 0);
top += e.offsetTop + (e.clientTop != null ? e.clientTop : 0);
e = e.offsetParent;
}
return new Array(left,top);
}
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var point1 = getPosition('firstGalaxy');
var point2 = getPosition('secondGalaxy');
var point3 = getPosition('lastGalaxy');
console.log(point1);
console.log(point2);
console.log(point3);
ctx.beginPath();
ctx.moveTo(point1[0], point1[1]);
ctx.lineTo(point2[0], point2[1]);
ctx.lineTo(point3[0], point3[1]);
ctx.strokeStyle="red";
ctx.stroke();
ctx.closePath();
A few directions :
1) to debug, be sure your points are at the right place by drawing them using something like :
function drawPoint(ctx, pt, color, pointSize ) {
ctx.fillStyle = color || '#F88';
var pointSize = pointSize || 2;
var x = pt[0], y=pt[1];
ctx.fillRect(x - pointSize/2, y-pointSize/2, pointSize, pointSize);
}
2) use getBoundingClientRect to retrieve a control position with maximum reliability.
function getPosition(element, provideCenter)
{
var elementBoundingRect = element.getBoundingClientRect();
var point = [elementBoundingRect.left, elementBoundingRect.top];
if (provideCenter) {
point[0] += (elementBoundingRect.right - elementBoundingRect.left) /2;
point[1] += (elementBoundingRect.bottom - elementBoundingRect.top ) /2;
}
return point;
}
3) Be sure the canvas covers all the screen and do simple unit tests on various parts of the screen using getPosition and drawPoint on several visible html items.
Edit : The code provided in 1) is good. If in doubt, look at this test here :
http://jsbin.com/aDimoJI/1/
You must be able to draw points anywhere before going anywhere further.
Be sure your canvas is on top of everything else for this test, so you'll have to handle this issue...
Basically I want to scroll a object along path. I've seen several threads looking for similar solution not using paper.js but i was wondering if this possible with paper.js. Or can someone give me a working jsfiddle of object follow svg curve because I couldn't get any thing to work. I ultimately want to have a chain of divs follow the path.
// vars
var point1 = [0, 100];
var point2 = [120, 100];
var point3 = [120, 150];
// draw the line
var path = new Path();
path.add(new Point(point1), new Point(point2), new Point(point3));
path.strokeColor = "#FFF";
path.closed = true;
// draw the circle
var circle = new Path.Circle(0,100,4);
circle.strokeColor = "#FFF";
// target to move to
var target = point2;
// how many frame does it take to reach a target
var steps = 200;
// defined vars for onFrame
var dX = 0;
var dY = 0;
// position circle on path
circle.position.x = target[0];
circle.position.y = target[1];
function onFrame(event) {
//check if cricle reached its target
if (Math.round(circle.position.x) == target[0] && Math.round(circle.position.y) == target[1]) {
switch(target) {
case point1:
target = point2;
break;
case point2:
target = point3;
break;
case point3:
target = point1;
break;
}
// calculate the dX and dY
dX = (target[0] - circle.position.x)/steps;
dY = (target[1] - circle.position.y)/steps;
}
// do the movement
//circle.position.x += dX;
//circle.position.y += dY;
}
Here is the jsfiddle:
http://jsfiddle.net/J9xgY/12/
Thanks!
You can find a point along a path with path.getPointAt(offset) where offset is measured in points along the length of the path. If you can calculate the position of a slider along its track, you can multiply that by the path.length to get an offset.
You can do this with an HTML slider or with a canvas element, as shown here:
// vars
var point1 = [0, 100];
var point2 = [120, 100];
var point3 = [120, 150];
// draw the line
var path = new Path();
path.add(new Point(point1), new Point(point2), new Point(point3));
path.strokeColor = "#FFF";
path.closed = true;
// draw the circle
var circle = new Path.Circle(0,100,4);
circle.strokeColor = "#FFF";
// slider
var sliderLine = new Path(new Point(10,30.5), new Point(210, 30.5));
sliderLine.strokeColor = '#FFF';
var sliderKnob = new Path.Circle(new Point(10,30.5), 5);
sliderKnob.fillColor = '#FFF';
var sliderHit = false;
function onMouseDown(event) {
if (event.item == sliderKnob) sliderHit = true;
}
function onMouseDrag(event) {
if (sliderHit === true) {
if (event.point.x > 10 && event.point.x < 210) {
sliderKnob.position.x = event.point.x;
}
else if (event.point.x < 11) {
sliderKnob.position.x = 10;
}
else if (event.point.x > 209) {
sliderKnob.position.x = 210;
}
// Get offset and set circle position
var percent = ( sliderKnob.position.x - 10 ) / 200;
circle.position = path.getPointAt(path.length * percent);
}
}
function onMouseUp(event) {
sliderHit = false;
}
jsfiddle: http://jsfiddle.net/J9xgY/13/
Click and drag the filled circle along the line to move the circle along the triangle.
I'm working on a small animation where the user drags a circle and the circle returns back to the starting point. I figured out a way to have the circle return to the starting point. The only problem is that it will hit one of the sides of the frame before returning. Is it possible for it to go straight back (follow the path of a line drawn between the shape and starting point).
The other problem is that my setInterval doesn't want to stop. If you try pulling it a second time it would pull it back before you release your mouse. It also seems to speed up after every time. I have tried using a while loop with a timer but the results weren't as good. Is this fixable?
var paper = Raphael(0, 0, 320, 200);
//var path = paper.path("M10 10L40 40").attr({stoke:'#000000'});
//var pathArray = path.attr("path");
var circle = paper.circle(50, 50, 20);
var newX;
var newY;
circle.attr("fill", "#f00");
circle.attr("stroke", "#fff");
var start = function () {
this.attr({cx: 50, cy: 50});
this.cx = this.attr("cx"),
this.cy = this.attr("cy");
},
move = function (dx, dy) {
var X = this.cx + dx,
Y = this.cy + dy;
this.attr({cx: X, cy: Y});
},
up = function () {
setInterval(function () {
if(circle.attr('cx') > 50){
circle.attr({cx : (circle.attr('cx') - 1)});
} else if (circle.attr('cx') < 50){
circle.attr({cx : (circle.attr('cx') + 1)});
}
if(circle.attr('cy') > 50){
circle.attr({cy : (circle.attr('cy') - 1)});
} else if (circle.attr('cy') < 50){
circle.attr({cy : (circle.attr('cy') + 1)});
}
path.attr({path: pathArray});
},2);
};
circle.drag(move, start, up);
Here's the Jfiddle: http://jsfiddle.net/Uznp2/
Thanks alot :D
I modified the "up" function to the one below
up = function () {
//starting x, y of circle to go back to
var interval = 1000;
var startingPointX = 50;
var startingPointY = 50;
var centerX = this.getBBox().x + (this.attr("r")/2);
var centerY = this.getBBox().y + (this.attr("r")/2);
var transX = (centerX - startingPointX) * -1;
var transY = (centerY - startingPointY) * -1;
this.animate({transform: "...T"+transX+", "+transY}, interval);
};
and the "start" function as follows:
var start = function () {
this.cx = this.attr("cx"),
this.cy = this.attr("cy");
}
Is this the behavior you are looking for? Sorry if I misunderstood the question.
If the circle need to get back to its initial position post drag, we can achieve that via simple animation using transform attribute.
// Assuming that (50,50) is the location the circle prior to drag-move (as seen in the code provided)
// The animation is set to execute in 1000 milliseconds, using the easing function of 'easeIn'.
up = function () {
circle.animate({transform: 'T50,50'}, 1000, 'easeIn');
};
Hope this helps.