How does "text-align: justify" works? - javascript

Hello I am writing a lib. for creating composition of texts, internal customisation. - d3-fusiontext.
I want to support
text-align: Justify
The user say provides me a long text. Mentions the height and width it would like to be rendered. The lib. wraps it up, and provides a good visual with wrapped texts. They are all svg text elements so that it can be exported too.
Now I would be to curious to know how the browser internally aligns in a justified manner? Any source/ links/ topics to start with. Any help/ guidance is highly appreciated.
This is a good example of how things might look.
codepen.io/anon/pen/zxNJKE
P.S: Sorry about no gh-pages and docs as the stuff is under dev. Will update.
Just a generalized curiosity how does the browser determines the spacings in justified alignment?

There are other answers on SO which provide information on how you can do text wrapping.
Word Wrap in Raphael JS / SVG
How to either determine SVG text box width, or force line breaks after 'x' characters?
Once you work out which characters/words fit on the line, you can use the textLength and lengthAdjust attributes to get SVG to stretch the line to fit the width.
<svg width="10cm" height="3cm" viewBox="0 0 1000 300"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<line x1="200" y1="0" x2="200" y2="300" stroke="red"/>
<line x1="800" y1="0" x2="800" y2="300" stroke="red"/>
<text x="200" y="100"
font-family="Verdana" font-size="55" fill="blue" >
Hello, out there
</text>
<text x="200" y="170"
font-family="Verdana" font-size="55" fill="blue"
textLength="600" lengthAdjust="spacing">
Hello, out there
</text>
<text x="200" y="240"
font-family="Verdana" font-size="55" fill="blue"
textLength="600" lengthAdjust="spacingAndGlyphs">
Hello, out there
</text>
<!-- Show outline of canvas using 'rect' element -->
<rect x="1" y="1" width="998" height="298"
fill="none" stroke="blue" stroke-width="2" />
</svg>

Related

Printing an inline SVG (in mm) from browser

I have to print my SVG straight from the browser, but I have no idea how to do that.
The locations and sizes of the SVG's elements are important, that's why the numbers are all in mm.
It has to print on pre-printed paper, in pre-printed containers.
The SVG currently looks something like this:
<svg xmlns="http://www.w3.org/2000/svg" class="col-md-12 designerCanvas" id="svgLabel" width="240mm" height="90mm" viewbox="0 0 240 90">
<image class="svg" id="img-160-68" visibility="visible" x="160.202" y="68.0135" width="14.0043" height="14.0043" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/images/Icons/icon02.png" />
<image class="svg" id="img-175-68" visibility="visible" x="175.791" y="68.0135" width="14.0043" height="14.0043" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/images/Icons/icon05.png" />
<image class="svg" id="img-191-68" visibility="visible" x="191.381" y="68.0135" width="14.0043" height="14.0043" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/images/Icons/icon07.png" />
<text class="svg" id="txt-0-5" font-family="Arial" font-size="1.64233" visibility="visible" text-anchor="start" x="0.5285" y="5.5489" height="33.29333142498542" width="79.26983672615574">
<tspan x="0.5285" dy="1.6423">[EN] Some Title: </tspan>
<tspan x="0.5285" dy="1.6423">There is some text here.</tspan>
<tspan x="0.5285" dy="1.6423">Even more text here. </tspan>
<tspan x="0.5285" dy="1.6423">WOW, a third line.</tspan>
<tspan x="0.5285" dy="1.6423">You're overdoing it</tspan>
<tspan x="0.5285" dy="1.6423">Please</tspan>
<tspan x="0.5285" dy="1.6423">STAHP</tspan>
<tspan x="0.5285" dy="1.6423">No More!!</tspan>
<tspan x="0.5285" dy="1.6423">That's it</tspan>
<tspan x="0.5285" dy="1.6423">I'm outta here....</tspan>
</text>
</svg>
Do note that the paper's (=SVG canvas) width and height come from the DB and can have several values.
The x, y, width and height of the elements now don't have mm, as the viewbox and units combo of the SVG canvas solve that, though I can add it if needed.
Client only wants me to support IE11+, though I myself want to support recent Chrome and FF as well.
I could load the drawing in a fresh (temporary) window to print it, though I'm not sure it'll print on the correct coördinates like that.
Maybe creating a PDF and print that is the way to go, though no idea how to send the svg to that.
The web application itself is an ASP.NET MVC (Core), with plain javascript and jQuery added to the front end.
Couldn't find much info on the web on the topic, besides printing a SVG in pixels on default paper, but I'm pretty sure the elements will get printed in the wrong location/size that way.
Any ideas?

Making a D3 widget scrollable

I'm sticking a D3 tree widget into my web app. It grows children and appends them to the tree. However, when the tree gets to be too big, it starts to go off the page. That's fine since I don't want to the individual tree nodes to get too small, but it would be nice if I could add a scroll bar. However, I've tried doing it the normal way, overflow: auto, but it doesn't work. Maybe it's something to do with the D3 svg stuff.
Here's the code for a tree with 2 nodes:
<div id="Graph">
<svg width="100%" height="10%" id="SVG" overflow="auto" display="block">
<g transform="translate(40,0)">
<path class="link" d="M0,20C213.75,20 213.75,20 427.5,20"></path>
<g class="node" transform="translate(427.5,20)">
<circle r="4.5" style="fill: rgb(255, 255, 255);"></circle>
<text x="10" dy=".35em" text-anchor="start" style="fill-opacity: 1;">1</text>
</g>
<g class="node" transform="translate(0,20)">
<circle r="4.5" style="fill: rgb(255, 255, 255);"></circle>
<text x="-10" dy=".35em" text-anchor="end" style="fill-opacity: 1;">0</text>
</g>
</g>
</svg>
</div>
Once it gets to be more than around 10 or 11 nodes, it goes off the screen. How can I fix this?
Make the width of the svg element > 100%. That will overflow the div and the div will be scrollable. You might also need to set the overflow style to scroll on the <div>

svg text-centering anomaly

I need to set SVG parameter text-anchor:"middle" for a set of single character tspan elements centered in small circles for a guitar chord chart generator: see http://chordography.blogspot.co.uk/.
When I paste the svg code into a browser: Chrome, IE, Firefox, Opera, Safari, or in Open Office Writer, the characters are placed left of centre, EXCEPT for the last tspan element, which is centered correctly. The last one is always OK, even if I rearrange the tspans. The problem may not be noticeable in most cases, but sticks out like a sore thumb in this application.
Here, the plot thickens. When I insert the svg code directly into the DOM with JavaScript, as is normal in Chordography, all tspan elements centre correctly. And there is one more twist; when I paste the code in Blogger, it also centres properly, as shown at http://chordography.blogspot.co.uk/p/blog-page_58.html.
Here is the code for the relevant parts derived from XMLSerializer, showing the locations of the circles and inset 'labels'. Only the final '1' is properly centered, along with the final 'A' in the footer.
<g class="dots">
<circle cx="62.1" cy="73.6" r="9.6"/>
<circle cx="85.1" cy="128.8" r="9.6"/>
<circle cx="108.1" cy="128.8" r="9.6"/>
<circle cx="131.1" cy="128.8" r="9.6"/>
<circle cx="154.1" cy="73.6" r="9.6"/>
</g>
<g text-anchor="middle" class="text">
<text class="labels">
<tspan x="62.1" y="79.2">1</tspan>
<tspan x="85.1" y="134.4">2</tspan>
<tspan x="108.1" y="134.4">3</tspan>
<tspan x="131.1" y="134.4">4</tspan>
<tspan x="154.1" y="79.2">1</tspan>
</text>
<text class="footer">
<tspan x="39.1" y="189.6"> </tspan>
<tspan x="62.1" y="189.6">D</tspan>
<tspan x="85.1" y="189.6">A</tspan>
<tspan x="108.1" y="189.6">D</tspan>
<tspan x="131.1" y="189.6">F♯</tspan>
<tspan x="154.1" y="189.6">A</tspan>
</text>
</g>
All a bit bizarre; any ideas anyone.
If you add 'text-anchor="middle"' to each tspan you will center them (you have to remove the space between the 'tspans' as well, otherwise the extra space will be considered as part of the first line and they won't be completely centered).
The space is most likely the reason you are having this issue.
The tspans look like this ...
<tspan text-anchor="middle" x="56.5" y="72">1</tspan><tspan
text-anchor="middle" x="77.5" y="122">2</tspan><tspan
text-anchor="middle" x="98.5" y="122">3</tspan><tspan
text-anchor="middle" x="119.5" y="122">4</tspan><tspan
text-anchor="middle" x="140.5" y="72">1</tspan>
Reference jsFiddle: http://jsfiddle.net/rfornal/0u5wmevm/
Usually I'd regex all unwanted characters, then read string as array, eg:
var badStr = 'xx,1p23,4 "5'; // string with errors
var newStr = str.replace(/[^x\d]/g,''); // outputs: x12345
console.log(newstr[1]); // debug, outputs: 1

Toggle layer in SVG

I am trying to create a HTML page with a check list that we can also make it large without losing quality. As a result I want to use SVG.
I would like to have a script to operate on the SVG so that I can toggle the group svg_2 (a check mark) on or off so that we have checked and unchecked box. It doesn't have to change when loaded, just need like an inline command that will do it.
<svg width="20%" height="20%" xmlns="http://www.w3.org/2000/svg">
<rect id="svg_1" fill="#ffffff" stroke="#000000" stroke-width="10%" x="2.5%" y="2.5%" width="85%" height="85%" />
<g id="svg_2">
<line fill="none" stroke="#ff0000" stroke-width="10%" x1="43.5%" y1="77.5%" x2="10.5%" y2="49.5%" id="svg_3" stroke-linecap="round" stroke-linejoin="bevel"/>
<line fill="none" stroke="#ff0000" stroke-width="10%" x1="95%" y1="9.5%" x2="44.5%" y2="78.5%" id="svg_4" stroke-linecap="round" stroke-linejoin="bevel"/>
</g>
</svg>
You can use JavaScript to toggle the svg_2 on or off depending on its previous state (example using JQuery):
$("svg").click(function() {
if ( $('#svg_2').css('visibility') == 'hidden' )
$('#svg_2').css('visibility','visible');
else
$('#svg_2').css('visibility','hidden');
});
You could also use some other CSS attribute (such as display).
See and try it here: JSFiddle

Javascript function for painting connected walls in labyrinth?

I have a problem for which made simplified code for express it. In few words I need to build code in Javascript for painting connected SVG lines. The simple example:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" >
<line x1="50" y1="50" x2="200" y2="50" stroke="steelblue" stroke-width="20" onclick="fillWall(evt)" />
<line x1="100" y1="100" x2="400" y2="100" stroke="steelblue" stroke-width="20" onclick="fillWall(evt)" />
<line x1="300" y1="300" x2="200" y2="300" stroke="steelblue" stroke-width="20" onclick="fillWall(evt)" />
<line x1="100" y1="50" x2="100" y2="400" stroke="steelblue" stroke-width="20" onclick="fillWall(evt)" />
<line x1="300" y1="100" x2="300" y2="300" stroke="steelblue" stroke-width="20" onclick="fillWall(evt)" />
<line x1="200" y1="300" x2="200" y2="200" stroke="steelblue" stroke-width="20" onclick="fillWall(evt)" />
<script type="text/javascript">
<![CDATA[
function fillWall(evt) {
var tgt=evt.target;
tgt.setAttributeNS(null, "stroke", "firebrick");
}
]]>
</script>
</svg>
This is labyrinth of few walls when you click on some it changes color, so I need to do it with one click to paint all connected, no matter on which wall click is applied. In full sized scale there are almost thousand of these walls, and some are connected, some aren't. I tried to learn recursive functions, but easily exceeded stack size.
Please help, I'll appreciate that a huge.
there is a function on purpose: getIntersectionList that paired with getBBox
could help you to solve your problem. Pseudo code:
fillWall(evt) {
fillConnected(evt.target, [])
}
fillConnected(node, filled) {
if (!filled.contains(node)) {
fill(node);
filled.append(node);
foreach(n in document.getIntersectionList(node.getBBox()))
fillConnected(n, filled)
}
}
I'll try to craft actual code using jsFiddle, and will post the address later...
edit see this fiddle, but it seems that Firefox doesnt' still implements the required getIntersectionList. Then if we must craft our own, it's surely best if we cache the lists, because it's going to be a rather costly method...
edit I've modified the fiddle' code, that worked just on local files, now in Chrome run fine, but where the walls just touch, the getIntersectionList doesn't work. So we must anyway implement our own version... See you later...
edit well, at last the fiddle seems to work. Please note that walls must have their endpoints sorted (x2 >= x1, y2 >= y1), You can see on that walls coloured yellow (corrected) and green (still wrong) the effect of that sort.
Pseudo-code version of mine:
function doWall(I_oWall) {
if I_oWall.painted then return;
I_oWall.paint();
for each wall in walls
if I_oWall.isAdjacentTo(wall) then
doWall(wall);
end if
loop
}
Sorry, I know it is not a full and complete answer but I think it will really help you in how to figure out your issue.
cheers

Categories