Good time forum users. Please tell me how to get the size of the element taking into account the font parameters (size, type, style)
let tagText = document.createElementNS("http://www.w3.org/2000/svg", "text");
tagText.setAttributeNS(null, "font-size", 18);
tagText.setAttributeNS(null, "font-weight", 400);
tagText.setAttributeNS(null, "font-family", "Roboto");
tagText.innerHTML = 'Some text ...';
// where ViewPort ??
let widthTitle = tagText.getBBox().width;
console.log('width title: ', widthTitle); // return 0;
updated
Unfortunately, it is not very convenient to change the size after adding, because you have to find all the elements and proportionally change the position. (I initially set up the template engine (handlebars.js) where I pass the necessary parameters and it automatically builds an element with dimensions (the problem is only with get length text).
The OP is commenting:
I generate an svg object depending on the data received. The resulting text can be of different lengths and I need to calculate the size of it to properly generate the object in width.
As I've commented: In this case you may begin with whatever size you want for the svg, append the text, get the size of the text, for example using the textLength property, and next you change the size of your svg element
let tagText = document.createElementNS("http://www.w3.org/2000/svg", "text");
tagText.setAttributeNS(null, "y", 20);
tagText.textContent = 'Some text ...';
svg.appendChild(tagText)
let widthTitle = tagText.textLength.baseVal.value;
svg.setAttributeNS(null,"viewBox",`0 0 ${widthTitle} 25`)
text{font-size:18px;
font-weight:400;
font-family:Roboto
}
svg{border:1px solid; width:200px;}
<svg id="svg"></svg>
Assuming that the element has been inserted into the web page, you could use something like this:
getComputedStyle(tagText).width
However, if you did not specify that width yourself (using CSS, for instance), in your case, the default value will be auto.
If that's the case, you could try to look at the width of the element's parent, doing something like this:
tagText.parentElement.offsetWidth
Related
TLDR;
given this svg element:
<image width="30" height="48" x="3.75" y="6" href="http://some/image.jpg">
How can I retrieve the image's actual height and width (seeing as it is defined in part by the image's aspect ratio).
I have a d3js script that draws a bunch of <rect>s and a bunch of <image>s.
Now stuff is laid out so that the images fall inside the rects, as though the rects were borders. There is other stuff inside the rects too.
Now each of these images has it's own unique and special aspect ratio and this bothers me because it means each of the rects then has a different amount of blank space. This is untidy.
To avoid this I want to load the images then get the actual image dimensions and then adjust the positions and sizes of the surrounding goodies. The crux of the matter is getting the actual image sizes. How can I do this?
I've googled around a bit and spent some quality time with the debugging console to no avail. Just nothing comes up. I'll keep hunting but an answer would be really nice.
First, set the width attribute only, keep height unspecified.
Then, call the getBBox for the image element.
Note that image box is available after it's properly rendered by the SVG
const image = parent.append('image').attr('xlink:href', url).attr('width', 100);
setTimeout(() => {
const box = image.node().getBBox();
const ratio = box.width / box.height;
}, 0);
This is the best I can come up with. I would be surprised and horrified if there isn't an easier way. Anyway:
add a normal html <img> element with a suitable src.
use js to fetch the image height and width
remove the extra html
Ugly but it works...
Here's some code:
var oImage = document.createElement("img");
oImage.setAttribute("src",sUrl);
document.body.appendChild(oImage);
var iWidth = oImage.width;
var iHeight = oImage.height;
oImage.remove();
I'm trying to measure the exact height used to render a given string with a given font with an SVG text tag.
I've tried using getBBox and getExtentOfChar, but the height returned by both of these includes some extra space above (and sometimes below) the actual text rendered.
http://upload.wikimedia.org/wikipedia/commons/3/39/Typography_Line_Terms.svg
Using the terms in this image, I'm trying to get the either the cap height + descender height of the text being rendered. Or, if that's not possible, just the cap height. Is there a good way to calculate these values?
Here's a quick codepen showing the extra space I'm talking about:
http://codepen.io/pcorey/pen/amkGl
HTML:
<div>
<svg><text>Hello</text></svg>
<svg><text>Age</text></svg>
</div>
JS:
$(function() {
$('svg').each(function() {
var svg = $(this);
var text = svg.find('text');
var bbox = text.get(0).getBBox();
svg.get(0).setAttribute('viewBox',
[bbox.x,
bbox.y,
bbox.width,
bbox.height].join(' '));
});
});
I understand that this is a fairly font-specific thing, so this might be totally impossible...
No. All the SVG DOM methods (getBBox(), getExtentOfChar()) are defined to return the full glyph cell height. That extra space above the cap height is allowance for taller glyphs - such as accented capitals. I think this is true for HTML DOM methods as well.
There are, however, JS libraries around which may be of use. For example:
https://github.com/Pomax/fontmetrics.js
I have not used this library myself, so I can't tell you how reliable or accurate it is.
I am doing a modification on svg-edit. I am using a function to make a path element bigger or smaller based on width and height inputs by the user. The user selects an element and clicks on a button to fire up the function which takes the last known width and heght measurements and then asks from the user the new width and height values. It then creates a divisor which it uses to create a TRANSFORM MATRIX operation on the element to make it as big as the user wants.
The problem is that when transforming matrices, the elements also changes position.
I want when the user is asked for a width and height also to be asked for x,y position on canvas and then move the selected element to that position.
Is their a way of repositioning an svg element?
function changeDimensions()
{
svgNode = svgCanvas.getSelectedElems()[0];
var dims = Raphael.pathBBox(svgNode.getAttribute('d'));
lasth = parseInt(dims.height);
lastw= parseInt(dims.width);
var transformw=prompt("Enter your new width");
var transformh=prompt("Enter your new height");
newW=transformw/lastw;
newH=transformh/lasth;
svgCanvas.changeSelectedAttribute("transform", "matrix(" + newW + ", 0, 0, " + newH + ", 0, 0)");
svgCanvas.recalculateAllSelectedDimensions();
}
Different svg elements have different attributes that they use to position themselves. For example rect's have x and y attributes but circles have cx, and cy. Path's do not have separate attributes.
However you can probably get what you need from a transform! Most svg elements will accept a transform attribute where you can assign a translation. E.g.
<path d="M10,10L20,100" transform="translate(30,40)"/>
In fact you can probably scale your path with the same transform attribute.
I'm trying to do something like:
$('<span>random text in here</span>').width()
But the width it's returning is 0. (The reason I'm trying to do this is to get the pixel width of a given text.)
How would I get this width, programmatically?
Thanks
You have to have it rendered.
You may do this :
var s = $('<span>random text in here</span>');
s.appendTo(document.body);
var w = s.width();
s.remove();
Demonstration
Note that :
nothing is displayed if you do this like I do in one go. For all practical purposes, nothing is inserted in the DOM,
you could also use an in memory canvas but it wouldn't handle anything more complex than simple text and wouldn't take into account your span's css settings.
Here's the solution measuring the width of some text using an in memory canvas :
var canvas = document.createElement('canvas');
var c = canvas.getContext('2d');
// set here c.font to adjust it to your need
var w = c.measureText('random text in here').width;
Demonstration
I would use the first one in the general case but it might depend on why you want to measure the text.
i'm using Highcharts , the chart result is a collection of SVG elements and i was trying to add some elements to this SVG using jquery
Here is what i have tried
function(chart) { // on chart load complete
$("#highcharts-0 Svg").
append(document.createElementNS("http://www.w3.org/2000/svg", "rect"));
$("#highcharts-0 Svg").find("rect").
attr({x : 100 , y:100 , width : 100 , height : 100 });
console.log($("#highcharts-0 Svg "));
});
i can't really say if this is working or not , all i can see is a <rect></rect> element in my DOM with no attr
another notice is when i hover on this element using chrome console it shows the rec on x-0 , y=0,
i have an idea that jquery does not append svg elements hop i'm wrong
Question How can i add element with attributes to SVG using jquery
EDIT
with help now i have id for the rect element
then i tried to add attr with using the id , but failed
ScreenShot
Highcharts also has a drawing API that you can use to draw rectangles. This works also for VML. Check out http://www.highcharts.com/ref/#renderer => rect and live sample at http://jsfiddle.net/gh/get/jquery/1.7.1/highslide-software/highcharts.com/tree/master/samples/highcharts/members/renderer-rect-on-chart/.
As you can see here, there're no attributes rx and ry, try to change it to x and y.
Rectangles have x and y attributes. rx and ry are used on circles.
Also, are you sure your selector is correct? You might want to lowercase the 'Svg'
** edit **
The rect in your screenshot doesn't have any of the attributes assigned. There's no width or height, or x/y positions. You should try giving the rectangle an id when appending it, and querying for it using that same id.
See:
https://developer.mozilla.org/en/DOM/document.createElementNS
You can do it like this:
var rect = document.createElementNS("http://www.w3.org/2000/svg","rect");
rect.id = 'your_id_here';
Then append the rect through the normal route.
Note that, since you have the raw dom element, you might be able to assign your other properties there as well. e.g.:
rect.x = 100;
rect.y = 100;
rect.fill = 'blue';