Как выровнять метку оси с расширенными основными линиями сетки вне хартарной области в Google Bubble Chart - PullRequest
0 голосов
/ 25 февраля 2020

Я использую пузырьковую диаграмму визуализации Google, мне нужно выровнять метки по вертикальной оси, как показано ниже, я хочу выровнять метки по краю диаграммы, а не по линии оси, также нужно 2 линии и расширить основную сетку линия вне области диаграммы. enter image description here

Вот пример того же jsfiddle: http://jsfiddle.net/g1goldmine/9xrw2gLj/140/

Также вот код:

<div data-ng-app="mainApp" data-ng-controller="mainSearchController"
     ng-init="ShowChart()">
    <div class="row" ng-mouseover="mousepoints($event)">
        <div google-chart chart="saleChart"
             agc-on-mouseover="showTooltip(row)"
             agc-on-mouseout="hideTooltip()">
        </div>
        <div id="custom_tooltip"
             style="position:fixed; border:0px solid #777777;
                    padding-left:10px; line-height:15px; color:#5f5f5f;
                    font-family:Arial; background-color:#FFFFFF;
                    height:auto; width:auto; font-size:10px;">
        </div>
    </div>
</div>

А вот код angularjs для привязки диаграммы

var app = angular.module('mainApp', ['googlechart']);

app.controller('mainSearchController', function ($scope) {

    $scope.ShowChart = function () {     
        var saleChart = {};
        saleChart.type = 'BubbleChart';
        saleChart.cssStyle = "height:100%; width:100%;";
        var options = {
            sizeAxis: {
                maxSize: 7,
                minSize: 1
            },
            fontSize:10,
            legend: 'none',
            height: 200,
            width: 400,
            bubble: { stroke: '#fdca0f', opacity: 1 },
            colors: ['#fdca0f', '#fdca0f'],
            tooltip: {
                trigger: 'none'
            },
            hAxis: {
                ticks: [
                    { v: 800, f: '2015' },
                    { v: 1200, f: '2016' },
                    { v: 1600, f: '2017' },
                    { v: 2000, f: '2018' },
                    { v: 2400, f: '2019' },
                    { v: 2800, f: '2020' }
                ],
                gridlines: { color: '#dedede' },
                minorGridlines: { color: '#f7f7f7', count: 3 },
                textStyle: { color: '#5f5f5f' }    
            },
            vAxis: {
                ticks: [
                    { v: 1, f: 'Chennai in March' },
                    { v: 2, f: 'Mumbai in March' },
                    { v: 3, f: 'Delhi in April' },
                    { v: 4, f: 'Chennai in April' }

                ],
                gridlines: { color: '#dedede' },
                textStyle: { color: '#5f5f5f' }
            }
        };

        var d = [
          ["Name", "Year", "Place", "", "Sales", "tooltip"],
          ["", 1000, 2, "", 26, "Sale List"],
          ["",1200,3,"",28,"Sale List"],
          ["",1400,3,"",48,"S"],
          ["",1600,3,"",29,"S"]
        ];
        saleChart.data = d;
        $scope.chartData = d;
        saleChart.options = options;
        $scope.saleChart = saleChart;        

    }

    var mouseX;
    var mouseY;
    $scope.mousepoints = function (e) {
        mouseX = e.pageX;
        mouseY = e.pageY;
    }

    $scope.showTooltip = function (row) {    
        var x = mouseX;
        var y = mouseY + 10;        
        if (row != null) {        
            dataTable = google.visualization.arrayToDataTable($scope.chartData);
            var v = dataTable.getValue(row, 5);
            //var v = $scope.chartData.rows[row][5];
            v = v.toString().replace(/,/g, "<br/>")

            $('#custom_tooltip').html('<div>' + v + '</div>').css({
                'top': y,
                'left': x
            }).fadeIn('slow');
        }
    }
    $scope.hideTooltip = function () {
        $('#custom_tooltip').fadeOut('fast');
    }
});

Ответы [ 2 ]

1 голос
/ 17 марта 2020

запрошенные изменения могут быть сделаны только путем изменения SVG диаграммы вручную,
это может быть сделано для события 'ready' диаграммы.

сначала добавьте событие ready к элементу <div google-chart> ...

<div google-chart chart="saleChart" agc-on-ready="onReady(chartWrapper)"
     agc-on-mouseover="showTooltip(row)" agc-on-mouseout="hideTooltip()">
</div>

, затем добавьте слушатель к контроллеру ...

для перемещения метки вниз, найдите элементы <text>,
и измените их атрибут 'y'.

Что касается линий сетки (<rect>), нам нужно изменить атрибут 'x', а также 'width'.
не только на линиях сетки, но и <rect> элементы, которые содержат линии сетки.

// ready event
$scope.onReady = function (chartWrapper) {
  // find, move labels
  var labels = chartWrapper.getChart().getContainer().getElementsByTagName('text');
  Array.prototype.forEach.call(labels, function(label) {
    if (label.getAttribute('text-anchor') === 'end') {
      var yLabel = parseFloat(label.getAttribute('y')) + (parseFloat(label.getAttribute('font-size')) * 2);
      label.setAttribute('y', yLabel);
    }
  });

  // find, expand grid lines
  var gridLines = chartWrapper.getChart().getContainer().getElementsByTagName('rect');
  Array.prototype.forEach.call(gridLines, function(line) {
    if ((line.getAttribute('height') === '1') ||
        ((line.getAttribute('x') !== '0') &&
        ((line.getAttribute('fill') === null) || (line.getAttribute('fill') === '#ffffff')))) {
      var lineWidth = parseFloat(line.getAttribute('width')) + parseFloat(line.getAttribute('x')) - 2;
      line.setAttribute('x', 2);
      line.setAttribute('width', lineWidth);
    }
  });
}

см. Следующий рабочий фрагмент ...

var app = angular.module('mainApp', ['googlechart']);

app.controller('mainSearchController', function ($scope) {
    $scope.ShowChart = function () {
        var saleChart = {};
        saleChart.type = 'BubbleChart';
        saleChart.cssStyle = "height:100%; width:100%;";
        var options = {
            sizeAxis: {
                maxSize: 7,
                minSize: 1
            },
            fontSize:10,
            legend: 'none',
            height: 200,
            width: 400,
            bubble: { stroke: '#fdca0f', opacity: 1 },
            colors: ['#fdca0f', '#fdca0f'],
            tooltip: {
                trigger: 'none'
            },
            hAxis: {
                ticks: [
                    { v: 800, f: '2015' },
                    { v: 1200, f: '2016' },
                    { v: 1600, f: '2017' },
                    { v: 2000, f: '2018' },
                    { v: 2400, f: '2019' },
                    { v: 2800, f: '2020' }
                ],
                gridlines: { color: '#dedede' },
                minorGridlines: { color: '#f7f7f7', count: 3 },
                textStyle: { color: '#5f5f5f' }
            },
            vAxis: {
                ticks: [
                    // add line break --> \n
                    { v: 1, f: 'Chennai\nin March' },
                    { v: 2, f: 'Mumbai\nin March' },
                    { v: 3, f: 'Delhi\nin April' },
                    { v: 4, f: 'Chennai\nin April' }
                ],
                gridlines: { color: '#dedede' },
                textStyle: { color: '#5f5f5f' }
            }
        };

        var d = [["Name", "Year", "Place", "", "Sales", "tooltip"],
        ["", 1000, 2, "", 26, "Sale List"],
        ["",1200,3,"",28,"Sale List"],
        ["",1400,3,"",48,"S"],["",1600,3,"",29,"S"]];
        saleChart.data = d;
        $scope.chartData = d;
        saleChart.options = options;
        $scope.saleChart = saleChart;

    }

    var mouseX;
    var mouseY;
    $scope.mousepoints = function (e) {
        mouseX = e.pageX;
        mouseY = e.pageY;
    }

    $scope.showTooltip = function (row) {
        var x = mouseX;
        var y = mouseY + 10;
        if (row != null) {
            dataTable = google.visualization.arrayToDataTable($scope.chartData);
            var v = dataTable.getValue(row, 5);
            //var v = $scope.chartData.rows[row][5];
            v = v.toString().replace(/,/g, "<br/>")

            $('#custom_tooltip').html('<div>' + v + '</div>').css({
                'top': y,
                'left': x
            }).fadeIn('slow');
        }
    }
    $scope.hideTooltip = function () {
        $('#custom_tooltip').fadeOut('fast');
    }
    
    $scope.onReady = function (chartWrapper) {
      var labels = chartWrapper.getChart().getContainer().getElementsByTagName('text');
      var labelIndex = 0;
      var nextLabels = [];
      Array.prototype.forEach.call(labels, function(label) {
        // find label
        if (label.getAttribute('text-anchor') === 'end') {
          // move label down
          var yLabel = parseFloat(label.getAttribute('y')) + (parseFloat(label.getAttribute('font-size')) * 1.5);
          label.setAttribute('y', yLabel);
          
          // set text line 1
          var labelText = chartWrapper.getOption('vAxis.ticks')[labelIndex].f.split('\n');
          label.textContent = labelText[0].toUpperCase();
          
          // save label
          nextLabels.push(label);
          labelIndex++;
        }
      });
      
      // add line 2
      nextLabels.forEach(function (label, labelIndex) {
        var yLabel = parseFloat(label.getAttribute('y')) + (parseFloat(label.getAttribute('font-size')) + 1);
        var nextLabel = label.parentNode.appendChild(label.cloneNode(true)); 
        var labelText = chartWrapper.getOption('vAxis.ticks')[labelIndex].f.split('\n');
        nextLabel.textContent = labelText[1];
        nextLabel.setAttribute('y', yLabel);
        
        // increase font size of line 1
        label.setAttribute('font-size', (parseFloat(label.getAttribute('font-size')) + 1));
        
        // re-align labels to left
        var labelWidth = label.getBBox().width;
        label.setAttribute('x', labelWidth + 2);
        labelWidth = nextLabel.getBBox().width;
        nextLabel.setAttribute('x', labelWidth + 2);
      });


      var gridLines = chartWrapper.getChart().getContainer().getElementsByTagName('rect');
      Array.prototype.forEach.call(gridLines, function(line) {
        if ((line.getAttribute('height') === '1') ||
            ((line.getAttribute('x') !== '0') &&
            ((line.getAttribute('fill') === null) || (line.getAttribute('fill') === '#ffffff')))) {
          var lineWidth = parseFloat(line.getAttribute('width')) + parseFloat(line.getAttribute('x')) - 2;
          line.setAttribute('x', 2);
          line.setAttribute('width', lineWidth);
        }
      });
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-google-chart/0.1.0/ng-google-chart.min.js"></script>

<div data-ng-app="mainApp" data-ng-controller="mainSearchController" ng-init="ShowChart()">
  <div class="row" ng-mouseover="mousepoints($event)">
    <div google-chart chart="saleChart" agc-on-mouseover="showTooltip(row)" agc-on-mouseout="hideTooltip()" agc-on-ready="onReady(chartWrapper)"></div>
    <div id="custom_tooltip" style="position:fixed; border:0px solid #777777; padding-left:10px; line-height:15px; color:#5f5f5f; font-family:Arial; background-color:#FFFFFF; height:auto; width:auto; font-size:10px;"></div>
  </div>
</div>
0 голосов
/ 16 марта 2020

Google диаграммы использует клип-путь для прикрепления визуальной графики. Вы можете управлять этим с помощью атрибутов cx (горизонтальная ось), cy (вертикальная ось) и r (радиус) для элементов <circle>. Поскольку каждая строка будет (или должна) иметь одинаковую высоту, вы можете просто добавить немного js, чтобы сделать cy = cy - 10; (или любое другое число, которое делает ваш круг, где вы хотите.

НО здесь есть еще одна проблема, вы не можете установить круги над верхней осью или снизу. Ну, вы можете, но это будет наполовину из холста. На данный момент я думаю, что здесь не так много, не могу использовать z-index css свойство для этих элементов, так что вы не сможете достичь желаемого подхода.

...