我使用的Google图表每10秒重绘一次。如果使用默认字体(Arial),则重绘(是的,我正在调用clearChart())是平滑的。如果我尝试通过在选项中执行fontName:'Roboto'来将字体更改为Roboto,则每次图表重绘时,它们都会“闪烁”,因为图表中隐藏了大约半秒钟(由空白填充),并且然后再次出现。
我可以在不同PC上甚至从Android上的Chrome复制相同的问题。
var temperatureOptions = {
fontName: 'Roboto',
hAxis: {
title: 'Time',
format: 'HH:mm',
},
vAxis: {
title: 'Temperature (℃)',
},
colors: ['#7892c2', '#4e6096', '#a52714', '#097138'],
legend: {
position: 'top',
}
};
temperatureChart.clearChart();
temperatureChart.draw(temperatureData, temperatureOptions);
如果我注释掉“ fontName:'Roboto',”,一切都会顺利进行。
完整HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Extractus</title>
<link rel="icon" type="image/png" href="/favicon.png">
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
<link href="https://fonts.googleapis.com/css?family=Roboto&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/style.css?v=201905271">
<meta charset="utf-8" />
</head>
<body>
<div class="container">
<div class="row">
<div class="col-12">
<a href="#" class="button" id="auto">Auto</a>
<a href="#" class="button" id="overrideOn">Override On</a>
<a href="#" class="button" id="overrideOff">Override Off</a>
<a href="#" class="button" id="restart">Restart</a>
</div>
</div>
<div id="stats" style="display:none;">On <span id="onPercentage"></span>% since <span id="onDate"></span></div>
<div id="spinner" class="lds-css ng-scope">
<div class="lds-spinner" style="width:100%;height:100%">
<div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
<span id="spinnerText">Connecting...</span>
</div>
</div>
<div class="chart" id="temperaturechart_div"></div>
<div class="chart" id="relativehumiditychart_div"></div>
<div class="chart" id="absolutehumiditychart_div"></div>
<div class="chart" id="needchart_div"></div>
<br>
<div class="row">
<div class="col-12">
<table id="table">
<thead id="tableHead">
<tr>
<th rowspan="2">Date</th>
<th colspan="4">Inside</th>
<th colspan="4">Outside</th>
<th rowspan="2">Need</th>
<th rowspan="2">Status</th>
</tr>
<tr>
<th>Temp (°C)</th>
<th>RH (%)</th>
<th>AH (g/m³)</th>
<th>DP (°C)</th>
<th>Temp (°C)</th>
<th>RH (%)</th>
<th>AH (g/m³)</th>
<th>DP (°C)</th>
</tr>
</thead>
<tbody id="tableBody"></tbody>
<tfoot id="tableFooter"></tfoot>
</table>
</div>
</div>
</div>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script src="/lib/signalr/dist/browser/signalr.min.js?v=201905272"></script>
<!--<script src="/lib/signalr/dist/browser/signalr-protocol-msgpack.min.js?v=201905272"></script>-->
<script src="/settings?v=201905272"></script>
<script src="/js/client.min.js?v=201905273" charset="utf-8"></script>
</body>
</html>
这是完整的JS:
"use strict";
google.charts.load('current', { packages: ['corechart', 'line'] });
google.charts.setOnLoadCallback(drawLineColors);
var temperatureData;
var relativeHumidityData;
var absoluteHumidityData;
var needData;
var temperatureChart;
var relativeHumidityChart;
var absoluteHumidityChart;
var needChart;
var lastDateSynced = new Date(2019, 1, 1, 0, 0, 0, 0);
var onDate = new Date(2019, 1, 1, 0, 0, 0, 0);
var onCount = 0;
var offCount = 0;
var synced = false;
var temperatureOptions = {
fontName: 'Roboto',
hAxis: {
title: 'Time',
format: 'HH:mm',
//textStyle: { fontName: 'Noto Sans JP' }
},
vAxis: {
title: 'Temperature (°C)',
//textStyle: { fontName: 'Noto Sans JP' }
},
colors: ['#7892c2', '#4e6096', '#a52714', '#097138'],
legend: {
position: 'top',
//textStyle: { fontName: 'Noto Sans JP' }
},
/*tooltip: {
textStyle: { fontName: 'Noto Sans JP' }
}*/
};
var relativeHumidityOptions = {
fontName: 'Roboto',
hAxis: {
title: 'Time',
format: 'HH:mm',
//textStyle: { fontName: 'Noto Sans JP' }
},
vAxis: {
title: 'Rel. Humidity (%)',
//textStyle: { fontName: 'Noto Sans JP' }
},
colors: ['#7892c2', '#4e6096'],
legend: {
position: 'top',
//textStyle: { fontName: 'Noto Sans JP' }
},
/*tooltip: {
textStyle: { fontName: 'Noto Sans JP' }
}*/
};
var absoluteHumidityOptions = {
fontName: 'Roboto',
hAxis: {
title: 'Time',
format: 'HH:mm',
//textStyle: { fontName: 'Noto Sans JP' }
},
vAxis: {
title: 'Abs. Humidity (g/m³)',
//textStyle: { fontName: 'Noto Sans JP' }
},
colors: ['#7892c2', '#4e6096'],
legend: {
position: 'top',
//textStyle: { fontName: 'Noto Sans JP' }
},
/*tooltip: {
textStyle: { fontName: 'Noto Sans JP' }
}*/
};
var needOptions = {
fontName: 'Roboto',
allowHtml: true,
hAxis: {
title: 'Time',
format: 'HH:mm',
//textStyle: { fontName: 'Noto Sans JP' }
},
vAxis: {
title: 'Need',
//textStyle: { fontName: 'Noto Sans JP' }
},
colors: ['#7892c2'],
seriesType: "line",
connectSteps: false,
series: {
1: {
type: "steppedArea",
color: '#FFE666',
visibleInLegend: false,
areaOpacity: 0.4,
isStacked: false,
enableInteractivity: false,
lineWidth: 1
},
2: {
type: "steppedArea",
color: '#00B31E',
visibleInLegend: false,
areaOpacity: 0.4,
isStacked: false,
enableInteractivity: false,
lineWidth: 0
}
},
legend: {
position: 'top',
//textStyle: { fontName: 'Noto Sans JP' }
},
/*tooltip: {
textStyle: { fontName: 'Noto Sans JP' }
}*/
};
//var connection = new signalR.HubConnectionBuilder().withUrl("/signalRHub").withHubProtocol(new signalR.protocols.msgpack.MessagePackHubProtocol()).build();
var connection = new signalR.HubConnectionBuilder().withUrl("/signalRHub").build();
//Disable send button until connection is established
document.getElementById("auto").disabled = true;
document.getElementById("overrideOn").disabled = true;
document.getElementById("overrideOff").disabled = true;
document.getElementById("restart").disabled = true;
function formatDate(dateObject) {
var d = new Date(dateObject);
var day = d.getDate();
var month = d.getMonth() + 1;
var year = d.getFullYear();
var hours = d.getHours();
var minutes = d.getMinutes();
var seconds = d.getSeconds();
if (day < 10) {
day = "0" + day;
}
if (hours < 10) {
hours = "0" + hours;
}
if (minutes < 10) {
minutes = "0" + minutes;
}
if (seconds < 10) {
seconds = "0" + seconds;
}
if (month < 10) {
month = "0" + month;
}
var date = year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds;
return date;
};
function round(value, precision) {
var multiplier = Math.pow(10, precision || 0);
return (Math.round(value * multiplier) / multiplier).toString();
}
function getTR(d, iT, oT, iRH, oRH, iAH, oAH, iDP, oDP, n, addData, insertRow) {
var s = true;
if (iRH < 0) { s = false; iRH = 0 - iRH; }
var date = new Date(d);
if (date > lastDateSynced)
lastDateSynced = date;
if (addData) {
if (insertRow) {
temperatureData.insertRows(0, [
[date, iT, oT, iDP, oDP]
]);
relativeHumidityData.insertRows(0, [
[date, iRH, oRH]
]);
absoluteHumidityData.insertRows(0, [
[date, iAH, oAH]
]);
needData.insertRows(0, [
[date, n, minimumNeedForOn, maximumNeedForOff]
]);
}
else {
temperatureData.addRows([
[date, iT, oT, iDP, oDP]
]);
relativeHumidityData.addRows([
[date, iRH, oRH]
]);
absoluteHumidityData.addRows([
[date, iAH, oAH]
]);
needData.addRows([
[date, n, minimumNeedForOn, maximumNeedForOff]
]);
}
}
var dTD = document.createElement("td");
dTD.textContent = formatDate(d);
var iTTD = document.createElement("td");
iTTD.textContent = round(iT, 1);
var iRHTD = document.createElement("td");
iRHTD.textContent = round(iRH, 1);
var iAHTD = document.createElement("td");
iAHTD.textContent = round(iAH, 2);
var iDPTD = document.createElement("td");
iDPTD.textContent = round(iDP, 1);
var oTTD = document.createElement("td");
oTTD.textContent = round(oT, 1);
var oRHTD = document.createElement("td");
oRHTD.textContent = round(oRH, 1);
var oAHTD = document.createElement("td");
oAHTD.textContent = round(oAH, 2);
var oDPTD = document.createElement("td");
oDPTD.textContent = round(oDP, 1);
var nTD = document.createElement("td");
nTD.textContent = round(n, 2);
if (n >= minimumNeedForOn)
nTD.style.backgroundColor = '#D98880';
else if (n > maximumNeedForOff)
nTD.style.backgroundColor = '#F7DC6F';
else
nTD.style.backgroundColor = '#7DCEA0';
var sTD = document.createElement("td");
if (s)
sTD.textContent = "on";
else
sTD.textContent = "off";
var tr = document.createElement("tr");
tr.appendChild(dTD);
tr.appendChild(iTTD);
tr.appendChild(iRHTD);
tr.appendChild(iAHTD);
tr.appendChild(iDPTD);
tr.appendChild(oTTD);
tr.appendChild(oRHTD);
tr.appendChild(oAHTD);
tr.appendChild(oDPTD);
tr.appendChild(nTD);
tr.appendChild(sTD);
return tr;
}
connection.on("S", function (d, iT, oT, iRH, oRH, iAH, oAH, iDP, oDP, n) {
var tr = getTR(d, iT, oT, iRH, oRH, iAH, oAH, iDP, oDP, n, true, true);
var tableBody = document.getElementById("tableBody");
tableBody.insertBefore(tr, tableBody.firstChild);
if (synced) {
var s = true;
if (iRH < 0) { s = false; iRH = 0 - iRH; }
if (s)
onCount = onCount + 1;
else
offCount = offCount + 1;
document.getElementById('onPercentage').innerText = Math.round((onCount / (onCount + offCount)) * 10000) / 100;
}
drawCharts();
});
connection.on("R", function (onD, onC, offC) {
document.getElementById("spinner").style.display = 'none';
var x = document.getElementsByClassName("chart");
var i;
for (i = 0; i < x.length; i++) {
x[i].style.display = 'inline-block';
}
onDate = new Date(onD);
onCount = onC;
offCount = offC;
document.getElementById('onPercentage').innerText = Math.round((onCount / (onCount + offCount)) * 10000) / 100;
document.getElementById('onDate').innerText = formatDate(onDate);
document.getElementById('stats').style.display = 'block';
synced = true;
drawCharts();
});
connection.on("L", function (d, iT, oT, iRH, oRH, iAH, oAH, iDP, oDP, n) {
var tr = getTR(d, iT, oT, iRH, oRH, iAH, oAH, iDP, oDP, n, false, false);
tr.setAttribute("style", "background-color: #F0E68C");
var tableHead = document.getElementById("tableHead");
if (tableHead.children.length === 2)
tableHead.appendChild(tr);
else
tableHead.children[2].replaceWith(tr);
});
connection.on("F", function (d, iT, oT, iRH, oRH, iAH, oAH, iDP, oDP, n) {
var tr = getTR(d, iT, oT, iRH, oRH, iAH, oAH, iDP, oDP, n, true, false);
var tableBody = document.getElementById("tableBody");
tableBody.appendChild(tr);
});
document.getElementById("auto").addEventListener("click", function (event) {
connection.invoke("Auto", 0).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
document.getElementById("overrideOn").addEventListener("click", function (event) {
connection.invoke("OverrideOn", 0).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
document.getElementById("overrideOff").addEventListener("click", function (event) {
connection.invoke("OverrideOff", 0).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
document.getElementById("restart").addEventListener("click", function (event) {
connection.invoke("Restart", 0).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
async function start() {
try {
await connection.start();
connection.invoke("Sync", lastDateSynced).catch(function (err) {
return console.error(err.toString());
});
document.getElementById("auto").disabled = false;
document.getElementById("overrideOn").disabled = false;
document.getElementById("overrideOff").disabled = false;
document.getElementById("restart").disabled = false;
document.getElementById("spinnerText").innerText = 'Loading charts...';
} catch (err) {
console.log(err);
setTimeout(() => start(), 5000);
}
};
connection.onclose(async () => {
var bodyNode = document.getElementById("tableBody");
var footerNode = document.getElementById("tableFooter");
while (bodyNode.children.length > 0) {
footerNode.insertBefore(bodyNode.lastChild, footerNode.firstChild);
bodyNode.deleteRow(bodyNode.children.length - 1);
}
document.getElementById("auto").disabled = true;
document.getElementById("overrideOn").disabled = true;
document.getElementById("overrideOff").disabled = true;
document.getElementById("restart").disabled = true;
document.getElementById("spinner").style.display = 'block';
document.getElementById('stats').style.display = 'none';
document.getElementById("spinnerText").innerText = 'Reconnecting...';
synced = false;
var x = document.getElementsByClassName("chart");
var i;
for (i = 0; i < x.length; i++) {
x[i].style.display = 'none';
}
await start();
});
//start();
function clearData() {
temperatureData = new google.visualization.DataTable();
relativeHumidityData = new google.visualization.DataTable();
absoluteHumidityData = new google.visualization.DataTable();
needData = new google.visualization.DataTable();
temperatureData.addColumn('date', 'X');
temperatureData.addColumn('number', 'Inside Temp.');
temperatureData.addColumn('number', 'Outside Temp.');
temperatureData.addColumn('number', 'Inside Dew Point');
temperatureData.addColumn('number', 'Outside Dew Point');
relativeHumidityData.addColumn('date', 'X');
relativeHumidityData.addColumn('number', 'Inside Relative Humidity');
relativeHumidityData.addColumn('number', 'Outside Relative Humidity');
absoluteHumidityData.addColumn('date', 'X');
absoluteHumidityData.addColumn('number', 'Inside Absolute Humidity');
absoluteHumidityData.addColumn('number', 'Outside Absolute Humidity');
needData.addColumn('date', 'X');
needData.addColumn('number', 'Need');
needData.addColumn('number', 'Minimum Need For On');
needData.addColumn('number', 'Maximum Need For Off');
}
function drawLineColors() {
clearData();
temperatureChart = new google.visualization.LineChart(document.getElementById('temperaturechart_div'));
relativeHumidityChart = new google.visualization.LineChart(document.getElementById('relativehumiditychart_div'));
absoluteHumidityChart = new google.visualization.LineChart(document.getElementById('absolutehumiditychart_div'));
needChart = new google.visualization.LineChart(document.getElementById('needchart_div'));
date_formatter = new google.visualization.DateFormat({
pattern: "yyyy-MM-dd HH:mm:ss"
});
temperature_formatter = new google.visualization.NumberFormat({
pattern: "#.#°C"
});
percentage_formatter = new google.visualization.NumberFormat({
pattern: '#.#\'%\''
});
absoluteHumidity_formatter = new google.visualization.NumberFormat({
pattern: "#.##g/m³"
});
need_formatter = new google.visualization.NumberFormat({
pattern: "#.##"
});
needColor_formatter = new google.visualization.ColorFormat();
needColor_formatter.addRange(null, 17.0, '#7DCEA0', 'white');
needColor_formatter.addRange(17.0, 20.5, '#F7DC6F', 'white');
needColor_formatter.addRange(20.5, null, '#D98880', 'white');
start();
}
var date_formatter;
var temperature_formatter;
var percentage_formatter;
var absoluteHumidity_formatter;
var need_formatter;
var needColor_formatter;
function drawCharts() {
date_formatter.format(temperatureData, 0);
date_formatter.format(relativeHumidityData, 0);
date_formatter.format(absoluteHumidityData, 0);
date_formatter.format(needData, 0);
temperature_formatter.format(temperatureData, 1);
temperature_formatter.format(temperatureData, 2);
temperature_formatter.format(temperatureData, 3);
temperature_formatter.format(temperatureData, 4);
percentage_formatter.format(relativeHumidityData, 1);
percentage_formatter.format(relativeHumidityData, 2);
absoluteHumidity_formatter.format(absoluteHumidityData, 1);
absoluteHumidity_formatter.format(absoluteHumidityData, 2);
need_formatter.format(needData, 1);
needColor_formatter.format(needData, 1);
temperatureData.sort({ column: 0, desc: true });
relativeHumidityData.sort({ column: 0, desc: true });
absoluteHumidityData.sort({ column: 0, desc: true });
needData.sort({ column: 0, desc: true });
temperatureChart.clearChart();
temperatureChart.draw(temperatureData, temperatureOptions);
relativeHumidityChart.clearChart();
relativeHumidityChart.draw(relativeHumidityData, relativeHumidityOptions);
absoluteHumidityChart.clearChart();
absoluteHumidityChart.draw(absoluteHumidityData, absoluteHumidityOptions);
needChart.clearChart();
needChart.draw(needData, needOptions);
}
答案 0 :(得分:1)
删除'line'
程序包,只需要'corechart'
'line'
用于物料折线图-> google.charts.Line
您没有使用。
您使用的是经典图表或核心图表-> google.visualization.LineChart
'line'
软件包似乎引起闪烁,
参见以下工作片段...
带有'line'
软件包-闪烁
google.charts.load('current', {
packages: ['corechart', 'line']
}).then(function () {
var temperatureData;
var temperatureChart;
var temperatureOptions = {
fontName: 'Roboto',
hAxis: {
title: 'Time',
format: 'HH:mm',
},
vAxis: {
title: 'Temperature (℃)',
},
colors: ['#7892c2', '#4e6096', '#a52714', '#097138'],
legend: {
position: 'top',
}
};
temperatureData = new google.visualization.DataTable();
temperatureData.addColumn('date', 'X');
temperatureData.addColumn('number', 'Inside Temp.');
temperatureData.addColumn('number', 'Outside Temp.');
temperatureData.addColumn('number', 'Inside Dew Point');
temperatureData.addColumn('number', 'Outside Dew Point');
var oneDay = (24 * 60 * 60 * 1000);
var index = (new Date((new Date()).getTime() - (oneDay * 365.25))).getTime();
var rowDate = new Date(index);
temperatureData.addRow([rowDate, Math.floor(Math.random() * 60), Math.floor(Math.random() * 80), Math.floor(Math.random() * 30), Math.floor(Math.random() * 50)]);
temperatureChart = new google.visualization.LineChart(document.getElementById('temperaturechart_div'));
google.visualization.events.addListener(temperatureChart, 'ready', function () {
setTimeout(function () {
index = index + oneDay;
rowDate = new Date(index);
temperatureData.addRow([rowDate, Math.floor(Math.random() * 60), Math.floor(Math.random() * 80), Math.floor(Math.random() * 30), Math.floor(Math.random() * 50)]);
temperatureChart.clearChart();
temperatureChart.draw(temperatureData, temperatureOptions);
}, 3000);
});
temperatureChart.draw(temperatureData, temperatureOptions);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div class="chart" id="temperaturechart_div"></div>
没有'line'
软件包-不闪烁
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var temperatureData;
var temperatureChart;
var temperatureOptions = {
fontName: 'Roboto',
hAxis: {
title: 'Time',
format: 'HH:mm',
},
vAxis: {
title: 'Temperature (℃)',
},
colors: ['#7892c2', '#4e6096', '#a52714', '#097138'],
legend: {
position: 'top',
}
};
temperatureData = new google.visualization.DataTable();
temperatureData.addColumn('date', 'X');
temperatureData.addColumn('number', 'Inside Temp.');
temperatureData.addColumn('number', 'Outside Temp.');
temperatureData.addColumn('number', 'Inside Dew Point');
temperatureData.addColumn('number', 'Outside Dew Point');
var oneDay = (24 * 60 * 60 * 1000);
var index = (new Date((new Date()).getTime() - (oneDay * 365.25))).getTime();
var rowDate = new Date(index);
temperatureData.addRow([rowDate, Math.floor(Math.random() * 60), Math.floor(Math.random() * 80), Math.floor(Math.random() * 30), Math.floor(Math.random() * 50)]);
temperatureChart = new google.visualization.LineChart(document.getElementById('temperaturechart_div'));
google.visualization.events.addListener(temperatureChart, 'ready', function () {
setTimeout(function () {
index = index + oneDay;
rowDate = new Date(index);
temperatureData.addRow([rowDate, Math.floor(Math.random() * 60), Math.floor(Math.random() * 80), Math.floor(Math.random() * 30), Math.floor(Math.random() * 50)]);
temperatureChart.clearChart();
temperatureChart.draw(temperatureData, temperatureOptions);
}, 3000);
});
temperatureChart.draw(temperatureData, temperatureOptions);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div class="chart" id="temperaturechart_div"></div>