How to use preserveAspectRatio on SVG <symbol> using SVG.JS - javascript

I recently found out about using 'preserveAspectRatio' on symbols in SVGs, which I will be honest was a gamechanger for they type of designs I have been trying to accomplish. However, I can't seem to get it to work using SVG.JS.
Link to JS Fiddle
/* canvas created */
var draw = SVG('maindiv').viewbox('0 0 500 500').attr({ 'preserveAspectRatio': 'none' })
/* polgon created */
var polyg = draw.polygon('0,150 500,150 500,500 0,500').fill('black')
/* symbol created and inserted, with functioning viewbox but preserveAspect ratio not working */
var txt = draw.symbol().viewbox('0 0 500 500').attr({ 'preserveAspectRatio': 'xMinYMin meet' })
txt.text('Some Text').font({family: 'Arial',weight: 'bold',size: 30,fill: '#f06'})
var title = draw.use(txt)
/* clickable animation */
polyg.click(function() {
this.animate().attr({'points':'0,350 500,350 500,500 0,500'})
})
If you take a look at that code in the link, the black polygon correctly extends the entire viewport, but the text which is in fact a symbol, should NOT scale with the viewport. Go ahead and resize your window and you will see that the text resizes itself.
Any ideas? There's a lack of documentation on how to do this using SVG.JS so I'm sure this will help a few people out there who are trying to acheive this same challenge of having multiple elements in the same SVG canvas, some responsive to the viewport and some static.

Related

Zoom image given x and y

I have an image which as a "ruler" (made of basic divs positioned absolute on top of the image) that are use to measure the ends of the image. Now the idea is that if you long press one of the ruler ends (the dots at the end of the line which are draggable), the image in the background would zoom in that point, and follow the dot if the user moves it. I am able to detect the long press but I cannot get the image to zoom and follow the dot once detected. The code below is where I have done the detection and now I should apply the styling to move the image. I thought of using the transition property but couldn't get it to zoom on the dot. Any help is appreciated...
Here's a codesandbox with how the ruler works: Link
Meaningful code:
const x = get('x', varToUse); //This just gives the x coordinate of the ruler end
const y = get('y', varToUse); //This just gives the y coordinate of the ruler end
const image = ruler.current.parentElement.parentElement.childNodes[1].childNodes[1];
if (zoom) {
image.style.transform = `translate(${x * 2}px, ${y * 2}px) scale(2.0)`;
} else {
image.style.transform = `scale(1.0)`;
}
This is what the ruler looks like just to get an understanding:
You can make the image a div with background-image.
.image {
background-image: url({image_url});
}
so this way you can update the image size and position easily with this properties
.image {
background-size: x y;
background-position x y;
}
I think this way is easier to do the image resizing and zoom abilities.
another way is to use a canvas library that can help you a lot they have lots of built in functions.
I think trying it without library is better for now but as it grows try to move to a canvas library
The first reason is that in the code you provided, the DOM element that is being manipulated is a div id='root'. The image should be selected.

How to use stage width and height in Adobe Animate CC (Canvas doc)

I'm trying to center something on the stage using javascript inside an Adobe Animate CC canvas doc. Before in AS3 I would have accesses to the stage property.
So I would be able to do something like this
trace(stage.width);
I tried the same in js, but doesn't seem to work.
console.log(stage.width);
Does anyone know if there is an equivalent to the stage property in create js?
In a canvas project, use stage.canvas.width
For example, if you have a clip named myClip, you can center it like this:
this.myClip.x = stage.canvas.width / 2;
container.x = (lib.properties["width"]/2);
container.y = (lib.properties["height"]/2);
you can set values to lib properties. example:
lib.properties["height"] = "800"; // change to whatever you want
You can check your main js files top lines. These lines affect the style of you main canvas tag(check with inspect element). Notice that stage.canvas.width/heigth values change with browser resizing but lib.properties not so much
check image --> using lib. properties instead of stage
I'm not sure how to change the size or position in the .js,
In Adobe Animate cc 2015.2 you simply open the .fla file and go to "publish settings" and select "centre stage" + "make responsive". this obviously for the browser.
If you mean actually positioning the stage to centre inside Animate CC.
You will find an icon next to the "zoom" (100%), just click that and it will centre your project. Image of the icon I am talking about.

Apply zoom in center of the canvas

I need to apply zoom to the javascript canvas which I have badly accomplished by using the following line of code:
ctx.scale(2,2) //doubles everything's size
Instead of zooming, its obviously doubling the size of the canvas and all of its elements. I'd be okay with this if I got it working like the image below shows:
Any ideas on how I could accomplish what is depicted in the picture above? I'm not using any external libraries hence making this so difficult. Thanks.
You can translate the context by half the canvas size using ctx.translate()
EDIT :
var zoomfactor = 2; //set whatever you want as zoom factor
ctx.transform(zoomfactor,0,0,zoomfactor,-(zoomfactor-1)*canvas.width/2,-(zoomfactor-1)*canvas.height/2)

What to do with SVG so it can be resized using Javascript?

Let's say I loaded SVG, displayed it in browser, and so far it is OK.
Now, I would like to resize it. All methods I found googling failed to give me the desired effect.
It is all variations of:
$svg.removeAttr('width')
.removeAttr('height')
//.attr('preserveAspectRatio','xMinYMin meet')
//.css('width',width+'px')
//.css('height',height+'px')
.css('width','100%')
.css('height','100%')
.attr('viewBox','0 0 '+width+' '+height)
;
Nothing. I get the view of desired size, but the image (SVG) is clipped to that view instead of being resized. Setting size via attributes does not change a thing. Like the size of that SVG is carved in stone.
Thanks to frenchie answer (see below) it appears JS tries hard to resize SVG and for basic SVG it just works. So the real question is -- what to do with SVG (real-world SVG, not just a rectangle) so Javascript would be able to resize it?
SVG I am testing: http://jsfiddle.net/D6599/
I created SVG with Inkscape, and this is how I load SVG in JS:
$.get(svg_url, function(data) {
// Get the SVG tag, ignore the rest
svg = $(data).find('svg')
.attr('id', 'SVG')
// Remove any invalid XML tags as per http://validator.w3.org
.removeAttr('xmlns:a')
[0];
on_load();
}, 'xml');
The code comes from How to change color of SVG image using CSS (jQuery SVG image replacement)?. What I have later on is svg element (I wrapped it using jQuery).
This is not the question how to load SVG, or what to do with cross-domain issue. SVG loads fine, it is the same domain as the script (my disk).
Your SVG markup should look like this:
<svg id="SomeID" height="20" width="20">......</svg>
So all you need to do is reset the css properties. Something like this should work:
$('#SomeID').css({'width':40, 'height' :40});
And if you can't change the id of the SVG markup then you can simply wrap it around a div like this:
<div id="SomeID"><svg>....</svg></div>
$('#SomeID').find('svg').css({'width': 40, 'height': 40});
Here's a jsFiddle:
function Start() {
$('#TheButton').click(ResizeSVG);
};
function ResizeSVG() {
$('#TheSVG').css({'width':40, 'height' :40});
}
$(Start);
Finally I found it. I hope it will change in future, but for now there is a crucial difference if you change attribute by editing actual SVG file, and changing SVG on-fly using Javascript.
In order JS could resize SVG you have to manually edit SVG file and change height and width attributes to following lines.
Before:
width="600px"
height="560px"
After:
viewBox="0 0 600 560"
width="100%"
height="100%"
Of course in your case the values will be different. Please note that you can change those attributes programmatically with Javascript but it does not work (at least not for me).
Now, you can load such file as usual and compute, let's say width/height ratio.
var vbox = $svg.attr('viewBox').split(' ');
var w_ratio = vbox[2]/vbox[3]; // width/height
Such fixed file is still readable by Inkscape, I don't know how about other programs.

Cross - browser issues using Raphael JS

I am creating a rectangle element in raphael JS as a tooltip on an SVG circle element generated by raphael JS. I am unable to access the coordinates of the center of the circle (which I need to place the rectangle tooltip) using the following code in Internet Explorer..
var c = {};
c.x = parseInt(c_element.node.attributes[0].nodeValue);
c.y = parseInt(c_element.node.attributes[1].nodeValue);
//code for the rectangle element tooltip
r = paper.rect(c.x,c.y,50,50);
Its working fine in Firefox.. But in IE, the tooltip gets created at the upper left corner of the div enclosing my raphael JS paper and not on the center o the circle as desired..
How do I solve this cross-browser issue? Please help..
I don't know for certain why IE doesn't like this, but there's a much easier way:
c.x = c_element.attr("cx");
c.y = c_element.attr("cy");
jsFiddle
If you log the Raphael object to the console, you can check out the "attrs" property to see what's in there. Different for every type of Raphael object.
While we're all here: I highly recommend using an absolutely positioned div for your tooltips. HTML handles things like wrapping text and resizing the tooltip to accomodate different amounts of text much more easily than the SVG text element. See this answer. (Whatever you use, you'll still need to access the coordinates of the circle.)

Categories

Resources