2016-09-24 98 views
0

桌面的問題 - 大約501-1200px enter image description here縮放,掩蔽,不透明度在d3.js

手機 - 約350-500px

enter image description here


enter image description here

我已經建立,有一個圓形切割出它的面具,它的增長,縮小和有一個標籤。但我有好一會才正確尺度問題。

我曾嘗試縮放功能與視框 - 但它不工作,並調整大小導致不透明蒙的錯誤,我已經無法修復。

Using ViewBox to resize svg depending on the window size

//最新JS小提琴 http://jsfiddle.net/NYEaX/1563/

$(document).ready(function() { 


    function maskMaker(el) { 

    var backcolor = $(el).data("color"); 
    var backopacity = $(el).data("opacity"); 

    var height = $(el).data("height"); 
    var width = $(el).data("width"); 

    var width = 1120; 
    var height = 500; 

    var labelName = $(el).data("label-name"); 
    var bubbleValue = $(el).data("bubble-value"); 
    var displaceLeft = $(el).data("displace-left"); 
    var displaceTop = $(el).data("displace-top"); 

    var data = [{ 
     "label": labelName, 
     "x": displaceLeft, 
     "y": displaceTop, 
     "value": bubbleValue 
    }]; 

    console.log("MASK data", data); 


    // Set the main elements for the series chart 
    var svgroot = d3.select($(el)[0]) 
     .append("svg") 
     .attr("viewBox", "0 0 " + width + " " + height) 
     /* 
        .attr("width", "100%") 
        .attr("height", "100%")*/ 
     .attr("width", width) 
     .attr("height", height) 
     .attr("preserveAspectRatio", "xMidYMid meet"); 

    // filters go in defs element 
    var defs = svgroot.append("defs"); 

    var mask = defs.append("mask") 
     .attr("id", "myMask"); 

    mask.append("rect") 
     .attr("x", 0) 
     .attr("y", 0) 
     .attr("width", "100%") 
     .attr("height", "100%") 
     .style("fill", "white") 
     .style("opacity", backopacity); 


    var invisiblebubble = mask.append("circle") 
     .data(data); 


    //create a fixed bubble first     
    invisiblebubble 
     .attr("cx", "50%") 
     .attr("cy", "50%") 
     .attr("r", function(d) { 
     return d.value - 20; 
     }); 


    //now mask the fixed circle  
    var masker = defs.append(function() { 
     return mask.node().cloneNode(true) 
     }) 
     .attr("id", "myMaskForPointer") 
     .select("rect") 
     .style("opacity", 0.8); 

    invisiblebubble 
     .attr("r", 10); 

    //animate this circle 
    invisiblebubble 
     .attr("cx", "50%") 
     .attr("cy", "50%") 
     .transition() 
     .duration(1800) 
     .attr("r", 10) 
     .transition() 
     .duration(900) 
     .attr("r", function(d) { 
     return d.value; 
     }); 


    //apply the rest of the chart elements 
    var svg = svgroot 
     .attr("class", "series") 
     .append("g") 
     .attr("transform", "translate(0,0)") 


    var rect = svg 
     .append("rect") 
     .attr("x", 0) 
     .attr("y", 0) 
     .attr("width", "100%") 
     .attr("height", "100%") 
     .attr("mask", "url(#myMask)") 
     .style("fill", backcolor); 


    /* 
         //__labels 
         var centrallabel = svgroot.append("g") 
         .attr("class", "centrallabel") 
         .data(data); 

        centrallabel  
         .append("text") 
         .attr("text-anchor", "middle") 
         .attr("x", 550) 
         .attr("y", 250 + 10) 
         .text(function(d) { 
          return "200"; 
         }) 
         */ 


    function addLabel() { 

     //__labels 
     var labels = svgroot.append("g") 
     .attr("class", "labels") 

     //__ enter 
     var labels = labels.selectAll("text") 
     .data(data); 

     labels.enter() 
     .append("text") 
     .attr("text-anchor", "middle") 

     //__ update 
     //labels 

     .attr("x", function(d) { 
      return d.x; 
     }) 
     .attr("y", function(d) { 
      return d.y - 10; 
     }) 
     .text(function(d) { 
      return d.label; 
     }) 
     .each(function(d) { 
      var bbox = this.getBBox(); 
      d.sx = d.x - bbox.width/2 - 2; 
      d.ox = d.x + bbox.width/2 + 2; 
      d.sy = d.oy = d.y + 5; 
      d.cx = 550; 
      d.cy = 250; 
     }) 
     .transition() 
     .duration(300) 

     labels 
     .transition() 
     .duration(300) 

     //__ exit 
     labels.exit().remove(); 
     //__labels      
    } 


    function addPointer() { 
     //__pointers 
     var pointers = svgroot.append("g") 
     .attr("class", "pointers"); 


     var dots = defs.append("marker") 
     .attr("id", "circ") 
     .attr("markerWidth", 6) 
     .attr("markerHeight", 6) 
     .attr("refX", 3) 
     .attr("refY", 3); 


     var pointers = pointers.selectAll("path.pointer") 
     .data(data); 

     //__ enter 
     pointers.enter() 
     .append("path") 
     .attr("class", "pointer") 
     .style("fill", "none") 
     .attr("marker-end", "url(#circ)") 
     .attr("mask", "url(#myMaskForPointer)") 

     //__ update 
     //pointers 
     .attr("d", function(d) { 
      if (d.cx > d.ox) { 
      return "M" + d.sx + "," + d.sy + "L" + d.ox + "," + d.oy + " " + d.cx + "," + d.cy; 
      } else { 
      return "M" + d.ox + "," + d.oy + "L" + d.sx + "," + d.sy + " " + d.cx + "," + d.cy; 
      } 
     }) 
     .transition() 
     .duration(300) 

     pointers 
     .transition() 
     .duration(300) 

     //__ exit 
     pointers.exit().remove(); 
     //__pointers 
    } 

    //delay for the mask 
    setTimeout(function() { 
     addLabel(); 
     addPointer(); 
    }, 1000); 

    } 


function resizeHandling(el){ 

    function maskResizer(width, height) { 
    $(el).find('.series').attr("width", width); 
    $(el).find('.series').attr("height", height); 
    $(el).find('.series').attr("viewBox", "0 0 " + width + " " + height); 
    } 


    $(window).resize(function() { 
    var paneWidth = $(el).width(); 
    var paneHeight = $(el).height(); 
    console.log("paneHeight", paneHeight); 
    console.log("paneWidth", paneWidth); 
    maskResizer(paneWidth, paneHeight); 
    }); 
} 
    //var el = $(".mask"); //selector 

    $('[data-role="maskmaker"]').each(function(index) { 
    console.log("test") 
    maskMaker(this); 
    resizeHandling(this); 
    }); 


}); 

回答

0

我想出了在縮放和當調整大小時,重繪元素此解決方案。

 function maskMaker(el){ 

     var backcolor = $(el).data("color"); 
     var backopacity = $(el).data("opacity"); 

     //var height = $(el).data("height"); 
     //var width = $(el).data("width"); 

     var width = $(el).parent().width(); 
     var height = $(el).parent().height(); 

     var labelName = $(el).data("label-name"); 
     var bubbleValue = $(el).data("bubble-value"); 
     var displaceLeft = $(el).data("displace-left"); 
     var displaceTop = $(el).data("displace-top"); 

     var centralLabel = $(el).data("central-label"); 

     var data = [{ 
      "label": labelName, 
      "centralLabel" : centralLabel, 
      "xPer": displaceLeft, 
      "yPer": displaceTop, 
      "value": bubbleValue 
     }]; 

     console.log("MASK data", data); 

     //width="100%" height="100%" viewBox="0 0 1120 500" preserveAspectRatio="none" 

     // Set the main elements for the series chart 
     var svgroot = d3.select($(el)[0]) 
      .append("svg") 
      .attr("viewBox", "0 0 "+width+" "+height) 
      .attr("width", "100%") 
      .attr("height", "100%") 
      .attr("preserveAspectRatio", "none"); 

     // filters go in defs element 
     var defs = svgroot.append("defs"); 

     var mask = defs.append("mask") 
        .attr("id", "myMask"); 

     mask.append("rect") 
      .attr("x", 0) 
      .attr("y", 0) 
      .attr("width", "100%") 
      .attr("height", "100%") 
      .style("fill", "white") 
      .style("opacity", 1); 


     var invisiblebubble = mask.append("circle") 
      .data(data); 


     //create a fixed bubble first     
      invisiblebubble 
      .attr("cx", "50%") 
      .attr("cy", "50%") 
      .attr("r", function(d) { 
       return d.value-20; 
      });    


     //now mask the fixed circle  
      var masker = defs.append(function() { 
      return mask.node().cloneNode(true) 
      }) 
      .attr("id", "myMaskForPointer") 
      .select("rect") 
      .style("fill", "white") 
      .style("opacity", 1); 

      invisiblebubble 
      .attr("r", 10); 


     //apply the rest of the chart elements 
      var svg = svgroot 
      .attr("class", "series") 
      .append("g") 
      .attr("transform", "translate(0,0)") 


      var rect = svg 
      .append("rect") 
      .attr("x", 0) 
      .attr("y", 0) 
      .attr("width", "100%") 
      .attr("height", "100%") 
      .attr("mask", "url(#myMask)") 
      .style("fill", backcolor) 
      .style("opacity", backopacity); 


     //animate this circle 

      invisiblebubble 
      .attr("cx", "50%") 
      .attr("cy", "50%") 
      .transition() 
      .duration(1800) 
      .attr("r", 10) 
      .transition() 
      .duration(900) 
      .attr("r", function(d) { 
       return d.value; 
      }); 



      if(centralLabel){ 
       //__labels 
       var centrallabel = svgroot.append("g") 
       .attr("class", "centrallabel") 
       .data(data); 

       centrallabel  
         .append("text") 
         .attr("text-anchor", "middle") 
         .attr("x", "50%") 
         .attr("y", "51%") 
         .text(function(d) { 
         return d.centralLabel; 
         });      
      } 



      var dots = defs.append("marker") 
        .attr("id", "circ") 
        .attr("markerWidth", 6) 
        .attr("markerHeight", 6) 
        .attr("refX", 3) 
        .attr("refY", 3); 


      function addLabel(){ 


       var width = $(el).parent().width(); 
       var height = $(el).parent().height(); 

       //__labels 
       var labels = svgroot.append("g") 
       .attr("class", "labels") 

       //__ enter 
       var labels = labels.selectAll("text") 
       .data(data); 

       labels.enter() 
       .append("text") 
       .attr("text-anchor", "middle") 

       //__ update 
       //labels 

       .attr("x", function(d) { 
        console.log("d.x", d.xPer); 
        return d.xPer +"%"; 
       }) 
       .attr("y", function(d) { 
        return d.yPer +"%"; 
       }) 
       .text(function(d) { 
        return d.label; 
       }) 
       .each(function(d) { 
        var bbox = this.getBBox(); 
        d.sx = (d.xPer/100 * width) - bbox.width/2 - 2; 
        d.ox = (d.xPer/100 * width) + bbox.width/2 + 2; 
        d.sy = d.oy = (d.yPer/100 * height) + 5; 
        d.cx = 550; 
        d.cy = 250; 
       }) 
       .transition() 
       .duration(300) 

       labels 
       .transition() 
       .duration(300) 

       //__ exit 
       labels.exit().remove(); 
       //__labels      
      } 

      function addPointer(){ 


       //__pointers 
       var pointers = svgroot.append("g") 
       .attr("class", "pointers"); 


       var pointers = pointers.selectAll("path.pointer") 
       .data(data); 

       //__ enter 
       pointers.enter() 
       .append("path") 
       .attr("class", "pointer") 
       .style("fill", "none") 
       .attr("marker-end", "url(#circ)") 
       .attr("mask", "url(#myMaskForPointer)") 

       //__ update 
       //pointers 
       .attr("d", function(d) { 
        if (d.cx > d.ox) { 
        return "M" + d.sx + "," + d.sy + "L" + d.ox + "," + d.oy + " " + d.cx + "," + d.cy; 
        } else { 
        return "M" + d.ox + "," + d.oy + "L" + d.sx + "," + d.sy + " " + d.cx + "," + d.cy; 
        } 
       }) 
       .transition() 
       .duration(300) 

       pointers 
       .transition() 
       .duration(300) 

       //__ exit 
       pointers.exit().remove(); 
       //__pointers 
      } 

      //delay for the mask 
      setTimeout(function(){ 
       addLabel(); 
       addPointer(); 
       resetMask(); 
      }, 1000); 



      //throttle 
      var rtime; 
      var timeout = false; 
      var delta = 200; 
      $(window).resize(function() { 
       rtime = new Date(); 
       if (timeout === false) { 
        timeout = true; 
        setTimeout(resizeend, delta); 
       } 
      }); 

      function resizeend() { 
       if (new Date() - rtime < delta) { 
        setTimeout(resizeend, delta); 
       } else { 
        timeout = false; 
        //alert('Done resizing'); 
        resetMask(); 
       }    
      } 
      //throttle 


      function resetMask(){ 
       console.log("redraw"); 

       var width = $(el).parent().width(); 
       var height = $(el).parent().height(); 

       svgroot 
        .attr("viewBox", "0 0 "+width+" "+height); 


        var ratio = 1; 

        if(width <= 501){ 
         ratio = 0.5; 
        } 

        invisiblebubble 
          .attr("cx", "50%") 
          .attr("cy", "50%") 
          .transition() 
          .duration(400) 
          .attr("r", function(d) { 
          return d.value * ratio; 
          }); 

       svgroot.selectAll("g.labels").remove(); 
       svgroot.selectAll("g.pointers").remove(); 

        addLabel(); 
        addPointer(); 

      } 

     } 

     maskMaker($this);