在d3.js中缩放和平移2个相应的图像相同的数量?

时间:2018-01-31 13:50:14

标签: javascript d3.js svg append zoom

我有一个与GeoJSON并排的SVG图像。两个图像中都有相应的对象。我使用d3添加了它们。我目前能够分别放大和平移它们。我还可以在缩放或平移两个图像中的任何一个时获得比例和x,y。现在我想同步两个图像的缩放/平移,这样如果在一个图像上完成缩放/平移,则在另一个图像上完成相同数量的缩放/平移。如果我调用zoom.translateByzoom.scaleBy函数但我不知道如何应用它,我想这可以完成。这是代码:

<!doctype html>
<html lang="en">    
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

    <title>Sketch-To-Metric Map Alignment by Qualitative Spatial Constraint Matching</title>

    <!-- the data of the map -->
    <script src="img/sketchmap_ids.json"></script>

    <!--Add support for earlier versions of Internet Explorer -->
    <!--[if lt IE 9]>
    <script src="lib/js/html5shiv.js"></script>
    <![endif]-->

    <filter id="offset" x="-20%" y="-10%" height="130%">
     <feGaussianBlur  in="SourceAlpha" stdDeviation="5"/>
      <feOffset dx="5" dy="5" result="B"/>
     <feMerge>
      <feMergeNode in="B"/>
      <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>

    <filter id="dropshadow_2" height="130%">
      <feGaussianBlur in="SourceAlpha" stdDeviation="3"/> <!-- stdDeviation is how much to blur -->
      <feOffset dx="2" dy="2" result="offsetblur"/> <!-- how much to offset -->
      <feMerge> 
        <feMergeNode/> <!-- this contains the offset blurred image -->
        <feMergeNode in="SourceGraphic"/> <!-- this contains the element that the filter is applied to -->
      </feMerge>
    </filter>
    <!-- circle r="10" style="filter:url(#dropshadow)"/ -->

    <filter id="dropshadow" height="130%">
      <feGaussianBlur in="SourceAlpha" stdDeviation="3"/> 
      <feOffset dx="2" dy="2" result="offsetblur"/>
      <feComponentTransfer>
        <feFuncA type="linear" slope="0.2"/>
      </feComponentTransfer>
      <feMerge> 
        <feMergeNode/>
        <feMergeNode in="SourceGraphic"/> 
      </feMerge>
    </filter>

    <style>
        .shadow {
            -webkit-filter: drop-shadow( 5px 5px 5px 10px);
                    filter: drop-shadow( 5px 5px 2px); /* Same syntax as box-shadow */

        }
        .reveal section img { background:none; border:none; box-shadow:none; }
        .service {
            stroke-width: 4;
            stroke: #999999;
            fill: none;
        }
        .residential-line {
            stroke-width: 8;
            stroke: #b3b3b3;
            fill: none;
        }
        .fence,.footway,.cycleway,.track,.path,.pedestrian,.steps {
            stroke-width: 2;
            stroke: #2b1100;
            stroke-dasharray: 3,2,3;
            fill: none;
        }
        .primary {
            stroke-width: 18;
            stroke: #b3b3b3;
            fill: none;
        }
        .tertiary {
            stroke-width: 12;
            stroke: #b3b3b3;
            fill: none;
        }
        .bridge {
            stroke-width: 12;
            stroke: #cd853f;
            fill: none;
        }
        .graveyard {
            stroke-width: 2;
            stroke: #444444;
            stroke-dasharray: 3,2,3;
            fill: #668000;
        }
        .waterway-line,.river-line,.weir {
            stroke-width: 5;
            stroke: #2A7FFF;
            fill: none;
        }
        .water {
            stroke-width: 1;
            stroke: #0066FF;
            fill: #2A7FFF;;
        }
        .scrub,.forest {
            stroke-width: 1;
            stroke: #008033;
            fill: #008033;
        }
        .grass,.village_green,.greenhouse {
            stroke-width: 1;
            stroke: #5FD35F;
            fill: #5FD35F;
        }
        .residential,.commercial {
            stroke-width: 1;
            stroke: #FFF6D5;
            fill: #FFF6D5;
        }
        .parking,.bicycle_parking {
            stroke-width: 1;
            stroke: #FFE680;
            fill: #FFE680;
        }
        .university,.civic,.yes,.house,.school {
            stroke-width: 0;
            fill: #916F6F;
        }
        .map-panel {
            width: 100%;   
            border: 1px solid #444444;
        }
        #sketch3,#sketch4,#sketch5,#sketch6,#sketch10,#sketchgraph11,#sketchgraph12 {
            width: 45%;
            float: left;
            padding-bottom:0px;
        }

        #metric3,#metric4,#metric5,#metric6,#metric10,#metricgraph11,#metricgraph12 {
            width: 45%;
            float: right;
            padding-bottom:0px;
        }

        .text-pane-left {
            width: 45%;
            float: right;
            padding-bottom:0px;
        }

        .text-pane-right {
            width: 45%;
            float: right;
            padding-bottom:0px;
        }

        #mynetwork {
            width: 854px;    
            height: 480px; 
            position: relative; 
            border: 1px solid #444444;
            background-color: #dddddd;
        }

        #othernetwork {
            width: 800px;    
            height: 600px; 
            position: relative; 
            border: 1px solid #444444;
            background-color: #dddddd;
        }

        #visualization {
            width: 800px;    
            height: 600px; 
            position: relative; 
            border: 1px solid #444444;
            background-color: #dddddd;
        }

        body {
            color: #d3d3d3;
            font: 12pt arial;
            background-color: #ffffff;
        }
    </style>  
</head>

<body>

    <div class="map-panel" id="panel">
        <div class="map-pane-left" id="sketch4"></div>
        <div class="map-pane-right" id="metric4"></div>
    </div>                                                  

    <script src="d3/d3.min.js"></script>
    <script src="d3/topojson.min.js"></script>
    <script src="https://d3js.org/d3.v4.min.js"></script>





    <script>
        //https://datascience.blog.wzb.eu/2016/08/29/bringing-svg-to-life-with-d3-js/


        //load sketch map

        d3.xml("img/sketch_all_in_components_web.svg").mimeType("image/svg+xml").get(function(error, xml)           {
            if (error) throw error;

            function sketchMapZoomed() {
                    svg.selectAll("*").attr("transform", "translate(" + d3.event.translate + ")" + "                        scale(" + d3.event.scale + ")")
                    var currentScale = d3.event.scale;
                    var currentTranslate = d3.event.translate;
                    console.log(currentScale, currentTranslate);

            }

      //var copy = xml.documentElement.cloneNode(true);
            document.getElementById('sketch4').appendChild(xml.documentElement);
            d3.select('#sketch4').selectAll('g,                                                                     path').on('mouseenter',animateMapTargets).on('mouseleave',removeFilter);      
            var svg = d3.select("svg")
            .call(d3.behavior.zoom().on("zoom", sketchMapZoomed ))
        });



        //load metric map




        var width = document.getElementById("sketch4").clientWidth;
        height = (width * 0.71053942806206943134954217685331);

        function metricMapZoomed () {
            svg.attr("transform", d3.event.transform)
            var transformMetric = d3.zoomTransform(this)
            console.log(transformMetric);
            //.call(d3.zoom.translateBy("sketch#4", transformMetric.x, transformMetric.y)) 
            //var t = d3.select("#sketch4").attr("transform", "translate(" + transformMetric.x + "," + transformMetric.y + ") scale(" + transformMetric.k + ")");       
      }

        var svg = d3.select("#metric4").append("svg")
            .attr("width", width)
            .attr("height", height)
            .attr("id", "metricmap")
            .call(d3.zoom().on("zoom", metricMapZoomed ))
            .append("g");

        //create a place holder rectangle to keep floats inline
        var svgContainer = d3.select("body").append("svg")
            .attr("width", width)
            .attr("height", width)
            .attr("id", "placeholder");

        d3.json("img/defense_data.json", function(error, map) {
            if (error) return console.error(error);

            var projection = d3.geo.mercator()
                .center([7.612337603149424, 51.96211781909236])
                .scale(3000000);
                //.translate(0,0);

            var path = d3.geo.path()
                .projection(projection);

            svg.selectAll(".city_block_landmarks")
                .data(topojson.feature(map, map.objects.city_block_landmarks).features)
                .enter().append("path")
                .attr("class", function(d){
                    //console.log(d.properties.class)
                    return d.properties.classfeature;
                })
                .attr("id", function(d){
                    //console.log(d.id)
                    return d.id;
                })
                .attr("d", path);

            svg.selectAll(".hidden_landmarks")
                .data(topojson.feature(map, map.objects.hidden_landmarks).features)
                .enter().append("path")
                .attr("class", function(d){
                    //console.log(d.properties.class)
                    return d.properties.classfeature;
                })
                .attr("id", function(d){
                    //console.log(d.id)
                    return d.id;
                })
                .attr("d", path);

            svg.selectAll(".botanica_mid_polygons")
                .data(topojson.feature(map, map.objects.botanica_mid_polygons).features)
                .enter().append("path")
                .attr("class", function(d){
                    //console.log(d.properties.class)
                    return d.properties.classfeature;
                })
                .attr("id", function(d){
                    //console.log(d.id)
                    return d.id;
                })
                .attr("d", path);

            svg.selectAll(".streets_linear_features")
                .data(topojson.feature(map, map.objects.streets_linear_features).features)
                .enter().append("path")
                .attr("class", function(d){
                    //console.log(d.properties.class)
                    return d.properties.classfeature;
                })
                .attr("id", function(d){
                    //console.log(d.id)
                    return d.id;
                })
                .attr("d", path);   
        });

        //animate objects on mouse on and remove animation on mouse off
        function animateMapTargets() {          
            if (this.id)
                if (targets[this.id])
                    targets[this.id].forEach(animateTargetNode);
        };

        function animateTargetNode(obj, i) {
            //console.log(d3.select('#'+obj)./*node().*/style('filter','url(#offset)'));
            //d3.select('#'+obj).style('filter','url(#offset)');
            //console.log(d3.select('#'+obj).classed("shadow", true));//
            d3.select('#'+obj).classed("shadow", true);
                //.attr()  style="filter:url(#dropshadow)"
                //.attr();
        }

        function removeFilter() {           
            if (this.id)
                if (targets[this.id])
                    targets[this.id].forEach(function animateTargetNode(obj, i) {
                        //d3.select('#'+obj).style('filter','none');
                        d3.select('#'+obj).classed("shadow", false);
                    });
        };




    </script>   
</body>
</html>

1 个答案:

答案 0 :(得分:0)

  

我想如果我拨打zoom.translateByzoom.scaleBy

,就可以完成

这两个都是相对的,即它们被添加到当前变换/乘以当前变换,它们不设置它。因此,如果当前比例为0.5并且您使用值为1.0的scaleBy,则仍然会得到0.5的比例(因为0.5 * 1.0 == 0.5)。

要在两个缩放之间“同步”绝对值,您将分别使用zoom.translateTozoom.scaleTo

更直接的方法是设置整个变换,而不是设置缩放变换的各个组件。为此,您将在源节点上使用zoomTransform(或使用缩放事件的event.transform)来获取当前变换,然后使用zoom.transform在目标上设置该变换。