【问题标题】:Calculate padding for C3js horizontal bar charts计算 C3js 水平条形图的填充
【发布时间】:2020-04-21 13:17:22
【问题描述】:

基于我的旧问题:C3js horizontal bar chart labels cut off and sizing issue 我现在正在尝试使用画布上下文 textwidth 根据文本宽度计算 y 轴的必要填充。

const colors = ['#0065A3', '#767670', '#D73648', '#7FB2CE', '#00345B'];


const data= [
['veryveryveryveryverylongdatalabel01', 439034],
['veryveryveryveryverylongdatalabel02', 413664],
['veryveryveryveryverylongdatalabel03', 351376],
['veryveryveryveryverylongdatalabel04', 349932],
['veryveryveryveryverylongdatalabel05', 316490],
['veryveryveryveryverylongdatalabel06', 315039],
['veryveryveryveryverylongdatalabel07', 285908],
['veryveryveryveryverylongdatalabel08', 285681],
['veryveryveryveryverylongdatalabel09', 285215],
['veryveryveryveryverylongdatalabel10', 203248],
['veryveryveryveryverylongdatalabel11', 200508],
['veryveryveryveryverylongdatalabel12', 195508],
['veryveryveryveryverylongdatalabel13', 195058],
['veryveryveryveryverylongdatalabel14', 193508],
['veryveryveryveryverylongdatalabel15', 185508],
['veryveryveryveryverylongdatalabel16', 180508],
['veryveryveryveryverylongdatalabel17', 177508]
];

let totalDataValue = 0
data.forEach(function(d){
	totalDataValue+=d[1];
});
let maxLabelWidth = 0;
/**
* Measures the rendered width of arbitrary text given the font size and font face
* @param {string} text The text to measure
* @param {number} fontSize The font size in pixels
* @param {string} fontFace The font face ("Arial", "Helvetica", etc.)
* @returns {number} The width of the text
		     **/
function getWidth(text, font) {
  const canvas = document.createElement('canvas'),
        context = canvas.getContext('2d');
  context.font = font;
  return context.measureText(text).width;
}

//TODO get font fpr c3-text from CSS 
const font = '10px sans-serif'
data.forEach(function(d){
	//formatted string
  const label = d[0] + ": " + d3.format(",.0f")(d[1]) + " ["+d3.format(".2%")(d[1]/totalDataValue)+"]"; 
	maxLabelWidth = Math.max(maxLabelWidth, getWidth(label, font));
});
var C3Styles = null;

const chart1 = c3.generate({
  bindto: d3.select('#chart1'),
  data: {
    columns: data,
    type: 'bar',
    labels: {format : function(v, id) {return id + ": " + d3.format(",.0f")(v) + " ["+d3.format(".2%")(v/totalDataValue)+"]"; }}
  },
  bar: {
  	width: { ratio: 1}
  },
  legend: {
    show: false,
  },
  tooltip: {
    show: true,
    format: {
      value: function(value) {
        return d3.format(",.0f")(value);
      }
    }
  },
  zoom: {
    enabled: true
  },
  axis: {
    x: {
      show:false,
      type:'category',
      categories: ['value1']
    },
    y: {
      show:false,
        padding : {
            top: Math.ceil(maxLabelWidth)
        }
    },
    rotated: true
  }
  });
#chart1 {
  width: 600px;
  height: 400px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.15/c3.min.css" rel="stylesheet" />
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.15/c3.min.js"></script>
<div id="chart1" class "c3">

</div>

还有两个问题: 首先,虽然没有间距、内边距等,但计算出的文本宽度略低于 SVG 文本元素的宽度。如何根据文本长度获取 SVG 元素的宽度?

其次,即使该值可以正确计算,计算出来的文本宽度似乎也太低,无法用于 axis.y.padding.top 值。我错过了什么?

【问题讨论】:

    标签: javascript c3.js


    【解决方案1】:

    我找到了解决方案:不要使用 y 轴填充,而是使用全局填充并关闭剪辑路径。

    padding : {
                  right: Math.ceil(maxLabelDataWidth)
              },
    

    d3.select(chart1.element).select("." + c3.chart.internal.fn.CLASS.chart).attr("clip-path", null);
    

    const colors = ['#0065A3', '#767670', '#D73648', '#7FB2CE', '#00345B'];
    
    
    const data= [
    ['veryveryveryveryverylongdatalabel01', 439034],
    ['veryveryveryveryverylongdatalabel02', 413664],
    ['veryveryveryveryverylongdatalabel03', 351376],
    ['veryveryveryveryverylongdatalabel04', 349932],
    ['veryveryveryveryverylongdatalabel05', 316490],
    ['veryveryveryveryverylongdatalabel06', 315039],
    ['veryveryveryveryverylongdatalabel07', 285908],
    ['veryveryveryveryverylongdatalabel08', 285681],
    ['veryveryveryveryverylongdatalabel09', 285215],
    ['veryveryveryveryverylongdatalabel10', 203248],
    ['veryveryveryveryverylongdatalabel11', 200508],
    ['veryveryveryveryverylongdatalabel12', 195508],
    ['veryveryveryveryverylongdatalabel13', 195058],
    ['veryveryveryveryverylongdatalabel14', 193508],
    ['veryveryveryveryverylongdatalabel15', 185508],
    ['veryveryveryveryverylongdatalabel16', 180508],
    ['veryveryveryveryverylongdatalabel17', 177508]
    ];
    
    let totalDataValue = 0
    data.forEach(function(d){
        totalDataValue+=d[1];
    });
    let maxLabelDataWidth = 0;
    /**
    * Measures the rendered width of arbitrary text given the font size and font face
    * @param {string} text The text to measure
    * @param {number} fontSize The font size in pixels
    * @param {string} fontFace The font face ("Arial", "Helvetica", etc.)
    * @returns {number} The width of the text
                 **/
    function getWidth(text, font) {
      const canvas = document.createElement('canvas'),
            context = canvas.getContext('2d');
      context.font = font;
      return context.measureText(text).width;
    }
    
    //TODO get font fpr c3-text from CSS 
    const font = '10px sans-serif'
    data.forEach(function(d){
        //formatted string
      const label = d3.format(",.0f")(d[1]) + " ["+d3.format(".2%")(d[1]/totalDataValue)+"]"; 
        maxLabelDataWidth = Math.max(maxLabelDataWidth, getWidth(label, font));
    });
    var C3Styles = null;
    
    const chart1 = c3.generate({
      bindto: d3.select('#chart1'),
      data: {
        columns: data,
        type: 'bar',
        labels: {format : function(v, id) {return id + ": " + d3.format(",.0f")(v) + " ["+d3.format(".2%")(v/totalDataValue)+"]"; }}
      },
      bar: {
        width: { ratio: 1}
      },
      legend: {
        show: false,
      },
      tooltip: {
        show: true,
        format: {
          value: function(value) {
            return d3.format(",.0f")(value);
          }
        }
      },
      zoom: {
        enabled: true
      },
      padding : {
          right: Math.ceil(maxLabelDataWidth)
      },
    
      axis: {
        x: {
          show:false,
          type:'category',
          categories: ['value1']
        },
        y: {
          show:false,
        },
        rotated: true
      }
      });
      
      d3.select(chart1.element).select("." + c3.chart.internal.fn.CLASS.chart).attr("clip-path", null);
    #chart1 {
      width: 600px;
      height: 400px;
    }
    <link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.20/c3.min.css" rel="stylesheet" />
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.7.20/c3.min.js"></script>
    <div id="chart1" class "c3">
    
    </div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2015-07-01
      • 2018-08-30
      • 2020-02-23
      • 2011-08-16
      • 1970-01-01
      相关资源
      最近更新 更多