Animate circle along sine curve - javascript

I am trying to replicate the visuals of f.lux using jQuery which looks like this (sorry for the poor quality). Basically, it is a circle following a sine wave path. I have looked at the jQuery.path animations and I tried replicating the animation, but my sine wave is choppy since it is drawn using CSS. Is there a way to draw the sine wave so it is smooth and then animate the circle following the sine wave path? I couldn't get a fiddle working but this is what my animation currently looks like now. My animation also does not loop back to where it starts unlike the f.lux animation.
I am not sure what the limits are for this either, will I need to make f.lux's background (the blue and pink halves of the sine wave) and then lay the animation on top of it or can I make the whole visual using Javascript, CSS, and jQuery?
Does anybody have any ideas or can anyone point me in the right direction?

To make your line smoother, you can use a svg element, like so :
<svg width="190" height="160" xmlns="http://www.w3.org/2000/svg">
<path d="M10 80 C 40 10, 65 20, 95 80" stroke="black" fill="#E0E0E0"/>
<path d="M95 80 C 105 100, 150 150, 180 80" stroke="black" fill="#EEEEEE"/>
</svg>
This uses two different bézier curves so you can use different colors for your background. You will have to change the values a bit to match you desired width/height and curvature. There is an explanation on svg paths here : https://developer.mozilla.org/en/docs/Web/SVG/Tutorial/Paths.
You can create an insert a svg element with javascript or jQuery SVG if you don't have access to the HTML source file.

Related

Lots of path on screen makes tooltip slow on iPhone

I am drawing 21 * 9 windBarbs in my d3 chart using PATH.
Sample path looks like this:
<path marker-start="url(#meteo-barbheadLight)" stroke="black" stroke-width="0.5" class="meteo-aloft-barb meteo-aloft-barb-group-0 moderate" d="M1 2 L8 2 M0 0 L1 2 Z" transform="translate(0, 225.64285714285714) scale(1.875), rotate(339.35300899956496, 0, 0), translate(-4, -2)" style="opacity: 0.2;"></path>
This is working fine on desktop web browser. But when I run it on iOS safari. Due to some reason tooltip-trendline performance becomes very poor.
I am not sure what is causing this issue. I even tried to isolate these barbs from trendline -tooltip functionality, but still it is slow. If I dont draw these barbs then tooltip is pretty smooth.
So question is :
1) Are those 21 * 9 barbs making page so heavy that tooltip is having lag on mobile browser?
2) What can be a better way to do this?
Application URL:
http://ec2.buser.net/bnforecast/meteogramv2/#!/app/dashboard?start=KBTP&product=MAV
A better way to do this is either draw all those paths inside a canvas instead of SVG or just export those paths to canvas using canvg library and then remove SVG path container element. Canvas is way lighter than SVG.
Also, one tip is to use display: none instead of opacity for performance boost.

Highcharts Grid Line Width (or Color) - Single Line

I have the following Highcharts (http://www.highcharts.com) scatter chart. Note that the axes start at -10 and stop at 10, with 0 in the middle. I want each 0 line to be a different width or color from all the others. Should be easy but I can't find in the API documentation how to do. All I can find is how to change properties for all lines. Has anyone done this or have suggestions?
Outside of the API I looked into using Javascript (specifically jQuery) to update the element's style but the only specific part (d) I could easily use to find which line to update isn't always the same. The element looks like.....
<path stroke-width="10" opacity="1" stroke="#D8D8D8" d="M 293.5 72 L 293.5 502" fill="none"></path>
Thanks.
You can implement plotLines. Check this out.
In yAxis, I have set a green line at value of 70.
In xAxis, I have set a blue line at value of 170.
You may play around with the color and width as well.

SVG and SMIL animate Ball bouncing 3 times and collision with wall

I need to animate a circle that bounce 3 times and hits a wall and return. it should follow a given path. i have tried it with animateMotion. This is how it is so far,
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>animation</title>
<!--<rect x="15" y="5" rx="5" ry="5" width="20" height="10" style="fill:#CCCCFF;stroke:#000099">-->
<circle cx="0" cy="50" r="15" fill="blue" stroke="black" stroke-width="1">
<animateMotion dur="6s" repeatCount="indefinite" rotate="auto">
<mpath xlink:href="#path1"/>
</animateMotion>
</circle>
<!--</rect>-->
<path id="path1" d="m21,39c0,0 46,-44 79,-1c33,43 62,58 97,26c35,-32 86,-30 86,
-31c0,-1 61,-9 29,43c-32,52 -19,51 -87,51c-68,0 -158,-5 -158,-6c0,-1 -40,-11 -41,-12 Z"
stroke-width="5" stroke="#000000" fill="none"/>
</svg>
actually something like below is what i am expecting, as i am new to the area, appreciate any guidance or support.
In order to create the impression that the ball is bouncing organically, you probably want a trajectory that looks a bit more like this:
In addition, you do not want a linear timing function. A linear timing function means the element will move at the same speed throughout the animation. But, the closer a ball is to the apex of a bounce, the slower the ball is going. Also consider that it is going faster at the start and end of the tallest bounce than it is at the start and end of the shortest bounce.
Based on the aforementioned info about the behaviour of a bouncing ball, we might guess that the timing function for one bounce should look something like this:
It starts out fast, slows down, and then speeds up again.
This diagram represents a cubic-bezier curve, also known as a spline. This particular cubic-bezier can be written as 0.1 0.8 1 0.3 - the x and y coords of the first control point (P1) followed by the x and y coords of the second control point (P2).
Combining the trajectory and the timing function:
jsfiddle. The timing needs to be refined a bit, but that's the general idea.
The <animateMotion> element requires four additional attributes to make this happen:
keyPoints="0;0.5;0.75;1"
keyTimes="0;0.35;0.6;1"
calcMode="spline"
keySplines="0.3 0.5 0.8 0.7;0.3 0.5 0.8 0.7;0.3 0.5 0.8 0.7"
what these mean:
keyPoints="0;0.5;0.75;1" - I've decided to split up the path into three sections, each leg of which is associated with a start and end time (from keyTimes) and a timing function (from keySplines). The values are between 0 and 1, separated by semi-colons, where 0 is start of path and 1 is end of path.
keyTimes="0;0.35;0.6;1" - the total duration of the animation is segmented according to these times. There should be exactly as many keyTimes times as there are keyPoints. The values are between 0 and 1, separated by semi-colons, where 0 is start and 1 is the total duration of the animation.
calcMode="spline" - indicates that we want the timing function to be cubic-bezier. setting calcMode to spline means we also have to set keySplineson this element.
keySplines="0.3 0.5 0.8 0.7;0.3 0.5 0.8 0.7;0.3 0.5 0.8 0.7" - each leg of the trajectory gets its own timing function. (So, there should be one fewer keySplines value than there are keyTimes. Here, I've used the same timing function for each, 0.3 0.5 0.8 0.7. Since there are four keyTimes, there are three keySplines values because the trajectory has three legs. (Again, the actual values that I used need to be refined but that's the general idea.)
If you want your circle to follow the path, you need the circle's position to be (0,0), since the motion animation will be relative to the circle's current position:
<circle cx="0" cy="0"...
You can also remove rotate="auto" since it isn't of any use in this case.
See jsfiddle

JS with SVG: Rotate SVG-Element around its center

I have to rotate three SVG-Objects around its center with JavaScript and not the <animation> tag. The big star at the top of the tree rotates correctly, but from the others I don't find the center coordinates.
This is the second star and the rotation in JS:
star2.setAttribute("transform", "rotate(" + angle + " 2000 200)");
and this is the svg:
<defs>
<symbol id="stern">
<polygon points="1000 50 1100 310 850 160 1150 160 900 310 1000 50" fill="yellow" />
</symbol>
</defs>
<use id="stern2" xlink:href="#stern" transform="translate(500,600) scale(0.5)" onmouseover="rotate2();" onmouseout="stop();" />
Here is a fiddle:
http://jsfiddle.net/F325k/
to rotate around the center you need to translate it first: Rotate rectangle around its own center in SVG
ps: the latest and reworked lib from the author of Raphaël is http://snapsvg.io/ in case you can use one.
For SVG, definately use third-party libraries. SVG is a pain with plain javascript. My suggestion: Definately go for D3js, I have been using it for a year at my workplace and it is great: dynamic, good community, brilliant documentation.
See the following example with spinning circle around its center which is called Planetarium: Planetarium Does the rotation without animation as you wanted. It uses a D3- timer and that is all.
There are a lot of examples there, so read the full example list here: d3js Full list of examples

Translating SVG elements for an Isometric view

I'm working on some JavaScript code to render standard 2D SVG/Canvas elements (drawn with Raphael-JS) in an isometric 3Dish view.
Say we have two rectangles drawn next to each other. I then have them redrawn at the correct angles (basically a 30 degree twist) for an isometric view.
(In the image above I've shown the origin for two corresponding elements.)
My problem is I don't know how to properly translate all the individual elements so they "tile" correctly instead of just overlapping.
While actually using tiles would make things easier as I could just base any given tile's placement on the one before it, tiles won't work in this case. Everything is dynamic and will be more complex than simple x/y planes.
Here is an image of some isometric tiles if there's any confusions as to how I want these objects to be placed.
You shouldn't apply the transformation to the individual elements, but to the source elements as a collection. In Raphael, you could use something like
var s = paper.set();
s.push(square1, square2);
and now do the transformations without too much math, which is supposed to work like this:
// s.clone(); // if you want to keep originals
s.rotate(45, 0, 0).scale(1, .7).translate(100, 0);
(However, scaling of rotated items seems to be broken in RaphaelJS.)
Plain SVG example:
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="-200,-500 1000,1000">
<title>Isometric</title>
<g id="source"> <!-- group -->
<circle cx="-50" cy="-50" r="50"/>
<rect width="100" height="100"/>
<rect width="100" height="100" x="101"/>
<rect width="100" height="100" x="50" y="-200"/>
</g>
<!-- make copy of group and apply transformations -->
<use xlink:href="#source" transform="translate(500) scale(1, .7) rotate(-45)"/>
</svg>
Using Raphel.js 2.0 you can do this using the .transform() method and providing a transform string that rotates 45 degrees and scales vertically 70% (or whatever pitch you want). It's important to pay attention to the position you are rotating and scaling around as well - in this case I'm using 0,0. You will also notice I'm translating 100 over to the right to compensate for the rotation.
Transform strings are also great for this use case because you can simply prepend the projection transformation to the transformation of other objects in the scene and they will all end up in the right place.
For example (see http://jsfiddle.net/k22yG/):
var paper = Raphael(10, 10, 320, 240),
set = paper.set();
// Build a set to make it easier to transform them all at once
set.push(
// Grid of rectangles
paper.rect(0, 0, 50, 50),
paper.rect(60, 0, 50, 50),
paper.rect(0, 60, 50, 50),
paper.rect(60, 60, 50, 50)
);
// Rotate, then scale, then move (describe in "reverse" order)
set.transform('t100,0s1,0.7,0,0r45,0,0');​

Categories