get dimension of an svg including stroke - javascript

I want to place an svg precisely into the corner of a div. The svg has a dynamic generated stroke. If the shape of the svg is irregular or lets say a star, the distance to the outmost part of the border is hard to calculate.
The problem could be solved, if I would be able to get the dimensions of the svg including the stroke.
My idea is:
load the external svg
place it in the middle of the div
apply the desired stroke-width
get the outmost dimensions of the svg
place it in the corner
Can I get the width of the svg including the stroke? Any other ideas?
Thanks

getBoundingClientRect is the only way short of calculating it yourself from first principles. That method is only implemented in Firefox and IE9+ as far as I know though.
For example this returns 54 on Firefox.

Related

Center SVG's viewBox on an element

I need to render one element from an SVG to an image. It needs to be like it appears in the SVG, without further transforms.
The only way I can think of to achieve this, is to set the SVG's viewbox on the target element. To do this, I need to compute the element's bounding box relative to the SVG viewBox.
I've tried to use getBBox(), but I don't think it can work. Its coordinates are relative to the transformed element: the transforms of the element and its parents aren't applied. It's not possible to apply those transforms to the bbox since the transformed-bbox might not contain the object anymore: for example think what would happen if the bbox need to rotate by 45 degrees.
An alternative could be getBoundingClientRect(). However it represents the bounding box of the element relative to the screen coordinates and again it might not be enough to apply the transforms from the screen to the SVG viewport, since they could transform the bounding box in a way that breaks it.
The last idea I have is to create a new <svg> element (with no transform), place in it one (or more) <g> whose function is to apply all the transform from the original SVG's viewBox to the target element's, then place (a copy of) the target element into it and eventually call getBBox() on the newly created SVG element: if I'm not mistaken, the resulting bbox should be what I need and I can set it as the viewBox of the original SVG. Although it might not work if the target element contains some <use> elements or similar stuff. I think it'll take quite some time to implement this and I'm afraid it will be wasted time since it won't work for whatever reason.
Are there other ways to obtain an element's bounding box relative to the SVG viewBox? Otherwise other ways to correctly render one element from an SVG to an image?

Is it possible to stretch a imageOverlay in leaflet?

I am making a leafletjs based application and I want the user to be able to 'draw' a svg image on the map. To accomplish this I am tracking the mousedown and mouseup events to define the imageBounds and using an imageOverlay to draw a svg image.
I want the svg image to be stretched so it completely fits the defined imageBounds, but instead is it scaled so it fits within the imageBounds without distorting the aspect ratio.
Is there a way to enable imageOverlays to ignore their original aspect ratio and stretch to fit in the imageBounds?
imageBounds = [southwest, northeast];
_tempShape = L.imageOverlay(_imageUrl, imageBounds);
_tempShape.addTo(_map);
EDIT: Tried to do the same thing with a bitmap image instead and it does stretch, so it seams to be a SVG specific thing.
I figured it out. It was not a leaflet problem but an inherent SVG behaviour. To allow a SVG to stretch while scaling I added the preserveAspectRatio="none" attribute to the SVG root node.
For anybody looking for more information on SVG scaling: https://css-tricks.com/scale-svg/

Canvas - Sticking png images together without taking into account transparent pixels

I have big horizontal strip image in photoshop which is made of lots of smaller elements. The background is transparent and the strip goes from smaller elements (left) to bigger elements (right). My goal is to make this strip interactive to mouse events.
Each element is some kind of polygonal image which is trimmed left and right and then exported as a png. It is then imported into a canvas.
The problem is that I can put them side by side but since they are not rectangles I need a way to calculate the offset made up by the transparent pixels on each side of each element to make them stick together correctly... I am using KineticJs to get a precise hitarea for each element... So maybe there is a way to do it automatically with kineticjs,or there is some kind of operation I could do using each image data?
My problem illustrated:
Any ideas?
Also I am doing this simply because I would prefer precise mouseOver bounding box on each item (rather than a simple rectangle) and would rather avoid the solution to calculate each offset manually... But maybe that's not worth it?!
Ok, so you have yourself a custom shape you want to use, here is a tutorial for that: http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-shape-tutorial/ , the simplest thing you can do, and even that seems fairly long, is to calculate the bounding lines for that shape. (Two somewhat vertical lines, and two somewhat horizontal lines). Then you test if the right vertical line of shape one crosses with the left vertical line of shape two, if they do, then set the coordinates of the images to be the same coordinate.
http://www.mathopenref.com/coordintersection.html
line1 = ax + b ..... line2 = cx+d //see possible tests
if(...intersection test...){ // or just test if some coordinate is left of some other coordinate
shape2.setX(shape1.getX()+shape1.getWidth()); //account for image width, so they don't overlap
shape2.setY(shape1.getY()) // no need to account for height
}
UPDATE: This is a very rough solution to the workings of the problem. The next step would be to do more fine tuning dependent on each image.
http://jsfiddle.net/9jkr7/15/
If you want precise areas, use an image map. With some clever finagling and a blank image gif you should be able to have the background you want whenever you hover over any particular area of the image map (might require javascript).
The other option I can think of would be to use SVG itself or one of the many libraries in existance to build interactive vector graphics into your page.
You could also write a function that calculates the left most, top most, right most, and bottom most pixel by looking at all of the pixels in the image data. Here's a tutorial on that:
http://www.html5canvastutorials.com/advanced/html5-canvas-get-image-data-tutorial/

Stretching/distorting a background image from a single point

Usually when an image is being resized in javascript or css3(using background-size), it will stretch an image from the center point. I need an image to be stretched and distorted from a single point that could be anywhere. It's going to be dynamic so I don't want to resort to using separate images.
Here's a pic that illustrates what I mean:
Hopefully there's an answer out there!
You have a few options to achieve this effect.
The "correct" way would be to use canvas to draw the image: Skewing images individually using canvas
Another way would be to fake the effect using the CSS transform skew.
http://developerdrive.com/demo/skewing_elements/skewing_elements.html
You would do this inside an element with "overflow: hidden" to make it look like a background image.
It's not even clear to me what you want from the image you're linking too. Do you want it distorted or not? And is the distortion uniform?
I'm going to guess whatever you're doing can be approximated by drawing an ever decreasing set of (or maybe rectangles) clipped from the center of a some image and drawing them onto a "canvas" (think generic term not html5 term) given new coordinates for the center of each clipping. There may be a faster way to draw this than redrawing parts of the image multiple times, it's just how I visualize it possibly working.. at least maybe in some mathematical sense.

Raphaƫl.js: How to scale a circle's fill image to fit the circle?

I'm trying to use Raphael's VML functionality for generating a circle with an image (fix for IE8 that lacks border-radius).
My problem is that if I use
circle.attr({fill: 'url(image.jpg)'});
and my image is larger than the circle the image is only partially showed and I can't find a way to downscale the image to the diameter of the circle.
How can I do this?
Are you serious about fixing IE8 border-radius with RaphaelJS?
I would suggest something like css3pie and there is even question in SO about usage.
But still, if you want to use RaphaelJS, you will need to use Element.transform to scale your image and only afterwards, set up rounded corners effect with another element.

Categories

Resources