javascriptraphaelsvgpanzoom

How to add new element with svg-pan-zoom library?


I'm using a pan-zoom library for zooming SVG elements. When I try adding a new path after zoom it displays improperly according to the old coordinates. Here is the code - JSFIDDLE. The problem may occur because the new element is not placed in the pan-zoom HTML tag. How to add the new object to place it at the correct pan-zoom coordinates?

$j(function() {
  var paper = Raphael('map', 1024, 768),

    attributes = {
      fill: 'none',
      stroke: '#808080',
      'fill-opacity': 0.6,
      'mode': 'multiply',
    }

 paper.canvas.setAttribute("viewBox", "0 0 647.67999 432.95999");
 paper.canvas.setAttribute('id', 'mySvgElement');
    
        //Compare the params
        var compareSize = function(boxWidth, boxHeight, minValue) {
            if ((boxWidth + boxHeight)/24 < minValue) {
            return minValue;
            } else {
            return (boxWidth + boxHeight)/24;
            }
        }
    //Show route

    var root = paper.path('M124.00721,89.633281C124.29828,91.15717599999999,124.58836,92.680072,124.87743,94.201967C124.51583000000001,95.145731,124.15325,96.23349499999999,123.78965000000001,97.247759C123.50057000000001,98.771685,123.21050000000001,100.29455,122.91943,101.81645C122.70287,102.90525000000001,122.48531000000001,103.99301,122.26676,105.07979C122.26776000000001,106.38616,122.26776000000001,107.69147000000001,122.26676,108.99581C122.63036000000001,109.79453000000001,122.99295000000001,110.59222000000001,123.35454,111.38893C123.71814,111.89757,124.51584,113.13038,125.09499,113.99961C125.74866999999999,115.30597,126.40133,116.61129,127.053,117.91563000000001C127.054,119.14947000000001,127.054,120.38227,127.053,121.61409C127.34407999999999,122.92045,127.63414999999999,124.22577000000001,127.92323,125.5301C128.57691,126.25631,129.22957,126.98148,129.88123000000002,127.70567C131.69524,129.08455,133.50818,130.46239,135.32015,131.83924C136.40895,133.21813,137.49671,134.59596,138.58349,135.97281999999998C139.23718000000002,137.93185999999997,139.88983000000002,139.88983,140.5415,141.84684C140.54250000000002,143.95093,140.54250000000002,146.05392999999998,140.5415,148.15598C140.03486,150.40511,139.52724,152.65315,139.01861000000002,154.90023C139.52725000000004,156.93179999999998,140.03487,158.96229,140.5415,160.99181C140.39746000000002,162.80581999999998,140.25243,164.61875999999998,140.10639,166.43072999999998C140.25243,168.31725999999998,140.39747,170.20271,140.5415,172.0872C140.76006,174.11876,140.97762,176.14925,141.19417,178.17878C141.41273,180.06530999999998,141.63029,181.95076,141.84684000000001,183.83525C141.77534000000003,185.28665,141.70280000000002,186.737,141.62929000000003,188.18638C140.97760000000002,190.14543,140.32495000000003,192.10340000000002,139.67128000000002,194.06040000000002C139.01959000000002,195.87441,138.36694000000003,197.68735,137.71327000000002,199.49932C136.91655000000003,200.80568000000002,136.11885,202.11099000000002,135.32015,203.41533C134.30586000000002,204.57666,133.29062000000002,205.73694,132.27436,206.89624C130.96999,207.47740000000002,129.66468,208.05754000000002,128.35834,208.63669000000002C126.69136999999999,210.37818000000001,125.02347,212.11859,123.35454,213.85805000000002C122.99294,215.30945000000003,122.63035,216.7598,122.26676,218.20918000000003C122.70288000000001,220.38578000000004,123.28302000000001,222.70634000000004,123.78965000000001,224.95343000000003C124.37081,226.33231000000004,124.95095,227.71014000000002,125.5301,229.08700000000002C124.95094,230.10329000000002,124.3708,231.11853000000002,123.78965000000001,232.13279000000003C122.70285000000001,233.65672000000004,121.61509000000001,235.17958000000002,120.5263,236.70148000000003C120.38226,238.37045000000003,120.23723000000001,240.03835000000004,120.09119000000001,241.70528000000004C120.74487,243.08416000000005,121.39753000000002,244.46199000000004,122.04920000000001,245.83885000000004C122.41280000000002,247.58034000000004,122.77539000000002,249.46579000000003,123.13698000000001,251.27777000000003C123.28302000000001,252.94673000000003,123.42806,254.61463000000003,123.5721,256.28156C122.84789,258.67573,122.12272,261.06881,121.39653000000001,263.46093C120.67233000000002,264.91234000000003,119.94715000000001,266.36268,119.22097000000001,267.81206000000003C119.0044,269.48103000000003,118.78685000000002,271.14893,118.56830000000001,272.81586000000004C119.07694000000001,274.33979000000005,119.58456000000001,276.15273,120.09119000000001,277.81966000000006C120.67235000000001,278.98098000000005,121.25249000000001,280.14126000000005,121.83164000000001,281.3005600000001C121.83264000000001,282.9695300000001,121.83264000000001,284.63743000000005,121.83164000000001,286.3043600000001C121.25248,287.8282900000001,120.67234,289.3511500000001,120.09119000000001,290.8730500000001C119.6303,292.3220900000001,119.16843000000001,293.7700700000001,118.70555000000002,295.21708000000007').hide();

var circle = paper.circle(150, 40, 10);


  var animatePath = function(path, duration, attributes) {
    //root.glow({color: "#04d413",opacity: 1, width: 5});
    var circle = paper.circle(50, 40, 10);

    if (!duration) duration = 1500;
    if (!attributes) attributes = {};

    var len = root.getTotalLength();
    var previous;
    root.hide();
    $j(root.node).animate({
      'to': 1
    }, {
      'duration': duration,
      'step': function(pos, fx) {
        var offset = len * fx.pos;
        var subpath = root.getSubpath(0, offset);
        if (previous) previous.remove();
        previous = root.paper.path(subpath).attr(attributes);
        console.log();
      },
      'complete': function() {
        //previous.remove();
        //root.show();
      }
    });
  };
animatePath(root, 2000, {"stroke": "green", "stroke-dasharray": "- "});

});
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 11px;
}

.wrapper {
margin: 0 auto;
width: 1024px;
position: relative;
}

path {
    /*mix-blend-mode: multiply;*/
    /*mix-blend-mode: multiply;*/
}

path:hover{
    /*mix-blend-mode: multiply;*/
}

#map {
float: left;
clear: both;
width: 1024px;
height: 768px;
}

.point img {
vertical-align: middle;
margin-right: 10px;
}

a img {
border: none;
}

.point{
position: absolute;
background: #fff;
width: 300px;
height: 600px;
top: 10%;
left: 85%;
/*transform: translate(-50%, -50%);*/
border-radius: 5px;
border: 1px solid #ccc;
padding: 10px;
box-shadow: 0 12px 20px -10px;
text-align: center;
display: none;
}

.point .close {
display: block;
position: absolute;
top: -10px;
right: -10px;
width: 24px;
height: 24px;
text-indent: -9999px;
outline: none;
background: url(../img/close.png) no-repeat;
}
<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Raphael Map</title>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type='text/javascript'>
    var $j = jQuery.noConflict();
</script> 

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script>
<script data-semver="2.0.3" data-require="jquery@2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script type='text/javascript'>
    var $i = jQuery.noConflict();
</script> 

<script data-semver="2.1.0" data-require="raphael@2.1.0" src="https://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
<script src="http://chrismichaelscott.github.io/fraphael/downloads/fraphael.js"></script>
<script src="https://ariutta.github.io/svg-pan-zoom/dist/svg-pan-zoom.js"></script>


</head>

<body>
 
    <div class="wrapper">
        <div id="map">
        </div>
    </div>

    <div id="myDIV">
    1
    </div>
        
    <script>
      // Don't use window.onLoad like this in production, because it can only listen to one function.
      window.onload = function() {
        // Expose to window namespase for testing purposes
        window.zoomTiger = svgPanZoom('#mySvgElement', {
          zoomEnabled: true,
          controlIconsEnabled: true,
          fit: true,
          center: true,
          // viewportSelector: document.getElementById('demo-tiger').querySelector('#g4') // this option will make library to misbehave. Viewport should have no transform attribute
        });

        /*document.getElementById('enable').addEventListener('click', function() {
          window.zoomTiger.enableControlIcons();
        })
        document.getElementById('disable').addEventListener('click', function() {
          window.zoomTiger.disableControlIcons();
        })*/
      };
 </script>

</body>
</html>

How to add the new object to place it at the correct pan-zoom coordinates?


Solution

  • The main problem, is that you are re-inserting the path during each animation as it changes. This adds the path into the svg not under control by pan-zoom.

    You create one path, then use another to reinsert as well. That doesn't break it, but is unnecessary. Raphael has the tools to do it without needing that.

    You can simply change the attribute 'path' with the new subPath string. And Raphael has it's own getSubpath() and getTotalLength() methods, without needing an element.

    So the key changes are...

    Set up the path string, as an actual string, not an element.

    var pathString = 'M124.00721,89.633281C12...very long string';
    
    // Get the length of the path
    var len = Raphael.getTotalLength(pathString);
    
    // create a basic empty path, we will use to amend.
    var path = paper.path("M0,0").attr(attributes)
    
    // inside animation, get our new subpath...
    var subpath = Raphael.getSubpath(pathString, 0, offset);
    
    // now, simply change it's attribute, no need to delete/readd
    path.attr('path', subpath).attr(attributes);
    

    jsfiddle

    So that's it, no needed to mess about with 2 paths, and constantly deleting/readding. Just use one path, and one pathstring, and amend the path attribute. That should be better performance wise as well.