Centred texts with different sizes in responsive SVG image - html

How can one get a scalable SVG image with texts with different sizes, all centred both vertically and horizontally?
What I would like to achieve:
What I have tried so far (JSFiddle demo):
<text x="50" y="30"
style="text-anchor: middle;alignment-baseline:middle"
fill="black" font-family="'Arial'" font-size="20">
H1 HEADLINE</text>
<text x="50" y="45"
style="text-anchor: middle;alignment-baseline:middle"
fill="black" font-family="'Arial'" font-size="15">
H2 HEADLINE</text>
Thanks in advance for any tips :) I cannot use JavaScript.

From section 10.1 of SVG 1.1:
SVG performs no automatic line breaking or word wrapping. To achieve the effect of multiple lines of text, use one of the following methods:
The author or authoring package needs to pre-compute the line breaks and use multiple ‘text’ elements (one for each line of text).
The author or authoring package needs to pre-compute the line breaks and use a single ‘text’ element with one or more ‘tspan’ child elements with appropriate values for attributes ‘x’, ‘y’, ‘dx’ and ‘dy’ to set new start positions for those characters which start new lines. (This approach allows user text selection across multiple lines of text -- see Text selection and clipboard operations.)
Express the text to be rendered in another XML namespace such as XHTML [XHTML] embedded inline within a ‘foreignObject’ element. (Note: the exact semantics of this approach are not completely defined at this time.)
As such, you need to either manually calculate the vertical location to get vertical centering, or use <foreignObject> to embed HTML+CSS within your SVG (at the correct location) which can perform vertical centering, e.g. using display:table-cell; vertical-align:middle.

Related

How to draw solid/dotted/dashed lines using most basic HTML/CSS possible (for tcpdf to render them correctly)

Observe Image below. It is a composite of two graphs, where different curves are shown in solid lines, dotted lines, and variations of dashed lines with different length of stroke.
TL;DR
I need a way to generate solid lines, dashed lines, dotted lines using basic/simplest HTML/CSS possible in hopes that tcpdf rendering engine will understand, since tcpdf does not deal well with lastest and greatest HTML/CSS markup. How?
Details you may not need, but may appreciate:
I am using flot + tcpdf to generate these, where graphs are first generated on canvas, and canvas are then transferred to PDF engine and everything seems to work fine except the legend. The legend of the curves is not being transferred to canvas, due to flot not having the capacity just yet to write its legend onto canvas. It writes it onto DIV in HTML/CSS, and the legend code generated by flot translates horribly (i.e. it did big ugly rectangles instead of lines) to tcpdf's native weak HTML-to-pdf rendering engine. In other words, I need to create my own legend using most basic HTML/CSS, and hope that tcpdf will understand and render it correctly.
use SVG, not HTML/CSS.
http://www.tcpdf.org/doc/code/classTCPDF.html#a56536508fb1b5aede7d2ed27f56c2353
<svg height="30" width="100">
<g fill="none" stroke="black" stroke-width="4">
<path stroke-dasharray="20,10" d="M5 2 300 0" />
</g>
</svg>

Reduce area of svg text

I am currently creating a word cloud using an in house developed library, it uses the svg element text to display the words, the problem I have encounter is that the area of some words sometimes overlaps other words as you can see if you inspect test1 in this jsfiddle, this becomes a problem if the words must be clickable.
I want to know if it is possible to reduce the area of the text to the minimum, just wrapping the word, a small padding is accepted.
I have already tried the solution posted in this answer but it didn't work.
I would prefer a css solution if it exists rather than messing with svg but if there is no other option that will do.
Edit: Ok, enough reputation to post images. What I currently have:
What I would like to have:
There are two problems; I currently have only a solution to one. Your text example is misleading. Try Text1g instead to see the descent (i.e. the amount of space below the baseline which the g needs). If you do this, then you'll see that the texts really overlap - you just don't notice because your test text doesn't contain a good set of test characters.
Apart from that, I see that the element is 67px high while the font-size is only 60px. I don't see where the additional 7 pixels are coming from. It's not padding and not margin :-/
Why do you need to know the minimum bounding box?
If it is because you are linking with the element, or applying click events to the words, then you should investigate the pointer-events attribute.
You possibly want something like:
<text ... pointer-events="fill">ejecutar</text>
You will only get events when the pointer is over the fill of the words. This might be a bit fiddly for clicking though because the holes in words will not be clickable.
You could ease that by putting an invisible <rect> of an appropriate size in front of the word with pointer-events="fill". The "fill" value will attract events for where the fill would be even if it is invisible. However that requires you know the bbox of the word, which we already established you don't have (?).
You could give the words an invisible fat stroke and use pointer-events="all". The invisible stroke will make the clickable area (invisbly) fatter and hence the inter-word holes smaller.

Is there a way to put a group element inside a rectangle to use for animations?

Is there a way to place a group inside a rectangle object in svg and then treat that as basically a rectangle element. I want to do that because it would make animations much easier for me since I wouldn't need to move each individual element of the group but could just move the rectangle. I know I can use the translate property for the group to do animations but it would be easier if I could use fixed positions.
You could put the elements in a group <g> in a <defs> and then refer to the <g> using a <use> element to display it. A <use> element has x and y attributes.

Strange difference between HTML and SVG span rendering in Safari

This question is a little specific and I am hoping someone here can shed some light on a potential solution for me.
All of the following points are important:
I am writing some HTML pages that are going to be read on a third party hand-held device.
In order to fit the requirements of this device each word must be in a separate span, this is for an upcoming feature of the device that I am not allowed to go into, but it has to be formatted like this.
This HTML is being converted from SVG, the SVG is created from Adobe Illustrator documents.
The only place I have any control of the creation of the HTML is in the conversion from SVG to HTML.
My problem is this, in SVG text is broken down into "text" nodes and tspan nodes. Look at this simple SVG, note how I am changing the Y coord on the first tspan.
<text><tspan y="50">Hello</tspan><tspan> World</tspan></text>
When this renders in a webkit based browser, like safari, the sentence "Hello World" is displayed with the word "World" right next to the word "Hello".
In my converted HTML example:
<div><span style="position:absolute;top:50px;">Hello</span><span> World</span></div>
"Hello" is displayed with a y offset of 50, however "World" is displayed in the top left corner origin of the page.
This is frustrating as I do not have the coords of where the "World" span should be placed in the SVG (as Illustrator does not need this coord to render it correctly). Also, there may be one or more tspans in the SVG with altered positions which will prevent me from applying the style to the div.
In short, does anyone know if there is an attribute I can set to place the second span directly after the first?
Thanks
You could style the div instead of the span
<div style="position:absolute;top=50px;"><span>Hello</span><span> World</span></div>
That would keep text-chunks together and positioned relative to each other, but you could still have a span for every single word
Have figured this out after trying a bunch of different things.
It is actually very straightforward, however I didn't realise spans could be nested so I am going to let myself off.
<div><span style="position:absolute;top:50px;"><span>Hello</span><span> World</span></span></div>
The trick is to wrap all the words that need to be grouped together in a span. Hopefully this helps anyone who is stuck on a similar issue.

best/shortest way to draw 1px grid in SVG

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.