Jump to content
Search Community

Move then tween on a path???

SLSCoder test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

I'm not sure I follow everything you're asking, but it sounds like you plan to use .pngs and are not including them as child elements of the SVG?

 

If you want the position and size data of the SVG, I'd use getBoundingClientRect();

https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect

 

If you could provide a demo, it would help answer any new questions. 

 

Thanks.

 

 

 

  • Like 1
Link to comment
Share on other sites

Actually I've got the png files inside the svg as you recommended.

It didn't seem to matter in my case because I've got css set to a percentage so they'll scale anyway.

 

I tried using getBoundingClientRect(); but it didn't return width or height correctly for any browser size.

That is, sometimes it seemed to work, most of the time it was off.

I googled it and found that different browsers respond differently and not accurately.

I mostly test in IE because it's the most problematic.

 

I realize this is outside the realm of greensock. I really appreciate your patience with me.

Link to comment
Share on other sites

Hm, I don't think I've ever heard of getBoundingClientRect() being wrong most of the time - it has always worked flawlessly for me in every browser, so I'm really curious. Do you have an example that shows it being inaccurate? I wonder if perhaps you're misunderstanding what it's supposed to return? 

  • Like 1
Link to comment
Share on other sites

OK, I've got a new CodePen.
The .png files are inside the <svg> tag.
1. I can't move the SVG so that when the dead center (where the 2 arcs meet) is on the top left of the BigLogo.png.
2. When the SVG resizes (because CSS %)  the images inside the SVG don't resize. That's OK, I resize them using % in CSS.
3. When the animation runs the size is not scaled to the new size of the Arcs and it's way off position.

I'm sorry this is so difficult for me.

See the Pen dzwrOy by SLSCoder (@SLSCoder) on CodePen

 

Link to comment
Share on other sites

2 hours ago, GreenSock said:

Hm, I don't think I've ever heard of getBoundingClientRect() being wrong most of the time - it has always worked flawlessly for me in every browser, so I'm really curious. Do you have an example that shows it being inaccurate? I wonder if perhaps you're misunderstanding what it's supposed to return? 

Could be I'm not using it right. I'll update the Codepen above to try to use it.

Maybe I'll get lucky :-o

 

OK, I've added  getBoundingClientRect().
When I change the screen size the width does change.
The height does not change.

 

So far, I can't use this animation at all.

If I can't find both the width & height I can't position the paths.
I have to use .png (or image format) because I'll have to do this with photographs as well.
 

Is the only way to make an animation with a bezier path that starts on the bottom and is responsive to use vectors?
Can it be done using image files at all?

Thanks again for all your help.

Link to comment
Share on other sites

I think you may be overthinking this whole animation. If you put all the images inside the SVG, this should work just fine. I've made a fork of your pen and added a gray rectangle just so it's clear where the actual SVG is sitting.

 

See the Pen ayPxBN by PointC (@PointC) on CodePen

I had to make some manual adjustments to the smaller pngs x/y position so they'd land on the main graphic correctly because they are different sizes. (If all three images were the same size, they'd be easy to line up) You can clearly see scaling is a bit of an issue using images instead of paths, but the whole thing does scale up and down and maintains path and image position as you'd expect.

 

Hopefully that helps. Happy tweening.

 

  • Like 2
Link to comment
Share on other sites

I see. I was using <img tags inside the svg.

I think what I need to do is learn how to manipulate svg.

I notice that CSS has no control over the elements inside the svg.

I'll do some studying and play with this Codepen a bit.
I'm sure now that I can make it work but I've gotta learn svg.

If I *ever* get this whole animation done I'll show it to you.
Thanks *again* for your help.

Link to comment
Share on other sites

On 8/30/2017 at 6:11 PM, SLSCoder said:

I've gotta make this animation responsive.

How can I make the path and the motion scalable in Javascript?

I tried using align but to no avail.

 

I set those demos up to handle different sizes because I knew that was going to be your next question. But forget all that for now. I see that is just going to lead us down another rabbit hole.

 

Just do EXACTLY what @PointC is telling you to do, and it will work. 

 

I would highly recommend to read up on SVG before trying to do anymore animating. Here's a good place to start. Please go through every item.

http://tutorials.jenkov.com/svg/index.html

 

You can use CSS with SVG, but most of the properties are different than HTML. Notice there is no left or top anywhere. 

https://www.w3.org/TR/SVG/styling.html#SVGStylingProperties

 

  • Like 5
Link to comment
Share on other sites

OK, I've read Jenkov's entire tutorial on SVG. Thanks for that. It was very informative.

Now I see, an SVG element is more like an iFrame than a normal html element.

In addition, a whole new set of (similar) rules apply. The coordinate systems are two separate systems.

 

I'm still stuck. I think I can just make the SVG the entire screen width & height but what I really wanted was for the BigLogo to not be inside the SVG.

The reason is simply that it flies up to the left corner of the page and shrinks at the end of the animation. It remains permanently. The 'logo parts' the arcs and the svg - disappear - if I can do that.

 

My problem is conceptually simple. I can't find the center of the scaled svg in Javascript.

Again, I realize this isn't a Greensock issue. I've hunted for information and for forums on SVG. I can't find anything.

The best reference I've gotten was the one Blake gave me.

 

If you don't know of a way to find the center of the scaled SVG I understand. You guys didn't write SVG or HTML's handling of it.

Thanks much for your help either way.

Link to comment
Share on other sites

If your SVG doesn't have a viewBox, no scaling will take place, so 100px inside your SVG is the same as 100px outside your SVG.

 

If your SVG does have a viewBox, the center can be calculated from it. So for this... 

viewBox="0 0 1000 1000"

 

The center of the viewBox would be 500, 500. It's just half the width and height values of the viewBox. In this demo, the blue rectangle represents the viewBox, so to move the circle to the center, I just tween it to 500, 500.

 

 

See the Pen 94db3f5126162ae065a299ba373fc07b by osublake (@osublake) on CodePen

 

Note that I'm not counting the gray part (the background) of the demo as part of the viewBox. That's like the letterbox of a movie. You can control where and how the viewBox is positioned using the preserveAspectRatio attribute. 

 

You can get the position and size of something inside your SVG using the getBBox method. Note that this method has some gotchas as explained here.

 

12 hours ago, SLSCoder said:

The reason is simply that it flies up to the left corner of the page and shrinks at the end of the animation. It remains permanently. The 'logo parts' the arcs and the svg - disappear - if I can do that.

 

This is easy to do. Make a demo that moves your logos to center, and I can show you how to do this. Basically, it involves using getBoundingClientRect to absolute position and scale the permanent logo over the animated logo. From there you hide the animated logo/SVG, and animate the permanent logo to it's final place and size.

 

This post explains how to do something similar, although you probably won't need to use 3 elements for what you're doing.

 

  • Like 4
Link to comment
Share on other sites

Thanks very much for your response Blake.

I'm sorry to keep coming back to you with this. I realize it's not greensock, it's SVG.

I can't find anybody on the Internet who really knows anything about SVG positioning (especially related to HTML coordinates), except you.

I started developing software in 1994 and am Microsoft certified as a programmer. I program in multiple languages. In this case, HTML, CSS, Javascript and now SVG. I am finding SVG positioning to be a nightmare so far. At this point I'd rather learn C than SVG. It's easier.

 

PLAN A: Position the SVG in the HTML coordinates to make LogoBig dead center.

I wasn't clear about 'center'. I can't find SVG center in the HTML coordinate system. I can  find it easily in the SVG coordinates.

This is because the site is responsive so the 'size' of the SVG changes with the browser window size.

I can't get the width AND height of the scaled SVG in Javascript.
I tried using getBoundingClientRect() . In my last Codepen I show the numbers (width & height).

Width does change with the screen size but not height.

I also tried getBBox - no cigar.

Scrap that - I can't position an SVG based on it's center, in HTML coordinates.

 

PLAN B: Make the SVG's size =  $(window).width()  * $(window).height() and position the elements within the SVG.

I want the BigLogo centered in the browser window. The viewBox's x & y are both at 0.

That should be the top left corner of the viewPort yes? which is also the top left corner of the browser window, yes?

Position LogoBig X:  (viewBox.width/2) - (BigLogo.width/2) should put LogoBig dead center (x, not y).

Position LogoBig Y:  (viewBox.height/2) - (BigLogo.height/2) should put LogoBig dead center (y this time).

That doesn't work. Y seems ok 'this time'. X  is too far left.

Position Both Arcs: Make the top & bottom arc MEET right at BigLogo's X, Y point.
I can't even determine the width or height of the arcs let alone actually expect SVG to put them in the right place.

HELP!! - would be greatly appreciated.

See the Pen MvRrwX by SLSCoder (@SLSCoder) on CodePen

 

 

 

 

 

 

 

 

 

Link to comment
Share on other sites

Thanks much Mike. Interesting twist on my animation :)

I see, you use CSS to put the top left corner of the SVG in the center, then you use

TweenMax.set(".centered", {xPercent:-50, yPercent:-50});

to pull it into center.

That worked!

I still don't have any faith in SVG's x, y coordinate system. I fear in the future, positioning SVG will always require some finagling.

 

Can I ask how you generated the code for the SVGs?

Thanks again, I think I can move on with this job now - finally.

Link to comment
Share on other sites

2 hours ago, SLSCoder said:

I still don't have any faith in SVG's x, y coordinate system. I fear in the future, positioning SVG will always require some finagling.

 

There's nothing wrong with the SVG coordinate system. It's consistent, and works pretty much the same as every 2d graphics library ever made. 

 

Everything is based on a transformation matrix. That's the key. Unfortunately, I cannot recommend a single resource to help you out with that because I've never seen one, so good luck with that. There are ways to get and work with those transformation matrices in the browser, but again, good luck finding any documentation on it.

 

Here's a really simple example that converts the mouse position into the coordinate space of the SVG. Try resizing it and using different values values for the preserveAspectRatio attribute. There are ways to figure everything out.

 

See the Pen 3cee7fb024ee232db4ee09d153fc96e5 by osublake (@osublake) on CodePen

 

 

 

 

 

  • Like 4
Link to comment
Share on other sites

Thanks Blake.

I did find this. It's for CSS, not SVG. Are the concepts the same?
CSS3 Transform Matrix.

Then there's this: SVG Coordinate Transformations.

 

I almost understand this

var pt = point.matrixTransform(svg.getScreenCTM().inverse());

I don't understand why 'inverse()'.

 

My problem has been with positioning the SVG in the HTML.

I finally did find a way to get the width and height of the SVG, even scaled using JQuery.

$("#svg").width(), $("#svg").height();

I've got a couple questions about the Html VS. SVG numbers.

1. If CSS/HTML doesn't specify units, it defaults to px? Also, if SVG units aren't specified do they default to px?

2. If so, why do the SVG numbers increase faster than the CSS numbers? This is what tripped me up.

Maybe this is the question. Is a pixel different in size between the CSS & the SVG?

 

I'm still studying . . . and really appreciate your help.

Link to comment
Share on other sites

I'd strongly recommend reading through the link that @Carl posted above. It's a wonderful resource for understanding SVG coordinate systems, the viewBox and viewport. This is a copy and paste directly from that post.

 

In SVG, values can be set with or without a unit identifier. A unitless value is said to be specified in user space using user units. If a value is specified in user units, then the value is assumed to be equivalent to the same number of “px” units. You can also specify values using units. The supported length unit identifiers in SVG are: em, ex, px, pt, pc, cm, mm, in, and percentages.

 

SVG numbers increase faster than CSS? I don't follow that question, but here's a little demo I made as an answer to another question in the forum that may help. See how it's three copies of the same SVG and they all move 350 units on the x and then 50 on the y? The only one that's actually moving 350 pixels is the middle one. You have to remember that SVG elements live in their own world. Again, I highly recommend the article above for a better understanding.  

 

See the Pen QyjMaW by PointC (@PointC) on CodePen

Happy tweening.

:)

  • Like 2
Link to comment
Share on other sites

14 hours ago, SLSCoder said:

I did find this. It's for CSS, not SVG. Are the concepts the same?
CSS3 Transform Matrix.

Then there's this: SVG Coordinate Transformations.

 

Yep. Math works the same everywhere, so it's the same concept. There's an abundance of information about how to do matrix transforms, but you'll almost never see how it relates to SVG or how to use it with SVG DOM methods.

 

14 hours ago, SLSCoder said:

1. If CSS/HTML doesn't specify units, it defaults to px?

 

There is no default unit for CSS/HTML. However, you don't have specify units when using GSAP. It will automatically add "px" to the value if you don't specify one.

 

14 hours ago, SLSCoder said:

Also, if SVG units aren't specified do they default to px?

 

Yes, but that's probably why you're getting confused. Stop thinking in pixels. Think in values. 

 

14 hours ago, SLSCoder said:

2. If so, why do the SVG numbers increase faster than the CSS numbers? This is what tripped me up.

 

Because the coordinates are being scaled. But it's all about relativity. Imagine that you are standing 1 foot away from me and then I scale you down to the size of an ant. To me, you'll still be 1 foot away, but to you I will be like a mile away.

 

You're getting confused because you're thinking about everything relative to screen coordinates. Think about an image. What happens when you change it's size? It scales the image to fit the dimensions you specified, so the size and position of all those pixel values are completely different than what they were.

 

Once you start to think about the size and position of stuff in terms of relativity, it will start to make more sense. 

  • Like 2
Link to comment
Share on other sites

OK, I've read the entire first part of the 3 part series by Sara Soueidan - again - this time very slowly, working with the demo throughout it.

I'll read Part 2 tomorrow.

 

I think I understand now. The viewPort is what you see. The viewBox is what the graphics are in.

The viewBox is exactly the same size as the viewPort visually even if the units are different numbers (different units).

So, if the viewBox width is 400 and the viewPort width is 800, then 1 viewBox unit = 2 viewPort units.

The graphics inside the viewBox maintain the same number of viewBox units, no matter the size (in units) of the viewBox.

Therefore graphics would appear smaller (viewPort & viewBox are visually the same) in a larger viewBox (in units) and visa versa.

 

So this should let me position SVG elements according to HTML units:
1 HTMLSVGUnit = 1SVGUnit * (1HTMLUnit/1SVGUnit)

To move an SVG element 1 HTML unit I have to move it 1 HTMLSVGUnit (yea I made that up :-\).

Is that right?

 

Link to comment
Share on other sites

Hi @SLSCoder

 

It sounds like you have a better understanding, but might not be seeing what's really going on. Elements are positioned inside an SVG based on an aspect ratio, so your conversion will only work under certain conditions. 

 

Here's a demo to help you understand aspect ratio better. I'm positioning HTML elements using CSS as if they were part of an SVG graphic. Try changing the alignX/alignY variables to "min", "mid", or "max", and the aspectType to "meet", "slice", or "none". Go through every line of code to see what's going on. That's essentially what is going on inside an SVG at the top level.

 

 

  • Like 3
Link to comment
Share on other sites

Thanks Blake. It took about 5 minutes to realize I still didn't have it.

I had Irma to deal with, being in Central Florida.

 

I understand the preserveAspectRatio attribute after reading that article.

I was playing with: Interactive SVG Coordinate Demo

Admittedly, I didn't take it into account.

 

My biggest problem is not being able to get the size of the SVG after it's been scaled, in HTML coordinates.

I tried

I can put the top, left corner in a specific position but it's hard to know where that is without knowing it's height & width.

 

I read through your code. Impressive. I made comments

// Demonstrates how the aspect ratio is calculated inside an SVG
// https://greensock.com/forums/topic/17018-move-then-tween-on-a-path/?page=2&tab=comments#comment-76430


// Try meet, slice, or none
var aspectType = "meet";

// Try min, mid, or max
var alignX = "mid";
var alignY = "mid";

var viewport = document.querySelector(".viewport");
var image = document.querySelector(".image");
var ball = document.querySelector(".ball");

var viewBox = {
  width: 1920,
  height: 1080
};

// Represents values from getBBox()
var ballBox = {
  x: ball.offsetLeft,
  y: ball.offsetTop,
  width: ball.offsetWidth,
  height: ball.offsetHeight
};

window.addEventListener("resize", resize);
resize();

function resize() {
  
	var viewportWidth = viewport.offsetWidth;
	var viewportHeight = viewport.offsetHeight;
	
	//AHH - the HtmlToSvg	Unit
	var scaleX = viewportWidth  / viewBox.width;
	var scaleY = viewportHeight / viewBox.height;
	
	//Preserve the aspect ratio
	if (aspectType === "meet") {
	//Set the scale for both X & Y so the viewPort contains the viewBox
	scaleX = scaleY = Math.min(scaleX, scaleY);    
	} else if (aspectType === "slice") {
	//Set the scale for both X & Y so the viewBox completely fills the viewPort
	scaleX = scaleY = Math.max(scaleX, scaleY);
	}
	
	//scaleX & scaleY are equal - scale 
	var viewWidth  = viewBox.width  * scaleX;
	var viewHeight = viewBox.height * scaleY;
	
	var viewX = 0; //if alignX === "min" left of the viewBox @ left of the viewPort
	var viewY = 0; //if alignX === "min" top of the viewBox @ top of the viewPort
	
	if (alignX === "mid") {
	viewX = (viewportWidth - viewWidth) / 2; //center of viewBox @ center of viewPort
	} else if (alignX === "max") { 
	viewX = viewportWidth - viewWidth;  //right of viewBox @ right of viewPort
	}
	
	if (alignY === "mid") {
	viewY = (viewportHeight - viewHeight) / 2; //Middle of viewBox @ middle of viewPort
	} else if (alignY === "max") {
	viewY = viewportHeight - viewHeight;  //Bottom of viewBox @ bottom of viewPort
	}
	
	
	//Manually scale the image & ball to position & preserve the aspect ratio.
	image.style.left = viewX + "px";
	image.style.top  = viewY + "px";
	image.style.width  = viewWidth  + "px";
	image.style.height = viewHeight + "px";
	
	ball.style.left = (viewX + ballBox.x * scaleX) + "px";
	ball.style.top  = (viewY + ballBox.y * scaleY) + "px";
	ball.style.width  = (ballBox.width  * scaleX) + "px";
	ball.style.height = (ballBox.height * scaleY) + "px";
}

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...