最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Scale loaded SVG and zoom in with snap svg - Stack Overflow

programmeradmin2浏览0评论

So basically what I need to do is to load an SVG with SNAP.svg and add an effect (zoom in) I understand that in order to achieve this I need to respect this :

  • Load the SVG file
  • Scale de SVG in (0 ?)
  • Append this SVG
  • Add a transform effect (with the suitable scale)

The problem is that I need to display this in a 650 width and 280 height size.

The SVG I'm loading, witch I'll name it 'map' is in 1920 width and 1080 height.

This is my code so far :

    <svg id="svg" width="650px" height="280px"></svg>
    <script type="text/javascript">
        var s = Snap("#svg");

        var map = Snap.load("./src/map.svg", function (f) {
                        g = f.select("g");
                        var t = Snap.matrix().scale(0.35);
                        s.append(g);
                        g.group(g.selectAll("path")).transform(t);  
                    });
    </script>

It seems the scale instruction is working find but not the animation. Also, how I can center this loaded SVG not matter what scale it takes ?

Thank you !

UPDATE :

I managed to add some effects but I don't think the way I'm doing it it's the correct one :

            var carte = Snap.load("./src/carte.svg", function (f) {
                        g = f.select("g");
                        //var t = Snap.matrix().scale(0.35);
                        s.append(g);
                        //Set the map in first position
                        var firstScene = new Snap.Matrix();
                        firstScene.translate(300, 160);
                        firstScene.scale(0.05);

                        //Zoom effect
                        var secondScene = new Snap.Matrix();
                            secondScene.scale(2.0);
                            secondScene.translate(-850, -360);

                        //Move the matrix till desired point (not finish)
                        var threeScene = new Snap.Matrix();
                            threeScene.translate(-850, -360);

                        g.animate({ transform: firstScene }, 0, function() {g.animate ({ transform: secondScene}, 1500, mina.linear )});

                    });

It seems impossible to add a timer or more than two effects ?

So basically what I need to do is to load an SVG with SNAP.svg and add an effect (zoom in) I understand that in order to achieve this I need to respect this :

  • Load the SVG file
  • Scale de SVG in (0 ?)
  • Append this SVG
  • Add a transform effect (with the suitable scale)

The problem is that I need to display this in a 650 width and 280 height size.

The SVG I'm loading, witch I'll name it 'map' is in 1920 width and 1080 height.

This is my code so far :

    <svg id="svg" width="650px" height="280px"></svg>
    <script type="text/javascript">
        var s = Snap("#svg");

        var map = Snap.load("./src/map.svg", function (f) {
                        g = f.select("g");
                        var t = Snap.matrix().scale(0.35);
                        s.append(g);
                        g.group(g.selectAll("path")).transform(t);  
                    });
    </script>

It seems the scale instruction is working find but not the animation. Also, how I can center this loaded SVG not matter what scale it takes ?

Thank you !

UPDATE :

I managed to add some effects but I don't think the way I'm doing it it's the correct one :

            var carte = Snap.load("./src/carte.svg", function (f) {
                        g = f.select("g");
                        //var t = Snap.matrix().scale(0.35);
                        s.append(g);
                        //Set the map in first position
                        var firstScene = new Snap.Matrix();
                        firstScene.translate(300, 160);
                        firstScene.scale(0.05);

                        //Zoom effect
                        var secondScene = new Snap.Matrix();
                            secondScene.scale(2.0);
                            secondScene.translate(-850, -360);

                        //Move the matrix till desired point (not finish)
                        var threeScene = new Snap.Matrix();
                            threeScene.translate(-850, -360);

                        g.animate({ transform: firstScene }, 0, function() {g.animate ({ transform: secondScene}, 1500, mina.linear )});

                    });

It seems impossible to add a timer or more than two effects ?

Share Improve this question edited Jan 21, 2015 at 0:14 Russo asked Jan 20, 2015 at 5:37 RussoRusso 3413 silver badges12 bronze badges 4
  • Could you put it on a jsfiddle ? I'd probably just use Snaps transform strings, like transform('s0.35'), save a bit of code. There isn't any animation in your code ? You can also basically zoom in just via changing the viewBox on the svg (s) element if you want to zoom everything in. – Ian Commented Jan 20, 2015 at 10:33
  • I already using transform and it seems to work, but the problem is that I whant to add an animation and I can't find the way – Russo Commented Jan 20, 2015 at 21:52
  • You can just call a callback on the 2nd animate too to get a 3rd, but at that point you probably want to do something slightly different code wise. Here's a possible example of one route you could take svg.dabbles.info/snaptut-animateframe (if its useful I'll put the code as an answer) – Ian Commented Jan 21, 2015 at 9:29
  • It seems to be the correct way in order to add animations, I finally managed to make this work, you can post as an answer too – Russo Commented Jan 22, 2015 at 1:19
Add a ment  | 

3 Answers 3

Reset to default 4

Just as an alternative if there are quite a few sequenced animations I may be tempted to write a function to handle an array of animations. It could look something like this...

function nextFrame ( el, frameArray,  whichFrame ) {
    if( whichFrame >= frameArray.length ) { return }
    el.animate( frameArray[ whichFrame ].animation, 
                frameArray[ whichFrame ].dur, 
                frameArray[ whichFrame ].easing, 
                nextFrame.bind( null, el, frameArray, whichFrame + 1 ) );
}

var block = s.rect(100, 100, 100, 100, 20, 20);
             .attr({ fill: "rgb(236, 240, 241)", stroke: "#1f2c39",
                     strokeWidth: 3, transform: 's1' });

var frames = [
    { animation: { transform: 's0.4,0.4,200,200' },         dur: 1000, easing: mina.bounce },
    { animation: { transform: 't-100,-80' },                dur: 1000, easing: mina.bounce },
    { animation: { transform: 's1.2,1.2,300,300t200,-100' },dur: 1000, easing: mina.bounce }
    ];

nextFrame( block, frames, 0 );

jsfiddle

This seems to work fine, but like lan said above, maybe his method it's better for doing animations

        var carte = Snap.load("./src/carte.svg", function (f) {
                        g = f.select("g");
                        //var t = Snap.matrix().scale(0.35);
                        s.append(g);
                        //Load the map
                        var firstScene = new Snap.Matrix();
                        firstScene.translate(295, 160);
                        firstScene.scale(0.04);

                        //Set scene 1
                        var secondScene = new Snap.Matrix();
                            secondScene.scale(0.4);
                            secondScene.translate(-300, -10);

                        //Set scene 2
                        var threeScene = new Snap.Matrix();
                            //threeScene.scale(0.5);
                            threeScene.translate(-825, -380);

                        //Set scene 3
                        var fourScene = new Snap.Matrix();
                            fourScene.scale(21.0);
                            fourScene.translate(-1164, -526);

                        var anim1 = function() {
                            g.animate({ transform: firstScene}, 0, anim2);
                        }
                        var anim2 = function() {
                            g.animate({ transform: secondScene}, 1500, mina.easing, anim3);
                        }
                        var anim3 = function() {
                            g.animate({ transform: threeScene}, 1000, mina.linear, anim4);

                        }
                        var anim4 = function() {
                            g.animate({ transform: fourScene}, 2000, mina.easing);

                        }

                        anim1();

                    });

Is the fact of adding several matrix a performance killer ? Or this is the way it should be done ?

I think if you want to sequence animations, the most elegant way would be to use promises. For that all you would need is to wrap animate function in Q library or jQuery.Deferred. Here is the example I put together on jsFiddle https://jsfiddle/stsvilik/Lnhc77b2/

 function animate(obj, conf, duration, asing) {
     var def = Q.defer();
     obj.animate(conf, dur, easing, function(){
        def.resolve();
     });
     return def.promise;
 }
发布评论

评论列表(0)

  1. 暂无评论