首页 > 解决方案 > D3 v5 - 如何设置文本的背景颜色(仅与文本一样宽)

问题描述

考虑一下我放在一些圈子里的一些文本的代码:

var margins = {top:20, bottom:300, left:30, right:100};

var height = 600;
var width = 1080;

var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;

var svg = d3.select('body')
    .append('svg')
    .attr('width', totalWidth)
    .attr('height', totalHeight);

var graphGroup = svg.append('g')
    .attr('transform', "translate("+margins.left+","+margins.top+")");

//var tsvData = d3.tsv('circle-pack-data.tsv');

//tsvData.then(function(rawData) {

/*
  var data = rawData.map(function(d) {
    return {id:d.id, parentId:d.parentId, size:+d.size}
  });
*/



  var data = [
    [
    {'id':'3Q18'},
    {'id':'Greater China','parentId':'3Q18','size':428.7,'sign':'negative'},
    {'id':'Thematic','parentId':'3Q18', 'size':111.8,'sign':'positive'},
    {'id':'US','parentId':'3Q18', 'size':418.3,'sign':'positive'},
    {'id':'India','parentId':'3Q18', 'size':9.39,'sign':'negative'},
    {'id':'Europe','parentId':'3Q18', 'size':94.0,'sign':'positive'},
    {'id':'Japan','parentId':'3Q18', 'size':0,'sign':'positive'},
    {'id':'Global','parentId':'3Q18', 'size':41.9,'sign':'negative'}
  ],

  [
  {'id':'4Q18'},
  {'id':'Greater China','parentId':'4Q18','size':217.8,'sign':'negative'},
  {'id':'Thematic','parentId':'4Q18', 'size':100.5,'sign':'positive'},
  {'id':'US','parentId':'4Q18', 'size':127.9,'sign':'negative'},
  {'id':'India','parentId':'4Q18', 'size':1.5,'sign':'negative'},
  {'id':'Europe','parentId':'4Q18', 'size':1.5,'sign':'positive'},
  {'id':'Japan','parentId':'4Q18', 'size':0,'sign':'positive'},
  {'id':'Global','parentId':'4Q18', 'size':52.8,'sign':'negative'}
],

];

var colorMap = {
  '3Q18':"#d9d9d9",
  '4Q18':"#d9d9d9",
  '3Q19':"#d9d9d9",
  '4Q19':"#d9d9d9",
  'Greater China':"#003366",
  'Thematic':"#366092",
  'US':"#4f81b9",
  'India':"#95b3d7",
  'Europe':"#b8cce4",
  'Japan':"#e7eef8",
  'Global':"#a6a6a6"
};

var defs = svg.append('svg:defs');
var blue1x = "Fills/blue-1-crosshatch-redo.svg";
var blue2x = "Fills/blue-2-crosshatch.svg";
var blue3x = "Fills/blue-3-crosshatch.svg";
var blue4x = "Fills/blue-4-crosshatch.svg";
var blue5x = "Fills/blue-5-crosshatch.svg";
var blue6x = "Fills/blue-6-crosshatch.svg";
var grayx = "Fills/gray-2-crosshatch.svg";

defs.append("svg:pattern")
    .attr("id", "blue1_hatch")
    .attr("width", 20)
    .attr("height", 20)
    .attr("patternUnits", "userSpaceOnUse")
    .append("svg:image")
    .attr("xlink:href", blue1x)
    .attr("width", 20)
    .attr("height", 20)
    .attr("x", 0)
    .attr("y", 0);

  defs.append("svg:pattern")
      .attr("id", "blue2_hatch")
      .attr("width", 20)
      .attr("height", 20)
      .attr("patternUnits", "userSpaceOnUse")
      .append("svg:image")
      .attr("xlink:href", blue2x)
      .attr("width", 20)
      .attr("height", 20)
      .attr("x", 0)
      .attr("y", 0);

  defs.append("svg:pattern")
      .attr("id", "blue3_hatch")
      .attr("width", 20)
      .attr("height", 20)
      .attr("patternUnits", "userSpaceOnUse")
      .append("svg:image")
      .attr("xlink:href", blue3x)
      .attr("width", 20)
      .attr("height", 20)
      .attr("x", 0)
      .attr("y", 0);

  defs.append("svg:pattern")
      .attr("id", "blue4_hatch")
      .attr("width", 20)
      .attr("height", 20)
      .attr("patternUnits", "userSpaceOnUse")
      .append("svg:image")
      .attr("xlink:href", blue4x)
      .attr("width", 20)
      .attr("height", 20)
      .attr("x", 0)
      .attr("y", 0);

  defs.append("svg:pattern")
      .attr("id", "blue5_hatch")
      .attr("width", 20)
      .attr("height", 20)
      .attr("patternUnits", "userSpaceOnUse")
      .append("svg:image")
      .attr("xlink:href", blue5x)
      .attr("width", 20)
      .attr("height", 20)
      .attr("x", 0)
      .attr("y", 0);

  defs.append("svg:pattern")
      .attr("id", "blue6_hatch")
      .attr("width", 20)
      .attr("height", 20)
      .attr("patternUnits", "userSpaceOnUse")
      .append("svg:image")
      .attr("xlink:href", blue6x)
      .attr("width", 20)
      .attr("height", 20)
      .attr("x", 0)
      .attr("y", 0);

  defs.append("svg:pattern")
      .attr("id", "gray_hatch")
      .attr("width", 20)
      .attr("height", 20)
      .attr("patternUnits", "userSpaceOnUse")
      .append("svg:image")
      .attr("xlink:href", grayx)
      .attr("width", 20)
      .attr("height", 20)
      .attr("x", 0)
      .attr("y", 0);

var negativeMap = {
  '3Q18':"#d9d9d9",
  '4Q18':"#d9d9d9",
  '3Q19':"#d9d9d9",
  '4Q19':"#d9d9d9",
  'Greater China':"url(#blue1_hatch)",
  'Thematic':"url(#blue2_hatch)",
  'US':"url(#blue3_hatch)",
  'India':"url(#blue4_hatch)",
  'Europe':"url(#blue5_hatch)",
  'Japan':"url(#blue6_hatch)",
  'Global':"url(#gray_hatch)"
};

var strokeMap = {
  "Greater China":"#fff",
  "Thematic":"#fff",
  "US":"#fff",
  'India':"#000",
  'Europe':"#000",
  'Japan':"#000",
  'Global':"#000"
};

    for (var j=0; j <(data.length); j++) {

  var vData = d3.stratify()(data[j]);

  var vLayout = d3.pack().size([250, 250]);

  var vRoot = d3.hierarchy(vData).sum(function (d) { return d.data.size; });
  var vNodes = vRoot.descendants();
  vLayout(vRoot);

  var thisClass = "circ"+String(j);

  var vSlices = graphGroup.selectAll('.'+thisClass).data(vNodes).attr('class',thisClass).enter().append('g');

  console.log(vNodes)

  vSlices.append('circle')
      .attr('cx', function(d, i) {
          return d.x+(j*300)
      })
      .attr('cy', function (d) { return d.y; })
      .attr('r', function (d) { return d.r; })
      .style('fill', function(d) {
        //console.log(d.data.id)
        if (d.data.data.sign=='positive') {
          return colorMap[d.data.id];
        } else {
          return negativeMap[d.data.id];
        }
        });

  vSlices.append('text')
      .attr('x', function(d,i) {return d.x+(j*300)})
      .attr('y', function(d) {return d.y+5})
      .attr('text-anchor','middle')
      .style('fill', function(d) {return strokeMap[d.data.id]})
      .style('background-color', function(d) {return colorMap[d.data.id]})
      .text(function(d) {return d.data.data.size ? d.data.data.size : null});

}
<script src="https://d3js.org/d3.v5.min.js"></script>

由于圆圈的填充有时可能是阴影线(不是纯色),因此文本的可读性会受到影响。我还发现仅仅添加文本阴影是不够的。我想选择“核”选项并为我附加的文本分配纯色背景色。我想我可以通过以下方式做到这一点:

  vSlices.append('text')
      .attr('x', function(d,i) {return d.x+(j*300)})
      .attr('y', function(d) {return d.y+5})
      .attr('text-anchor','middle')
      .style('fill', function(d) {return strokeMap[d.data.id]})
      .style('background-color', function(d) {return colorMap[d.data.id]})
      .text(function(d) {return d.data.data.size ? d.data.data.size : null});

然而这并没有取得任何成果。

问题

为 svg 文本动态分配背景颜色的正确方法是什么?(看到背景颜色需要与圆圈的颜色相匹配colorMap

标签: javascriptcssd3.jssvg

解决方案


你可以用这样的css做到这一点

p {
  display: inline-block;
  background-color: tomato;
}

它只会为文本的背景赋予颜色。您也可以使用display: inline,但您将无法对边距或其他元素等元素进行更改。

所以使用display: inline-block

我希望它有帮助:)


推荐阅读