如何在 google 气泡图中将轴标签与图表区域外的扩展主要网格线对齐
How to align axis label with extended major gridlines outside the chartarea in google bubble chart
我正在使用 google 可视化气泡图,我需要像下面这样对齐垂直轴标签,我想将标签对齐到图表的边距而不是轴线,还需要 2线并将主网格线延伸到图表区域之外。
代码也在这里:
<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');
}
});
google 图表使用剪辑路径附加可视图形。您可以使用 <circle>
元素上的 cx
(水平轴)、cy
(垂直轴)和 r
(半径)属性来控制它。
由于每一行将(或必须)具有相同的高度,您可以简单地添加一些 js 来制作 cy = cy - 10;
(或任何使您的圆圈出现在您想要的位置的数字。
但是这里还有一个问题,你不能在顶轴或底轴上设置圆圈。好吧,你可以,但它将是 canvas 的一半。在这一点上我认为这里没什么可做的,不能在这个元素上使用 z-index css 属性 所以你可能无法达到所需的方法。
请求的更改只能通过手动修改图表的 SVG 来完成,
这可以在图表的 '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>
我正在使用 google 可视化气泡图,我需要像下面这样对齐垂直轴标签,我想将标签对齐到图表的边距而不是轴线,还需要 2线并将主网格线延伸到图表区域之外。
代码也在这里:
<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');
}
});
google 图表使用剪辑路径附加可视图形。您可以使用 <circle>
元素上的 cx
(水平轴)、cy
(垂直轴)和 r
(半径)属性来控制它。
由于每一行将(或必须)具有相同的高度,您可以简单地添加一些 js 来制作 cy = cy - 10;
(或任何使您的圆圈出现在您想要的位置的数字。
但是这里还有一个问题,你不能在顶轴或底轴上设置圆圈。好吧,你可以,但它将是 canvas 的一半。在这一点上我认为这里没什么可做的,不能在这个元素上使用 z-index css 属性 所以你可能无法达到所需的方法。
请求的更改只能通过手动修改图表的 SVG 来完成,
这可以在图表的 '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>