如何使用D3用矩形遮罩SVG图像?

时间:2020-09-08 17:15:51

标签: javascript svg d3.js

我正在尝试使用灰色背景矩形遮盖svg图像,以便可以使用d3.js v5部分显示其他颜色。

SVG

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 53.545 53.545" style="enable-background:new 0 0 53.545 53.545;" xml:space="preserve">
<g>
    <g>
        <circle cx="26.686" cy="4.507" r="4.507"/>
        <path d="M28.256,11.163c-1.123-0.228-2.344-0.218-3.447,0.042c-7.493,0.878-9.926,9.551-9.239,16.164
            c0.298,2.859,4.805,2.889,4.504,0c-0.25-2.41-0.143-6.047,1.138-8.632c0,3.142,0,6.284,0,9.425c0,0.111,0.011,0.215,0.016,0.322
            c-0.003,0.051-0.015,0.094-0.015,0.146c0,7.479-0.013,14.955-0.322,22.428c-0.137,3.322,5.014,3.309,5.15,0
            c0.242-5.857,0.303-11.717,0.317-17.578c0.244,0.016,0.488,0.016,0.732,0.002c0.015,5.861,0.074,11.721,0.314,17.576
            c0.137,3.309,5.288,3.322,5.15,0c-0.309-7.473-0.32-14.949-0.32-22.428c0-0.232-0.031-0.443-0.078-0.646
            c-0.007-3.247-0.131-6.497-0.093-9.742c1.534,2.597,1.674,6.558,1.408,9.125c-0.302,2.887,4.206,2.858,4.504,0
            C38.678,20.617,36.128,11.719,28.256,11.163z"/>
    </g>
</g>
</svg>

d3.js

private createSVG(rect): void {

    this.svg = d3.select(rect)
      .append('svg')
      .attr('class', 'psych-chart')
      .attr('width', this.width/2)
      .attr('height', this.height / 2)
      .attr("viewBox", '0 0 65 60')

  }

  private createChart() {

    let that = this;

    const rect = this.svgContainer.nativeElement;
    this.createSVG(rect);

    mask();

    d3.xml("../assets/images/person.svg")
      .then(xml => {

        var personFigure = xml.getElementsByTagName('g')[1];

        that.svg.node().append(personFigure);

        that.person = that.svg.select('g')
          .attr('transform', `translate(${that.margin.left}, ${that.margin.top})`)
          .attr('class', 'person-svg')


        that.person.select('path')
          .style('fill-opacity', 1)
          .style('fill', '#e7e7e7')
          .style('stroke-width', 0.3)
          .style('stroke', '#e7e7e7')
          .attr('mask', 'url(#person-mask)')

        that.person.select('circle')
          .style('fill', '#e7e7e7')
          .style('stroke-width', 0.3)
          .style('stroke', '#e7e7e7')
          .attr('mask', 'url(#person-mask)');
          
       

        styleImportedSVG();  

      });
    
   

    function mask() {
      const mask = that.svg
        .append('defs')
        .append('mask')
        .attr('id', 'person-mask')
        // add image in the clip-path
        
      // add background which is clipped
      mask.append('rect')
        .style('fill', '#01579b')
        .attr('width', 65)
        .transition()
        .duration(5000)
        .attr('height', 60)
        
        
    }


    function styleImportedSVG() {

      console.log('count', that.psychSafeMembersPercent);

      //that.svg.on('mouseover', function () {
      //  d3.selectAll('path')
      //    .attr('fill-opacity', 0.1)
      //    .attr('stroke-opacity', 0.3)
      //})

    }

   
  }

我不知道为什么在我的情况下屏蔽不起作用。我想要的是用遮罩SVG填充rect图像,以便仅根据我提供的值(例如10%,20%等)部分填充图像。如何实现此目的?

jsfiddle

1 个答案:

答案 0 :(得分:0)

我知道了。这是我做到的方式,但是我敢肯定还有更好的方法。任何帮助和修改将不胜感激。

this.maskHeight = (parseFloat(percentage) / 100 * parseFloat(this.mask.attr('height')));

    


    // add background which is clipped
    this.mask.append('rect')
      .attr('fill', '#fff')
      .attr('width', 65)
      .transition()
      .ease(d3.easeBounce)
      .duration(2000)
      .attr('height', this.maskHeight)


   
    d3.xml("../assets/images/person.svg")
      .then(xml => {

        var personFigure = xml.getElementsByTagName('g')[1];

        // adds person image to svg 
        that.svg.node().append(personFigure);

        // styling
        // person svg for the background
        that.svg.select('g')
          .attr('transform', `translate(${that.margin.left}, ${that.margin.top})`)
          .attr('class', 'person-svg-bg')

        var clone = that.svg
          .select('g').node()
          .cloneNode(true);

        that.svg.node().append(clone)

        var circle = that.svg.selectAll('circle')
          .attr('id', function (d, i) { return 'person-head-' + i })
          .style('fill', function (d, i) { if (i === 0) { return '#FFCC00' } else { return 'none' } })
          .style('stroke', function (d, i) { if (i === 0) { return null } else { return '#E7E7E7' } })
          .style('stroke-width', function (d, i) { if (i === 0) { return null } else { return 0.6 } })
          .attr('mask', function (d, i) { if (i === 0) { return 'url(#person-mask)' } else { return null } })

        var path = that.svg.selectAll('path')
          .attr('id', function (d, i) { return 'person-path-' + i })
          .style('fill', function (d, i) { if (i === 0) { return '#FFCC00' } else { return 'none' } })
          .style('stroke', function (d, i) { if (i === 0) { return null } else { return '#E7E7E7' } })
          .style('stroke-width', function (d, i) { if (i === 0) { return null } else { return 0.6 } })
          .attr('mask', function (d, i) { if (i === 0) { return 'url(#person-mask)' } else { return null } })

      });