3

I am working through an animation where I need to make this plane follow the path given and appear to be "circling" the earth. Here is the codePen, which as you can see is fairly simple.

Picture

My problem is with angles, I am trying to see how much should I rotate the plane as it moves through the path by calculating the slope of two points, and turning it into degrees.

Even though I have added an epsilon to safe-check for consistent differences across the points and every other safe-check, I am getting that as it approaches +-90 degrees, it changes signs, instead of passing to the other quadrant 120 degrees, etc.

I can understand that this is caused by the fact that formula

You can see this happening in the console right in the mid point (displays: slope, arctangent, degrees).

Console

To solve this, I am recurring to Math.atan2(), by using newPoint.x - firstPoint.x, newPoint.y - firstPoint.y as its arguments. It starts off with the right values (CodePen here). But it still does a funky rotation.

Here is the code (I'm not posting the SVG image because it's very large):

JS

        var snap = Snap('#Globe_1_');

        // Trail 1
        var trail1 = snap.path('M354.3,707.9c13.9,14.5,27.9,27.2,41.7,38c13.9,10.9,27.2,19.3,39.3,25.4 c12.6,6.1,24.8,9,35.7,10.3c10.9,1.2,21.1-1.2,30.2-5.4c17-7.8,29-24.8,35.7-48.3c7.2-23.5,9-55,5.4-91.8 c-3.7-36.8-12-77.9-24.8-120.9c-12.6-43-30.2-87.6-51.9-131.7c-21.1-44.1-45.2-85.8-70.7-122.7s-50.8-69.5-77.3-95.5 c-27.2-26-52.5-43.6-75.6-53.2c-22.9-9.7-43.6-10.3-60.4-2.5c-16.3,7.8-27.9,24.2-35.1,47.7c-7.2,23.5-9.7,53.8-6.6,88.8')
            .attr({
                id: 'trail1',
                fill:'none', 
                stroke: '#C25353',
                strokeMiterLimit: 10
            });

        var len = trail1.getTotalLength();

        var plane1 = snap.path('M375.7,708.4c0.1,0.8-0.7,1.8-1.6,1.9l-10.4,0.2l-8.4,15.1l-4,0l4.1-14.6l-7.8-0.2l-2.7,3.2L342,714 l1.6-4.9l-1.7-5.4l3.1,0.1l2.5,3.6l7.8,0.2l-4.3-14.6l4,0l8.3,14.7l10.4-0.2C375.5,706.7,376,707.1,375.7,708.4z') .attr({fill: '#CDCCCC' });


        var initPoint = trail1.getPointAtLength( 1 ),
            lastPoint,
            slope = 0,
            lastLen = 0;

        Snap.animate(0, len, function( value ) {

            movePoint = trail1.getPointAtLength( value );

            if (lastPoint && ( Math.abs(lastPoint.y - movePoint.y) > 1 || Math.abs(lastPoint.x - movePoint.x) > 1 )) {

                var slope_val = (lastPoint.y - movePoint.y) / (lastPoint.x - movePoint.x),
                    slope_atan = Math.atan2(movePoint.x - initPoint.x, movePoint.y - initPoint.y),
                    slope_deg = Snap.deg(slope_atan);

                slope = slope_deg;
                console.log('Capturing rotation', slope_val, slope_atan, slope_deg);
                lastLen = value; 

            }

            plane1.transform( 't' + parseInt(movePoint.x - 350) + ',' + parseInt( movePoint.y - 700) + 'r' + slope);

            lastPoint = movePoint;

        }, 5000, mina.linear);

Can you please help me out, thank you

Alain Jacomet Forte
  • 4,575
  • 6
  • 29
  • 41

1 Answers1

3

I'm not sure of the full effect you are after, if its purely 2d angle, Snap already has this built in (returning angle from point along line), so no need to work too hard...

element.getPointAtLength() returns an angle alpha, so movePoint.alpha can be used...

relevant line below, and other calculation lines removed.

plane1.transform( 't' + parseInt(movePoint.x - 350) + ',' + parseInt( movePoint.y - 700) + 'r' + (180 + movePoint.alpha));

codepen

Ian
  • 13,724
  • 4
  • 52
  • 75
  • Seems like you really know about this topic. Do you know why I have to apply that (-350, -700) translation to the path ? I have tried with different positionings for the svg @Ian – Alain Jacomet Forte Jul 21 '15 at 13:18
  • also if you want to give me a tip on how to add a 3D rotation on top of this, I'd appreciate it – Alain Jacomet Forte Jul 21 '15 at 14:29
  • You have to translate the path, because the first part of the path is ''M375.7,708.4' so it starts from that coordinate. To make it appear over the line, you need to move it back to 0,0. The alternative would be to have the path start at 0,0 (or maybe -10,-10 or whatever half the width is) and also relevant other absolute coordinates so it rotates around its center without needing any transform. It doesn't really matter too much though, just if its an option if its in some editor. – Ian Jul 21 '15 at 15:03
  • I don't know how to do 3d rotation in svg (as svg is just 2d so you would have to calculate stuff yourself, you may be able to fake some of it somehow). You could pose that specifically as a new question, as there is the odd example of recalculating paths for 3d, but not a lot of it about. Your previous example with css did perspective ok, but not sure that would work in IE10 or less. Or you may be able to use perspective if you apply that to the whole SVG (ie have different SVG layers overlapped over each other which could be interesting) – Ian Jul 21 '15 at 15:06