I am new to this. I want to make a clock similar to the one given here. But they have used images. Instead I want to make use of ARC. Does anyone know, how can we make an arc, that too using only css? Consider an example that I have to make an arc of 15 degrees. Any kind of suggestions are greatly appreciated.
Thanks in advance.....
I'd recommend you use SVG to do this. The markup is fairly simple, but you'll need to stay aware that there are four different rules which affect which side of the two end points the bulge of the arc with lay and if the bulge will try to take the "short way" or the "long way" with the given radius.
Here's an example. Use a stylesheet like this:
.arc{
fill:tan;
stroke:red;
stroke-width:4px;
}
combined with an svg path like this:
<svg width="100" height="100">
<path d="M 10,40 A 50,50 0 0 1 90,70"/>
</svg>
In short the commands in the above example are
M (move mode with absolute coordinates)
x,y (start the arc here here)
A (arc mode with absolute coordinates)
r1,r2 (the two radius of the ellipse that the arc goes around. use the same value twice for a circle)
z rotation (the rotation of that ellipse. 0 is no rotation)
large arc flag (see fiddle link below)
sweep flag (see fiddle link below)
x,y (where the arc will end)
I made this fiddle to demonstrate all the different combinations of the two flags in movement which helps me a lot in deciding which ones to use. http://jsfiddle.net/rgbk/avpye8nm
The W3C docs are here: http://www.w3.org/TR/SVG11/paths.html#PathDataEllipticalArcCommands They describe z rotation as "x-axis-rotation" which is wrong.
Does it have to be CSS ? or could you use HTL5 canvas?
http://www.w3schools.com/tags/canvas_arc.asp
then you could use that canvas to do the animation instead of using CSS animations...
Related
Given a path data string for an svg <path> element, I need a way to calculate new data for a path that surrounds the original path at a specified offset.
For example: let's take a star SVG:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="512px" height="512px" viewBox="0 0 512 512">
<path d="M 259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 z"/>
</svg>
Which renders like so:
I need to calculate the data for a path that would surround the star at a given distance (a.k.a. "offset").
So, My question is: If I have a desired offset, how can I take the path data for the inner (solid) star, and calculate path data for the outer (outline) star?
It may seem as though I should just scale up the star shape and use that. But the outline is, in fact, a different shape with different proportions. This becomes more apparent with larger offsets and more complex shapes.
It seems like the solution would only require some (heavy) math, so the solution should theoretically be language-agnostic. But maybe I'm missing something... My application's backend runs on PHP so I would prefer that.
I feel like this must have been solved somewhere but I can't seem to find a library that can do this kind of operation. I looked at D3.js and the Imagick PHP class but neither seemed to have what is needed.
There is a js library that you can use: flatten-js(to load and manipulate polygon data) with polygon-offset library which does exactly what you are looking for.
To convert the SVG path data to points you can use https://github.com/nornagon/flatten-svg
Something similar can be simply achieved with Dilate filter in SVG, but that will expand the raster data, instead of creating another path data.
Or, Here is an amazing answer that explains how to do this inside the SVG file by experimenting with stroke-width, but it would require some manual work.
the easiest way to do this is scaling a copy of the star around it's center. In this case the copy is an use element
use {
transform-origin: center;
transform: scale(1.13);
}
svg{width:90vh}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 520 512">
<use xlink:href="#star" fill="none" stroke="red" stroke-width="3" />
<path id="star" d="M 259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 z" />
</svg>
You can do this efficiently by manually calculating the appropriate transformation matrix (translate the center to 0,0; scale by X%; reverse the initial translation) - but if you want to avoid matrices, you can brute force it with algebra & the cartesian distance formula:
Calculate the center of the polygon - x0, y0
Take any polygon end point - x1, y1
The line defined by x0, y0 <-> x1, y1 is of the form y= nx + a
since you have the two coordinates you can find n and a by substitution
If the new polygon point (x2, y2) is B distance away from x1,y1 (where B is equal to e.g. 120% of the SQRT ((x1-x0)^2 + (y1-y0)^2) [cartesian distance formula] then you know that
B = SQRT ((x1-x2)^2 + (y1-y2)^2) [The cartesian distance formula again]
AND that y2 = nx2 + a (it has to be on the line)
Solve by substitution - which will give you two possible points for x2, y2 - one of which will lie on the segment between x0,y0 and x1, y1 - which you can test calculating whether x2,y2 is closer to x0, y0 than x1, y1. The other point is the one you want.
I'm assuming you want to handle any path. Including those with bézier curves. Correct?
Lines are relatively simple. Michael has offered some help there.
Arcs are more complicated. You will likely need to find the centre of the circle corresponding to the arc. The SVG spec can help you there. It includes a section on converting to "centre parameterization".
Béziers are the most complicated. There is no mathematical formula that you can feed a bézier in and get an offset bézier out. However you can use successive approximation to get as close as you like. This article on the Math StackExchange should be useful to you.
If you want agood primer on the math around bézier curves. I highly recommend this video from Freya Holmér. It includes a section on how to find the tangent and normal to the curve. You could use that to generate a set of line segments that are offset from the curve. You might find that simpler than the Tiller and Hanson algorithm mentioned above.
Context
I want to get an arrowhead on a path to a node in a graph that I am making. Because I am using bezier curves it is easier to use the center of the points to / from which the path ends / starts respectively.
In the attached JSFiddle (below) we see a simple triangle of points, one of which is the control points for a quadratic bezier curve. In addition the end markers have been offset to make contact with the node rather than being partially behind it; this is due to paths being drawn to the centers of the points rather than the edges.
Aesthetically there are a few things not quite right with this drawing:
the tip of the arrow head is thiner than the path
although the tip is angled correctly for the arrowhead on the bezier curve, the path is not centered at the point the arrow head appears.
These aesthetic flaws occur because:
the point of an arrow head is obviously thiner than a path / the path extends through the node
the arrow head is so large in respect to the curvature of the path, there is no satisfactory solution to the arrow head problem (given the current code)
Now one could jury-rig the second issue by making a tight cubic bezier curve as done in the second SVG of the JSFiddle.
However, as seen in the third SVG, this does not work with extreme curvature either.
Questions
Is there either a simple way to ensure that the angle of the arrow-head's point and positions of the path when the arrow head joins are centered; alternatively a way to simply scale the arrow head to be small enough where one would not notice?
Is there a way to make the path starting at the arrowhead to the end invisible? / alternatively a simple way to get paths to end prior to hitting the node?
# code to meet SO requirements
# look at this code
JSFiddle
SVG Marker Demo
For your specific application, try adding a viewBox to the marker to make it smaller so it looks somewhat aligned with the end of the bezier. (SVG markers do not currently align with curves.) Change refX to 'slide' the arrow a bit forward to the end of the line.
e.g.
<marker id="arrow" viewBox="0 0 25 25" markerWidth="20" markerHeight="10" refX="20" refY="5" orient="auto" markerUnits="strokeWidth">
Why not just make the markers use your coordinate system, instead of strokeweight:
<marker id="arrow" markerWidth="40" markerHeight="30" refX="25" refY="-5"
orient="auto" markerUnits="userSpaceOnUse" overflow="visible">
<!-- path for the arrow head -->
<path d="M-18,10 l 6 -15 l -6 -15 l 40 15 l -40 15 Z"
fill="white"
stroke='black'
stroke-width='3'
opacity='1' />
</marker>
Sorted. If we draw the paths after the "points" so that the arrow heads end up on top:
Can I fill outside of html <polygon> or <path> like the below image?
<div style="background:'image.png'>
<svg style="background:rgb(100,100,230)">
<polygon points="x,y x1,y1 ..."
style="fill:???;fill-rule:???"/>
</svg>
</div>
I can definitely fill inside of <polygon> or <path>. But how can I fill outside of them? I know one work-around which uses outer polygon enclosing the outside of the star. Is there a simple way?
I haven't found a way to fill the outside of a polygon. But you can produce the same effect, though it's a bit messy, like this.
Start somewhere outside your canvas. Create a path that goes from there to a point on the near side of the perimeter of your polygon, follow round your polygon - let's say we do this clockwise - all the way back to where you joined it, carry on clockwise to a point outside your canvas, and then go round the outside of your canvas, anticlockwise, in a big rectangle, back to where you first started.
You can't "fill outside" of a shape. But you can put a shape behind it.
In your example, you would have a blue square and then in front of it put a star-shaped clipped image.
This is my firs excursion on the HTML5 canvas, I have working knowledge of jQuery and Javascript.
I'm trying to create a "spinning globe" effect with it.
The idea is to have a circle and meridians "spinning" on it, to give the effect of a rotating globe.
I've drawn the circle and now I'm trying to create lines that start from the right (following the curve of the circle), move towards the centre straightnening up (in the middle they are straight) and follow the inverse curvature on the left, ending with the circle.
I'm trying to do this with the HTML5 canvas and jQuery but I'm not sure of where to start... should I create an arc and then try to animate it?
I'm even wondering if the canvas is the right tool or if I should use anything else.
Any suggestion is welcome!
Sebastian
You could use a quadratic bezier curve, which is basically just a curve with a start point, an end point, and a "control point" in the middle, which is what you would want to change as the globe spins. In this case, all of your lines would start and end at the north and south poles, respectively, of your "globe". For example, to make one of these lines:
// start drawing a line
canvas.beginPath();
// move the the top of your globe
canvas.moveTo(0,0);
/* draw a curve with the control point specified by the first two args,
* end point by the second two:
* (in your case, the control point would be in the middle of the globe) */
canvas.quadraticCurveTo(control_point_x, control_point_y, 0, 50);
// finish drawing, stroke and end
canvas.stroke();
canvas.closePath();
You would also have to take in to account how you will clear the lines after each frame, of course.
See: The Canvas element API, Complex Paths
This is what I got, didn't have the time to proceed any further: http://jsfiddle.net/Z6h3Z/
I use bezier curves where the two control points are in a sort of oval arc centered at the poles.
What I got stuck at is the distribution of points along the arc to look more realistic.
I need to draw a 1px grid (10px spacing) using the SVG canvas embedded within a webpage. There are many SVG tags to choose from and I was hoping someone could suggest what tags would be best suited for the job and produce the least amount of code.
For instance, is there a shorter alternative to plotting the path using the <path> tag? Perhaps by defining a square 10px x 10px then somehow repeating it accross the canvas.
Anyway, open to suggestions please.
Thanks
You can make a <pattern> (essentially the tile in your question) and fill any shape with that.
Here's an example of that technique.
I'm not an expert (day 3!), but I do know that Google uses rects to do this on Google charts, with either a width or a height equal to 1. Nothing fancy, just write the grid with lots of stuff like this:
<rect x="86" y="61" width="1" height="198" stroke="none" stroke-width="0" fill-opacity="1" stroke-opacity="1" stroke-dasharray="0" fill="#cccccc"></rect>
Why do they do this? Don't know. Their graphics are good, so someone has presumably thought about it. My own inclination is to do this with paths, using 'h' and 'v' for relative horizontal and vertical lines. It's more compact, but the output may not be so good.