SVG text not aligned correctly on edge - javascript

I have created an SVG with a base64 background image and two text areas (top and bottom text). These text areas can be updated via two input forms.
This functions correctly apart from on Internet Explorer and Edge, whereby the bottom text is aligned to the left instead of the center and the position of the bottom text is also incorrect. Top text is displaying correctly.
I am currently only trying to resolve this issue for Edge. If you view the link below I have a demo of the SVG and two fields.
https://jsfiddle.net/znhs955p/1/
For excepted behavior view on chrome or firefox.
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:12.58850098px;line-height:1.25;font-family:sans-serif;letter-spacing:2px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.43085253"
id="bottom"
transform="matrix(0.91651557,0,0,0.91221872,8.953221,18.767226)"
x="1.5895385"
y="3.9430504">
<textPath
xlink:href="#ellipse4592"
startOffset="50%"
id="bottom-text"
style="font-size:21px;letter-spacing:2px;stroke-width:1.43085253">
Bottom Text
</textPath>
</text>
<text
id="text4630"
style="font-style:normal;font-weight:normal;font-size:13.35012245px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.66707253"
xml:space="preserve"
transform="matrix(-0.90287605,0,0,-0.90624359,513.44619,329.63062)">
<textPath
xlink:href="#path5204"
startOffset="50%"
id="top-text"
style="font-size:18px;stroke-width:1.66707253">
Top Text
</textPath>
</text>

Remove the x and y attributes from the <text> element that wraps your <textPath>.
I.e. change:
<text ...
x="1.5895385"
y="3.9430504">
<textPath ... id="bottom-text" ...>Bottom Text</textPath>
</text>
to
<text ...>
<textPath ... id="bottom-text" ...>Bottom Text</textPath>
</text>
Those x and y attributes seem to be confusing IE.
https://jsfiddle.net/znhs955p/2/

Related

Using javascript, how do I copy svg tspan elements inside an svg text element into a different text element?

I have an svg text element with two tspan elements. It looks like this.
<text id="majNote5" x="25" y="70">
<tspan>D</tspan>
<tspan font-family="'Opus Text'" font-size="25">b</tspan>
</text>
I have a 2nd empty text element which looks like this.
<text id="majChord1" x="425" y="70" ></text>
I want to copy both tspan elements and their respective texts in the first text element into the 2nd text element.
I tried the following:
var majNote5 = document.getElementById('majNote5');
var majChord1 = document.getElementById('majChord1');
majChord1.textContent = majNote5.textContent;
This does copy the text contents of the tspan elements and places it in the other container, but without any of the tspan elements. So afterward it looks like this:
<text id="majChord1" x="25" y="70">Db</text>
How do I get the second text container to look exactly like the first container?
Thanks,
--christopher

Get the coordinates of a letter in a SVG text element

Say I have a very basic SVG:
<svg viewBox="0 0 100 50">
<path transform="translate(X,Y)" fill="none" stroke="red" d="M11,11.1c-3.9,1.2-12.4,9-10.4,12.2s14.9-0.8,15.5-2.1s-4-2.7-4-2.7"></path>
<text transform="translate(10,25)">Hello World.</text>
</svg>
I know the height and width of the <path> (from some other algorithm) and the position of the <text> (from the transform attribute shown above).
How can I know the X and Y coordinates of the letter W?
My goal here is to set the translation of the path so that it appears just below the letter W.
To give you a better idea of the end goal, here's what I'm trying to do: I want to automatically replace all <text> in a svg by paths that I've drawn to match the font (Permanent Marker). This way I can create a realistic handwriting effect (see here for a live demo: whiteboard-comics.com/good_time_for_drinking=f(week_day))
So far, I start with a <text> and my images look like this:
Then I replace by hand, letter by letter, in Illustrator, the entire text. And it end up looking like this:
And when I do it algorithmically (just based on the coordinates of the <text> element and the width of each hand drawn character as a <path>), it becomes this:

Internet Explorer and tspan vertical alignment

To vertically align a tspan element inside a text element in SVG, the CSS properties alignment-baseline and dominant-baseline work great in Chrome and in FF, respectively. So far so good.
With Internet Explorer it gets a bit crazy:
an open bug report asserts that these properties do not work for IE9-11 ...
... but the official documentation states that alignment-baseline is supported
CSS feature-sniffing in IE9 & IE11 reports that they support alignment-baseline as well as dominant-baseline for tspan, but they do not work with any values
to add confusion to frustration, this MSDN dev page simply says both properties are currently unsupported
This wouldn't be such an issue for IE9 (one could simply hack the desired alignment), but since I want to get away from browser detection, I would like to know:
is there a workable cross-browser solution?
how come even IE11 doesn't support this basic SVG styling property and how to work around that?
Thanks!
I have no idea why IE doesn't support alignment-baseline, let alone why you're getting such mixed information.
You can sort of hack the same behaviour using the dy attribute and font-based units ("em" and "ex"). It works pretty well if you just want to center a specific text element on a point.
<text x="50%" y="50%" dy="0.5ex" text-anchor="middle">
This text will be centered in your coordinate system!
</text>
But the problem with dy is that -- unless y is also set explicitly for the same element -- it is calculated relative to the position of the previous character. So if you want to center a text span relative to the surrounding spans, you have to first adjust for any previous offset and then set the new offset. The resulting code isn't pretty:
<text x="50%" y="25%" font-size="150%">
<tspan dy="0.5ex">Large font with</tspan><tspan
dy="-0.5ex"> <tspan
font-size="50%" dy="0.5ex">small font<tspan
dy="-0.5ex"> </tspan></tspan></tspan><tspan
dy="0.5ex">embedded.</tspan>
</text>
<text x="50%" y="75%" font-size="75%">
<tspan dy="0.5ex">Small font with</tspan><tspan
dy="-0.5ex"> <tspan
font-size="200%" dy="0.5ex">large font<tspan
dy="-0.5ex"> </tspan></tspan></tspan><tspan
dy="0.5ex">embedded.</tspan>
http://fiddle.jshell.net/awj49/
Rendering in IE11:
(gray lines mark the reference y coordinate)
If you can, it makes much cleaner code to just explicitly set the y attribute on each tspan:
<text x="50%" font-size="150%">
<tspan y="25%" dy="0.5ex">Large font with</tspan>
<tspan font-size="50%" y="25%" dy="0.5ex">small font</tspan>
<tspan y="25%" dy="0.5ex">embedded.</tspan>
</text>
<text x="50%" y="75%" font-size="75%">
<tspan y="75%" dy="0.5ex">Small font with</tspan>
<tspan font-size="200%" y="75%" dy="0.5ex">large font</tspan>
<tspan y="75%" dy="0.5ex">embedded.</tspan>
</text>
http://fiddle.jshell.net/awj49/1/
The final rendering is the same:
IE doesn't seem to support any vertical alignment CSS properties. A tspan is rendered with a default of what approximates alignment-baseline: central. Therefore, browser detection and polyfilling seems to be the only option just now to have your elements render the same across all browsers.
I adapted AmeliaBR's brilliant answer by manually adding to the y attribute of the parent text element to the desired difference of the font height in pixels (+50% of the font height = hanging, -50% = before-edge ...). Like so:
d3.selectAll('text').each( function()
var text = d3.select(this);
var dy = text.attr('y') || 0;
var h = text.style('font-size').replace('px', '') * 1;
var nh = (dy * 1) + (h / 2);
text.attr('y', nh);
});
I've used d3 here, but obviously this works with any JS library or pure JS DOM-selection.

Linked text around circle

I have two links that are designed like this:
I’m trying to get my head around a decent solution for this. The text would preferably be PNG images, but text in an SVG would be acceptable as well. I also need a hover state, but that can be done by using a png sprite or text color, so that is not an issue. The biggest problem is to create proper click areas.
HTML/CSS is just somewhat square and limited when it comes to overlapping link/hover areas.
I peeked at SVG solutions, I also considered using multiple squares for "hotspots" or rotating letter by letter using CSS3.
Does anyone have a clever idea on how to solve this? IE9+ support would be nice.
You could do this simply as an svg with two textPaths, where each link is just an <a> tag. Click regions will be automatically computed.
Here's an example:
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="700 0 500 500">
<title>Simple example of using links with svg textPaths</title>
<defs>
<style type="text/css">
text {
font: 50px sans-serif;
text-anchor: middle;
}
a:hover { fill: cornflowerblue; }
</style>
<path id="p1" d="M700 400a200 200 0 1 1 400 0"/>
<path id="p2" d="M700 400a200 200 0 1 1 400 0" transform="translate(0 50)"/>
</defs>
<text>
<a xlink:href="http://www.example.com/first">
<textPath xlink:href="#p1" startOffset="50%">First link</textPath>
</a>
<a xlink:href="http://www.example.com/second">
<textPath xlink:href="#p2" startOffset="50%">Second link</textPath>
</a>
</text>
</svg>
I have a theory. What if you did something like this:
create a container with the text
create a duplicate on a higher z-index
create a solid white overlay with the exact dimensions for each. (used later)
css rotate -90 on all
read this to skew the images opposite ways.
http://www.useragentman.com/blog/2011/01/07/css3-matrix-transform-for-the-mathematically-challenged/
then skew the overlays to match up giving you the appearance of the bended example in your question.

Space between two svg text elements

I am currently working with SVG element of JavaScript.
Here is my scenario.
I have an svg element in which I have two text element like this
<svg>
<g transform = "translate(0, 20)">
<text style="font-size: 0.5em;" x="0" y="-4"> text </text>
<text style="font-size: 0.5em;" x="70" y="-4"> value </text>
</g>
<svg>
It's appearing fine like this
text value
I have used font-size 0.5em because I want to my text to resize when I resize my svg.(by using jquery resizable)
Its working fine, but the problem is that when I resize my svg the space between text decreases and at some point the text becomes so big that both texts overlap with each other because of the fixed x and y attributes.
Is there a way to avoid this problem. A method by which I can keep the space between the two texts constant or the text can be relatively placed.
Converting to a single text value would seem to meet the use case you've outlined above. If you need text relatively placed you can convert one to a tspan and then use dx and dy e.g. <text>text <tspan dx="1em" dy="1em">value</tspan></text>

Categories

Resources