I have to build a SVG image containing some rotated text elements. I want to achieve the following:
Each text element shall be rotated around its center point by a degree.
The resulting (imaginary) bounding box of the rotated text shall be translated, so that it's upper left is at position x,y.
We don't know the content, i.e., the width, of the text elements beforehand.
What is the best way to do that?
(I have a basic understanding of SVG and I am able to look up the spec on my own. So I know about transform and rotate(), translate()... However, I struggle with this specific case.)
Related
In a webpage created with node/webpack, vega-lite, and vegaEmbed, I have a layer with rect marks with short annotations inside them using text marks. I'd like to clip the text to its surrounding rect but haven't figured out a way to do this and hope someone can point me in the right direction.
I realize text has a limit property in pixel units. If I could determine the pixel units of my rect marks (I don't know how to do this), using limit seems like a reasonable approach.
Also, if I knew the pixel extents of my rectangle, I can then write code to align the text within the rect which would be desirable. Currently I just use the same x as the rect, with a dx offset.
I've read about background for text which is a similar problem, but not the same.
By default, the anchor for the text element in SVG is at the bottom left, but I want it to be at the top left, since I am also creating a rectangle to act as the background for the text, but it is displayed incorrectly since the text is higher than the rectangle (because rectangle anchor/offset is at the top left). Is there a way to fix this, so both text and rectangle can be drawn at same coordinates and be displayed in the same location.
The dominant-baseline property/attribute worked for me:
svg {
dominant-baseline: hanging;
}
The coordinates (x and y) you supply for text elements is used as the baseline of the text. This makes sense because if there is text with varying font sizes on the same line, you would want their baselines to line up.
There is no "automatic" way to do what you want. SVG elements are always absolutely positioned.
You will just have to move the text down a bit by making the y coordinate a bit larger.
Alternatively, you could add a dy attribute to shift the text down a bit. Or even use a transform attribute to do the same. But using either of those methods wouldn't really be simplifying the process for you.
Suppose I have a svg path and a piece of text. I want to figure out where they intersect. I'm not really sure where to start, because the svg path's getBBox() function does not help.
Where should I start?
You have the text bounding box via getBBox(). Unfortunately, as you may have already discovered, that is not a tight bounding box of the glyphs. It includes the full descender and ascender heights of the font. However it should get you a reasonable approximation.
The next step is to determine where the path hits the bounding box. Getting a perfect mathematical solution is very hard, but there are iterative approaches that are much easier and give good results.
Path elements have a couple of DOM functions that can help: getTotalLength() and getPointAtLength(). You can step along the path from 0 to the path length, calling getPointAtLength(), until the point returned is inside the text bbox.
If you want to get more accurate and determine which character in the text touches the line, there are some DOM functions on SVG text elements that should be useful. For instance, `getExtentOfChar(n) returns the bounds of the nth character in the text.
I'm using Raphael to draw rectangles. Whoo-hoo!
Is there a way to right align contents of an SVG file?
Not just text, but shapes as well?
I can do the math and get the computed x value, but I'm looking for the lazy-simple solution.
Thank you.
There isn't. Unlike normal web pages where the window is resized and the content flows into it, when a Raphael paper is resized, there is no sort of flow, so aligning is irrelevant. Instead of setting align=right, you just set the right edge to be the same position you set the width of the paper to be. If you enlarge the paper, you can scale the contents with a single operation. Once you've set the position of the right edge, you've essentially set the align position. You don't need to re-set all edge values when the paper changes size, you just scale everything with one command. Hope that helps
This question already has answers here:
How can I cut one shape inside another?
(4 answers)
Closed 6 years ago.
So basically as my title says, I want to "cut a hole" in a rect element.
I have two rect elements, one on top of the other. The one on the bottom has a fill colour of white, and the one on the top has a fill colour of grey.
What I want to do is cut a triangle out of the top rect element so that the rect element below shows through.
This svg element is going to be used as an audio button for a media player on a page. In other words, you'll be able to click (or drag) your mouse left/right and the change in audio level will be represented by a change in the width of the rect element on the bottom, which shows through the triangle cut out of the top rect element.
I hope that's not too confusing. :P
Here is a quick mockup of what it should look like: http://forboden.com/coding/s1.png
Here is my code: http://forboden.com/coding/svgClipTest.html
Where am I going wrong here?
You should be able to use the fill-rule: evenodd(default) property to achieve this effect, if you want to prevent the fill of the rectangle from painting where the circle is. See this example from the SVG specification:
The key point is draw outer shape and inner shapes(holes) in different direction (clockwise vs anti-clockwise).
Draw the outer shape clockwise and draw the inner(holes) shapes anti-clockwise.
Or conversely, draw the outer shape(holes) anti-clockwise and draw the inner shapes clockwise.
Concat the path datas of outer shape and inner shapes(holes).
You can cut more holes by concat more hole path data.
This image explain how to cut a hole:
I see that you have it solved already, just wanted to add that if you want something more advanced then it's often quite easy to use a <mask>, see http://dev.w3.org/SVG/profiles/1.1F2/test/svg/masking-path-11-b.svg for example.
However, if you can avoid masking and clipping (e.g by just drawing things on top) that usually leads to better performance/user-experience.
Easiest way is to use <path> with the hole, and set pointer-events to none so events can pass through to the <rect> under. Of course there are many other ways to handle events such as wrapping them with a <g> and handling events on it.
You don't need to limit yourself to the basic shapes and use complicated clipping. Make things felxible enough so you can copy&paste path data generated by tools like inkscape.