【问题标题】:Scaling, masking, opacity issues in d3.jsd3.js 中的缩放、遮罩、不透明度问题
【发布时间】:2017-02-02 05:41:54
【问题描述】:

桌面 - 大约 501-1200 像素

移动 - 大约 350-500 像素


我已经制作了一个从中切出一个圆圈的面具,它会变大、变小并带有标签。但是我在尝试使其正确扩展时遇到了问题。

我尝试使用视图框重新缩放功能 - 但它不起作用,并且调整大小会导致我无法修复的不透明蒙版错误。

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);
  });


});

【问题讨论】:

    标签: javascript d3.js svg resize scaling


    【解决方案1】:

    当发生调整大小时,我想出了这个关于缩放和重绘元素的解决方案。

          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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-14
      • 1970-01-01
      • 1970-01-01
      • 2013-03-23
      • 1970-01-01
      • 1970-01-01
      • 2020-04-27
      • 2017-07-01
      相关资源
      最近更新 更多