代码之家  ›  专栏  ›  技术社区  ›  Shafique Jamal

c3js:如何移动和旋转网格线文本?

  •  0
  • Shafique Jamal  · 技术社区  · 6 年前

    可以向c3js图表添加网格线,如下所示:

    Add x grid lines

    Style x grid lines

    上面的第二个链接显示了如何设置网格线的样式。

    如何使用css或其他方法:

    (a)将网格线文本移动到网格线的另一侧?

    (b)将文本顺时针旋转90度,然后向左、向右等移动?

    更新:我正在使用 React-c3js ,因此我不能简单地选择svg元素并转换和旋转它(因此建议使用 CSS )

    1 回复  |  直到 6 年前
        1
  •  0
  •   Vanquished Wombat    6 年前

    这是一种可能的方法。图表的onrendered()事件用于运行某些js,这些js使用d3.js(在使用c3.js时已经存在)来定位网格线文本并根据需要对其进行操作。请参阅红色文本“label 2”和“label4”。

    我对css解决方案进行了合理的研究,但我的结论是,css方法会有问题,因为css和svg属性之间的接口在编写时不一致。js解决方案似乎是可行的。

    const { Component } = React;
    const columns = [
      ['My Numbers', 30, 200, 100, 400, 150, 250],
      ['Your Numbers', 50, 20, 10, 40, 15, 25]
    ];
    
    class Chart extends Component {
      componentDidMount() {
        this._updateChart();
      }
      componentDidUpdate() {
        this._updateChart();
      }
      _updateChart() {
        const chart = c3.generate({
          bindto: '#chart',
          size: { width: 400, height: 200},
          data: {
            columns: this.props.columns,
            type: this.props.chartType
          },
              grid: {
            x: {
                lines: [{value: 2, text: 'Label 2'}, {value: 4, text: 'LABEL 4'}]
            },
            y: {
                lines: [{value: 300, text: 'LABEL 300'}]
            }
        },
          onrendered:  function() {
    
            // for each svg element with the class 'c3-xgrid-line'
            d3.selectAll('.c3-xgrid-line').each(function(d, i){
    
              // cache the group node
              var groupNode = d3.select(this).node();         
    
              // for each 'text' element within the group 
              d3.select(this).select('text').each(function(d, i){
                            
                // hide the text to get size of group box otherwise text affects size.
                d3.select(this).attr("hidden",true); 
    
                // use svg getBBox() func to get the group size without the text - want the position
                var groupBx = groupNode.getBBox();
    
                d3.select(this)
                  .attr('transform', null) // remove text rotation
                  .attr('x', groupBx.x)   // x-offset from left of chart
                  .attr('y', 0)          // y-offset of the text from the top of the chart 
                  .attr('dx', 20)         // small x-adjust to clear the line
                  .attr('dy', 15)         // small y-adjust to get onto the chart
                  .attr("hidden", null)   // better make the text visible again
                  .attr("text-anchor", null)  // anchor to left by default
                  .style('fill', 'red');    // color it red for fun
                })
            })   
          }
        });
      }
      render() {
     
        
        return <div id="chart">hi</div>;  
        
      }
    
    }
    
    class App extends Component {
      constructor(props) {
        super(props);
        this._setBarChart = this._setBarChart.bind(this);
        this._setLineChart = this._setLineChart.bind(this);
        this.state = {
          chartType: 'line'
        };
      }
      _setBarChart() {
        this.setState({ chartType: 'bar' });
      }
      _setLineChart() {
        this.setState({ chartType: 'line' });
      }
    	render() {
    		return (
          <div className="app-wrap">
            <Chart 
              columns={columns}
              chartType={this.state.chartType} />
            <p>
              Chart Type
              <button onClick={this._setBarChart}>bar</button> 
              <button onClick={this._setLineChart}>Line</button>
            </p>
          </div>
        );
      }
    }
    
    ReactDOM.render(
    	<App />,
        document.getElementById('app')
    );
    * {
      box-sizing: border-box;
    }
    body {
      background: #eee;
    }
    p {
      text-align: center;
    }
    button {
      margin-left: 1em;
      background: #159fff;
      border: none;
      padding: 0.5em 2em;
      color: white;
      text-transform: uppercase;
    
    }
    
    #chart {
      background: #fff;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.7/c3.min.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.7/c3.min.js"></script>
    
    
    
    <div class='chart-wrapper'>
    <div id="app"></div>
    </div>