如何使用ng-repeat函数渲染两个Solid Gauge仪表盘?
解决AngularJS中循环生成多个Highcharts Solid Gauge仪表盘的问题
我一眼就看出问题所在了——你每次循环都在同一个humidity_container容器里初始化图表,后面的图表会直接覆盖前面的,所以最后只能看到最后一个数据的仪表盘。下面是具体的修复方案,分步骤来:
1. 先修改HTML结构,用ng-repeat生成独立容器
把原来的单个div改成循环生成的多个容器,每个容器要有唯一的ID,这样每个图表都有自己的渲染空间:
<!-- 用ng-repeat遍历vm.TempHumidity数组,每个项对应一个仪表盘容器 --> <div ng-repeat="item in vm.TempHumidity" id="gauge-container-{{$index}}" class="gauge-container" style="width: 200px; height: 200px;"></div>
这里给每个容器加了基础宽高样式,你可以根据需求调整。如果你的SensorID是唯一值,也可以用id="gauge-container-{{item.SensorID}}",比索引更可靠。
2. 调整AngularJS代码,修复数据存储和图表初始化逻辑
原来的代码里有两个关键问题:一是没把整理好的数据存入vm.TempHumidity数组(ng-repeat没数据可循环),二是图表初始化时机不对。修改后的完整代码如下:
vm.GetTempHumidity = function () { var TempHumidityURL = url + "sensors/TempHumidity"; $http.get(TempHumidityURL).then(function (response) { vm.TempHumidity = []; // 第一步:先把所有数据整理好存入数组 angular.forEach(response.data, function (value, key) { var obj = { SensorID: value.SensorID, SensorName: value.SensorName, Data1: value.Data.split(',')[0], Data2: value.Data.split(',')[1], SignalStrength: value.SignalStrength, Battery: value.Battery, InsertDate: moment(value.InsertDate).format('DD/MM/YYYY hh:mm A') }; // 一定要把对象push进数组,不然ng-repeat没数据 vm.TempHumidity.push(obj); }); // 第二步:等ng-repeat渲染完所有容器后,再初始化每个图表 // 用$timeout确保DOM已经渲染完成 $timeout(function() { angular.forEach(vm.TempHumidity, function(item, index) { var rawData = item.Data1; var data = getData(rawData); // 把getData函数提出来,避免重复定义 function getData(rawData) { var data = [], start = Math.round(Math.floor(rawData / 10) * 10); data.push(rawData); // 注意给i加var声明,避免污染全局变量 for (var i = start; i > 0; i -= 1) { data.push({ y: i }); } return data; } // 用唯一ID初始化对应容器的图表 Highcharts.chart(`gauge-container-${index}`, { chart: { type: 'solidgauge', marginTop: 0, backgroundColor: 'transparent', // height:150, }, credits: { enabled: false }, // 可以显示传感器名称,方便区分不同仪表盘 title: { text: item.SensorName, style: { fontSize: '14px' } }, subtitle: { text: rawData + ' °C', style: { 'font-size': '17px' }, y: 103, }, tooltip: { enabled: true }, pane: [{ startAngle: -90, endAngle: 90, background: [{ outerRadius: '100%', innerRadius: '60%', backgroundColor: Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0.1).get(), borderWidth: 0, shape: 'arc' }], size: '100%', center: ['50%', '30%'] }, { startAngle: -180, endAngle: 180, }], yAxis: [{ min: 0, max: 100, labels: { enabled: false }, stops: [ [0, '#55F709'], [0.1, '#0f0'], [0.2, '#2d0'], [0.3, '#4b0'], [0.4, '#690'], [0.5, '#870'], [0.6, '#a50'], [0.7, '#c30'], [0.8, '#e10'], [0.9, '#f03'], [1, '#f06'] ] }], series: [{ animation: false, dataLabels: { enabled: false }, color: Highcharts.getOptions().colors[0], radius: '100%', innerRadius: '60%', data: data, }] }); }); }); }); }
关键修改点说明
- 把整理好的
obj存入vm.TempHumidity数组,这样ng-repeat才有数据生成对应的容器。 - 用
$timeout延迟图表初始化,确保ng-repeat已经把所有容器渲染到DOM中,避免找不到元素的问题。 - 每个图表初始化时使用唯一的容器ID,彻底解决覆盖问题。
- 修复了
getData函数中i变量未声明的全局污染问题。 - 新增了传感器名称作为图表标题,方便区分不同的仪表盘。
内容的提问来源于stack exchange,提问作者Jayesh_K
相关产品推荐
相关产品推荐

