在d3 / svg中将元素置于最前面

时间:2018-12-06 02:58:39

标签: javascript jquery d3.js svg

我在http://cii.wwu.edu/shull/algaeBloom/experiment.html有一个装有d3的动画水箱

在更改两个水层之间的颜色fillColor和backFill颜色时,我使文本显示在顶部水层的后面。如何防止覆盖文字被覆盖?

enter image description here

  }

    // create box
    drawSvgContainer() {
      this.width = this.container.outerWidth();
      this.height = this.container.outerHeight();
      let viewBoxDef = `0, 0, ${this.width}, ${this.height}`;

      this.svgContainer = d3.select(this.container[0])
      .attr('id', 'svg-container')
      .append("svg")
      .attr("width", "100%")
      .attr("height", "100%")
      .attr("viewBox", viewBoxDef);

      this.bodyGroup = this.svgContainer.append('g')
      .attr('id', 'body-group')
      .attr('transform', `translate(${this.width/2}, ${this.height/2})`);
    }


    initTower () {
      let uniqId = this.uniqId();
      // this.tankGroup = this.bodyGroup.append('g').attr('id', 'tank-group');
      this.waveClip = this.bodyGroup.append('defs').append('clipPath').attr('id', uniqId);
      this.waveHorizontal = this.waveClip.append('path');

      this.backFill = this.bodyGroup.append('rect').attr('id', 'back-fill');
      this.skyFill = this.bodyGroup.append('rect').attr('id', 'sky-fill');
      this.border = this.bodyGroup.append('rect').attr('id', 'border');
      this.behindText = this.bodyGroup.append('text').attr('id', 'behind-text');
      this.behindArrow = this.bodyGroup.append('text').attr('id', 'behind-arrow');

      if (this.lightValueEnabled) {
        this.lightValueBehindText = this.bodyGroup.append('text').attr('id', 'light-behind-text');
      }

      if (this.respirationEnabled) {
        this.respirationBehindText = this.bodyGroup.append('text').attr('id', 'change-rate-value-behind-text');
      }

      this.waveGroup = this.bodyGroup.append('g').attr('clip-path', this.getUniqUrl(uniqId));
      this.waterFill = this.waveGroup.append('rect').attr('id', 'water-fill');

      this.overlayText = this.waveGroup.append('text').attr('id', 'overlay-text');
      this.overlayArrow = this.waveGroup.append('text').attr('id', 'overlay-arrow');
  }



applyFillAttributes() {
  if (this.tankType === 'tower') {

    this.applyAttributes(this.skyFill, {
      x: 0,
      y: 0,
      width: this.innerWidth,
      height: 30,
      fill: this.skyFillColor,
      'fill-opacity': this.backFillOpacity,
      transform: `translate(-${(this.tankWidth - this.borderWidth)/2}, -${(this.tankHeight - this.borderWidth)/2})`
    });


    this.applyAttributes(this.waterFill, {
      x: 0,
      y: 30,
      width: this.innerWidth,
      height: this.innerHeight-30,
      rx: this.innerCornerRadius,
      ry: this.innerCornerRadius,
      fill: this.backFillColor,
      'fill-opacity': this.backFillOpacity,
      transform: `translate(-${(this.tankWidth - this.borderWidth)/2}, -${(this.tankHeight - this.borderWidth)/2})`
    });


    this.applyAttributes(this.backFill, {
      datum: { color: this.backFillColor },
      x: 0,
      y: 0,
      width: this.innerWidth,
      height: this.innerHeight,
      rx: this.innerCornerRadius,
      ry: this.innerCornerRadius,
      fill: function(d) { return d.color; },
      transform: `translate(-${(this.tankWidth - this.borderWidth)/2}, -${(this.tankHeight - this.borderWidth)/2})`
    });

    this.applyAttributes(this.border, {
      x: 0,
      y: 0,
      width: this.tankWidth,
      height: this.tankHeight,
      rx: this.borderCornerRadius,
      ry: this.borderCornerRadius,
      'fill-opacity': 0,
      stroke: this.borderColor,
      'stroke-width': this.borderWidth,
      transform: `translate(-${this.tankWidth/2}, -${this.tankHeight/2})`
    });
}

applyTextAttributes() {
  let transform = `translate(0, ${this.fontSize/4})`;

  this.applyAttributes(this.behindText, {
    datum: { color: this.backFontColor === null ? this.fillColor : this.backFontColor },
    'text-anchor': 'middle',
    'font-family': this.fontFamily,
    'font-size': `${this.fontSize}px`,
    'font-weight': this.fontWeight,
    fill: function(d) { return d.color; },
    text: `0 ${this.fillUnit}`,
    transform: transform
  });

  this.applyAttributes(this.behindArrow, {
    datum: { color: this.backFontColor === null ? this.fillColor : this.backFontColor },
    'text-anchor': 'middle',
    'font-family': this.arrowFontFamily,
    'font-size': `${this.arrowFontSize}px`,
    'font-weight': this.arrowFontWeight,
    fill: function(d) { return d.color; },
    text: `${this.arrowName === null ? this.noArrowName : this.arrowName}`,
  });

  this.applyAttributes(this.overlayText, {
    datum: { color: this.frontFontColor === null ? "#fff" : this.frontFontColor },
    'text-anchor': 'middle',
    'font-family': this.fontFamily,
    'font-size': `${this.fontSize}px`,
    'font-weight': this.fontWeight,
    fill: function(d) { return d.color; },
    'fill-opacity': this.overlayTextFillOpacity,
    text: `0 ${this.fillUnit}`,
    transform: transform
  });

  this.applyAttributes(this.overlayArrow, {
    datum: { color: this.frontFontColor },
    'text-anchor': 'middle',
    'font-family': this.arrowFontFamily,
    'font-size': `${this.arrowFontSize}px`,
    'font-weight': this.arrowFontWeight,
    fill: function(d) { return d.color; },
    text: `${this.arrowName === null ? this.noArrowName : this.arrowName}`,
  });


// handle color change for bloom
tweenElements () {
  this.calculateColor();
  this.colorTransition(this.backFill, "fill", this.fillAnimationColor);
  this.colorTransition(this.supportLabelBg, 'stroke', this.fillAnimationColor);


  this.tweenText();

  if ( this.arrow === true ) {
    this.colorTransition(this.behindArrow, "fill", this.backArrowAnimationColor);
    this.colorTransition(this.overlayArrow, "fill", this.frontArrowColor);
  }
}


tweenText() {
  let that = this;

  this.behindText
  .transition()
  .delay(this.delay)
  .ease(this.ease)
  .duration(this.transitionDuration)
  .tween("text", function(d) {
    let node = this;
    let interpolate = d3.interpolate(that.textFormatter(node.textContent), that.textFormatter(that.fillValue));


    return function(t) {
      node.textContent = that.textFormatter(interpolate(t));
    };
  })
  .attrTween("fill", function(d) {
    let interpolator = d3.interpolateRgb(d.color, that.backFontAnimationColor);

    return function(t) {
      d.color = interpolator(t);
      return d.color;
    };
  });

  this.overlayText

  .transition()
  .delay(this.delay)
  .ease(this.ease)
  .duration(this.transitionDuration)
  .tween("text", function(d) {
    let node = this;
    let interpolate = d3.interpolate(that.textFormatter(node.textContent), that.textFormatter(that.fillValue));
    return function(t) {
      if (that.arrow === true) {
        that.updateArrowPosition();
      }
      node.textContent = that.textFormatter(interpolate(t));
    };
  })
  .attrTween("fill", function(d) {
    let interpolator = d3.interpolateRgb(d.color, that.frontFontColor);

    return function(t) {
      d.color = interpolator(t);
      return d.color;
    };
  })
  .on('end', function() {
    if (that.arrow === true) {
      that.updateArrowPosition();
    }
  });

  if (this.lightValueEnabled) {
    this.lightValueBehindText
    .transition()
    .delay(this.delay)
    .ease(this.ease)
    .duration(this.transitionDuration)
    .tween("text", function(d) {
      let node = this;
      let interpolate = d3.interpolate(that.lookupTextFormatter(node.textContent), that.lookupTextFormatter(that.lightValue));

      return function(t) {
        node.textContent = that.lookupTextFormatter(interpolate(t));
      };
    })
    .attrTween("fill", function(d) {
      let interpolator = d3.interpolateRgb(d.color, that.backFontAnimationColor);

      return function(t) {
        d.color = interpolator(t);
        return d.color;
      };
    });

    this.lightValueOverlayText
    .transition()
    .delay(this.delay)
    .ease(this.ease)
    .duration(this.transitionDuration)
    .tween("text", function(d) {
      let node = this;
      let interpolate = d3.interpolate(that.lookupTextFormatter(node.textContent), that.lookupTextFormatter(that.lightValue));
      return function(t) {
        node.textContent = that.lookupTextFormatter(interpolate(t));
      };
    })
    .attrTween("fill", function(d) {
      let interpolator = d3.interpolateRgb(d.color, that.frontFontColor);

      return function(t) {
        d.color = interpolator(t);
        return d.color;
      };
    });
  }

  if (this.respirationEnabled) {
    this.respirationBehindText
    .transition()
    .delay(this.delay)
    .ease(this.ease)
    .duration(this.transitionDuration)
    .tween("text", function(d) {
      let node = this;
      let interpolate = d3.interpolate(that.respirationTextFormatter(node.textContent), that.respirationTextFormatter(that.respiration));

      return function(t) {
        node.textContent = that.respirationTextFormatter(interpolate(t));
      };
    })
    .attrTween("fill", function(d) {
      let interpolator = d3.interpolateRgb(d.color, that.backFontAnimationColor);

      return function(t) {
        d.color = interpolator(t);
        return d.color;
      };
    });

    this.respirationOverlayText
    .transition()
    .delay(this.delay)
    .ease(this.ease)
    .duration(this.transitionDuration)
    .tween("text", function(d) {
      let node = this;
      let interpolate = d3.interpolate(that.respirationTextFormatter(node.textContent), that.respirationTextFormatter(that.respiration));
      return function(t) {
        node.textContent = that.respirationTextFormatter(interpolate(t));
      };
    })
    .attrTween("fill", function(d) {
      let interpolator = d3.interpolateRgb(d.color, that.frontFontColor);

      return function(t) {
        d.color = interpolator(t);
        return d.color;
      };
    });
  }
}

full js file

1 个答案:

答案 0 :(得分:0)

您已将所有4个文本元素两次添加到SVG。两者都被遮盖或修剪。

全部删除它们,并在g元素后添加一组文本,该元素被水上动画剪裁

tank.js::initTower ()中,注释所有this.backAAA变量,删除对这些变量的所有引用(很多行),并将所有this.overlayAAA变量附加到this.bodyGroup

  this.backFill = this.bodyGroup.append('rect').attr('id', 'back-fill');
  this.skyFill = this.bodyGroup.append('rect').attr('id', 'sky-fill');
  this.border = this.bodyGroup.append('rect').attr('id', 'border');
  // this.behindText = this.bodyGroup.append('text').attr('id', 'behind-text');
  // this.behindArrow = this.bodyGroup.append('text').attr('id', 'behind-arrow');

  // if (this.lightValueEnabled) {
  //   this.lightValueBehindText = this.bodyGroup.append('text').attr('id', 'light-behind-text');
  // }

  // if (this.respirationEnabled) {
  //   this.respirationBehindText = this.bodyGroup.append('text').attr('id', 'change-rate-value-behind-text');
  // }

  this.waveGroup = this.bodyGroup.append('g').attr('clip-path', this.getUniqUrl(uniqId));
  this.waterFill = this.waveGroup.append('rect').attr('id', 'water-fill');

  this.overlayText = this.bodyGroup.append('text').attr('id', 'overlay-text');
  this.overlayArrow = this.bodyGroup.append('text').attr('id', 'overlay-arrow');

  if (this.lightValueEnabled) {
    this.lightValueOverlayText = this.bodyGroup.append('text').attr('id', 'lookup-value-overlay-text');
  }

  if (this.respirationEnabled) {
    this.respirationOverlayText = this.bodyGroup.append('text').attr('id', 'change-rate-value-overlay-text');
  }

  this.supportLabelGroup = this.bodyGroup.append('g').attr('id', 'support-label-group');
  this.supportLabelBg = this.supportLabelGroup.append('rect').attr('id', 'support-label-bg');
  this.supportLabel = this.supportLabelGroup.append('text').attr('id', 'overlay-support-label');
  this.topSupportLabel = this.supportLabelGroup.append('text').attr('id', 'top-overlay-support-label');