悬停时,Chartjs 折线图在新旧数据之间闪烁
Chartjs Line Chart flickers between old and new data when hovering
我的问题不是制作图表,而是当我为开始频率和结束频率输入新值时,它们是我的 x 轴数组 的第一个和最后一个值调用 getFreq() 后,当我悬停时图表出现故障,在旧数据和新数据之间来回切换。谁能帮我弄清楚如何删除旧数据和 make/update 到图表不闪烁的新图表?我的代码如下所示。
let Conductivity = document.getElementById('Conductivity');
let StartFreq = document.getElementById('StartFreq');
let StopFreq = document.getElementById('StopFreq');
let a = document.getElementById('a');
let b = document.getElementById('b');
let unitInch = document.getElementById('unitInch');
let test = document.getElementById('test');
let diameter = document.getElementById('Diameter');
let ctx = document.getElementById('myChart').getContext('2d');
function generateLabels(){
// To generate the xa xis intervals
let xaxis = [];
for (let i = 0; i <= 10; i++) {
let valToAppend = Math.round((parseFloat(StartFreq.value) + (parseFloat(StopFreq.value)-parseFloat(StartFreq.value)) / 10 * i)*100)/100;
if (valToAppend <= parseFloat(StopFreq.value)){
xaxis.push(valToAppend)
}
}
return xaxis
}
function getFreq(){
let x = generateLabels();
let freq = [];
let start = x[0];
freq.push(start);
let end = x[x.length - 1];
for (let i=0; i < 4 * (end-start);i++){
let lastfreq = freq[freq.length - 1];
freq.push(lastfreq + 0.25)
}
// let rklen = freq.length;
return freq
}
function getRS(){
let RS = [];
let freq = getFreq();
freq.forEach(element =>{
let RStoAppend = Math.sqrt((2*Math.PI*(Math.pow(10,9)*element)*(4*Math.PI*Math.pow(10,-7)))/(2*(parseFloat(Conductivity.value)*Math.pow(10,7)))) ;
RS.push(RStoAppend)
});
return RS
}
function getRK(){
let RK = [];
let freq = getFreq();
freq.forEach(element => {
let RKtoappend = (2*Math.PI*(element * Math.pow(10,9))) / (3* Math.pow(10,8));
RK.push(RKtoappend)
});
return RK
}
function getRbeta(){
let Rbeta = [];
let RK = getRK();
RK.forEach(element => {
let Rbetatoappend = Math.sqrt(Math.pow(element,2) - Math.pow((Math.PI/(parseFloat(a.value)*25.4/1000)),2));
Rbeta.push(Rbetatoappend);
});
return Rbeta;
}
function getRatte(){
let Ratte = [];
let RS = getRS();
let RK = getRK();
let Rbeta = getRbeta();
for (let i = 0; i < RS.length ;i++){
let Rattetoappend = RS[i]*(2*(25.4/1000*parseFloat(b.value))*Math.pow(Math.PI,2)+Math.pow((parseFloat(a.value)*25.4/1000),3)*Math.pow(RK[i],2))/(Math.pow((parseFloat(a.value)*25.4/1000),3)*(25.4/1000*parseFloat(b.value))*Rbeta[i]*RK[i]*377)/(1000/25.4);
Ratte.push(Rattetoappend);
}
// test.innerHTML = '<td id="test">' + Ratte + '<td>';
return Ratte
}
function getRTE10(){
let RTE10 = [];
let Ratte = getRatte();
Ratte.forEach(element => {
if (isNaN(-20*Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))) {
RTE10.push(0)
}
else {
RTE10.push(-20 * Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))
}
});
return RTE10
}
//////////////////////// For CTE11/////////////
function getk(){
let k = [];
let freq = getFreq();
freq.forEach(element => {
k.push(2*Math.PI*element*Math.pow(10,9)/(3*Math.pow(10,8)))
});
return k
}
function getbeta(){
let beta = [];
let k = getk();
k.forEach(element => {
beta.push(Math.sqrt(Math.pow(element,2)-Math.pow((1.8412/(parseFloat(diameter.value)/2*25.4/1000)),2)))
});
return beta
}
function getTE11_1(){
let TE11_1 = [];
let k = getk();
let rs = getRS();
let beta = getbeta();
for (let i = 0; i < rs.length ;i++){
TE11_1.push(rs[i]*(Math.pow((1.8412/(parseFloat(diameter.value)/2*25.4/1000)),2)+Math.pow(k[i],2)/(Math.pow(1.8414,2)-1))/((parseFloat(diameter.value)/2*25.4/1000)*k[i]*beta[i]*377)/(1000/25.4));
}
return TE11_1
}
function getCTE11(){
let CTE11 = [];
let TE11_1 = getTE11_1();
TE11_1.forEach(element => {
if (isNaN(-20 * Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))) {
CTE11.push(0)
}
else {
CTE11.push(-20 * Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))
}
});
// test.innerHTML = '<td id="test">' + CTE11 + '<td>';
return CTE11
}
function getTM01(){
let TM01 = [];
let rs = getRS();
let freq = getFreq();
for (let i = 0; i < rs.length ;i++){
TM01.push(rs[i]/((parseFloat(diameter.value)/2 *25.4/1000)*377*Math.sqrt(1-Math.pow(((2.4049/(2*Math.PI*parseFloat(diameter.value)/2 *25.4/1000)*0.3)*Math.pow(10,9)/(freq[i]*Math.pow(10,9))),2)))/(1000/25.4));
}
return TM01
}
function getCTM01(){
let CTM01 = [];
let TM01 = getTM01();
TM01.forEach(element => {
if (isNaN(-20 * Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))) {
CTM01.push(0)
}
else {
CTM01.push(-20 * Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))
}
});
return CTM01
}
function getAt2(){
let at2 = [];
let freq = getFreq();
freq.forEach(element =>{
at2.push(Math.pow(((3.8318/(2*Math.PI*parseFloat(diameter.value)/2 *25.4/1000)*0.3)*Math.pow(10,9)/(element*Math.pow(10,9))),2)+1/(Math.pow(3.8318,2)-1))
});
return at2
}
function getAt1(){
let at1 = [];
let freq = getFreq();
let rs = getRS();
for (let i = 0; i < rs.length ;i++){
at1.push(rs[i]/(parseFloat(diameter.value)/2 *25.4/1000*377*Math.sqrt(1-Math.pow(((3.8318/(2*Math.PI*parseFloat(diameter.value)/2 *25.4/1000)*0.3)*Math.pow(10,9)/(freq[i]*Math.pow(10,9))),2)))/(1000/25.4));
}
return at1
}
function getCTE01(){
let CTE01 = [];
let at1 = getAt1();
let at2 = getAt2();
for(let i = 0;i < at1.length; i++){
if (isNaN((-20*Math.log10(Math.exp(-(at1[i]*at2[i])))*parseFloat(unitInch.value)))) {
CTE01.push(0)
}
else {
CTE01.push(-20 * Math.log10(Math.exp(-(at1[i] * at2[i]))) * parseFloat(unitInch.value))
}
}
return CTE01
}
function getdata(){
let data =[];
let xaxis = getFreq();
let RTE10 = getRTE10();
let CTE11 = getCTE11();
let CTM01 = getCTM01();
let CTE01 = getCTE01();
data.push(xaxis,RTE10,CTE11,CTM01,CTE01);
return data
}
function draw_chart(data) {
let chart = new Chart(ctx, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
labels: data[0],
datasets: [{
label: 'R-TE10',
data: data[1],
pointStyle : 'line',
backgroundColor: 'transparent',
borderColor: 'blue',
pointRadius: '0'
},{
label: 'C-TE11',
data: data[2],
pointStyle : 'line',
backgroundColor: 'transparent',
borderColor: 'orange',
pointRadius: '0'
},{
label: 'C-TM01',
data: data[3],
pointStyle : 'line',
backgroundColor: 'transparent',
borderColor: 'green',
pointRadius: '0'
},{
label: 'C-TE01',
data: data[4],
pointStyle : 'line',
backgroundColor: 'transparent',
borderColor: 'red',
pointRadius: '0'
}]
},
// Configuration options go here
options: {
responsive : true,
scales: {
xAxes :[{
ticks: {
min: StartFreq,
max: StopFreq,
suggestedMin: StartFreq,
suggestedMax: StopFreq,
stepSize: 0.25,
}
}],
yAxes: [{
ticks: {
min:0,
max:10,
suggestedMin: 0,
suggestedMax: 10,
maxTicksLimit: 11,
stepSize : 1,
beginAtZero: true,
}
}]
}
}
});
}
function generateChart() {
// removeData(chart);
let data = getdata();
draw_chart(data);
}
HTML
<table class="inner">
<tr class="inner">
<td class="inner"> Attenuation (air) /</td>
<td class="inner"> <input class="numInput" type="number" id="unitInch"/></td>
<td class="inner">(in inches)</td>
</tr>
<tr class="inner">
<td class="inner" colspan="2">Rectangular WG</td>
<td class="inner">Circular WG</td>
<td class="inner">Material</td>
</tr>
<tr class="inner">
<td class="inner">a (inch)</td>
<td class="inner">b (inch)</td>
<td class="inner">Diameter (inch)</td>
<td class="inner">Conductivity ( x 10<sup>7</sup> S/m)</td>
<td class="inner">Start Freq (GHz)</td>
<td class="inner">Stop Freq (GHz)</td>
</tr>
<tr class="inner">
<td class="inner"><input class="numInput" type="number" id='a'/></td>
<td class="inner"><input class="numInput" type="number" id="b"/></td>
<td class="inner"><input class="numInput" type="number" id="Diameter"/></td>
<td class="inner"><input class="numInput" type="number" id="Conductivity"/></td>
<td class="inner"><input class="numInput" type="number" id="StartFreq"/></td>
<td class="inner"><input class="numInput" type="number" id="StopFreq"/></td>
</tr>
</table>
<button onclick="generateChart()"><strong>Generate Chart</strong></button>
<div id="chartsize">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.js"></script>
<script src="js/chart.js"></script>
** 顺便说一句,我的图表在我第一次加载页面时完全正常,然后当我更新时,图表在悬停时疯狂闪烁。
我添加了更多代码,以便你们可以重新创建图表并弄清楚。请忽略糟糕的风格,我是网络开发的新手......
**
这似乎是 Chart.js 的一个常见问题。典型的建议解决方案是销毁 chart
实例,或者删除 canvas
元素并在图表更新时创建一个新元素。
对于第一种可能的解决方案,您可以尝试对图表对象调用 destroy()
。例如,如果您的图表对象是 chart
,您可以调用 chart.destroy();
。来自 documentation:
Use this to destroy any chart instances that are created. This will
clean up any references stored to the chart object within Chart.js,
along with any associated event listeners attached by Chart.js. This
must be called before the canvas is reused for a new chart.
然而,这似乎并不总是奏效。当我用您的代码测试它时,删除和创建 canvas
元素似乎有效。您可以使用如下所示的函数,并在您单击 "Generate Chart" 按钮时调用它:
function resetCanvas (){
$("canvas").remove();
$("#chartsize").append('<canvas id="myChart"><canvas>');
canvas = document.querySelector("#myChart");
ctx = canvas.getContext("2d");
};
请注意,您可能需要设置图表容器的高度和宽度。为简单起见,我将 jQuery 用于此功能。但如果需要,您可以使用 vanilla JS 重现它。
请参阅此处的 fiddle 以获取使用您的代码的示例:https://jsfiddle.net/fL1rd3wp/1/
我的问题不是制作图表,而是当我为开始频率和结束频率输入新值时,它们是我的 x 轴数组 的第一个和最后一个值调用 getFreq() 后,当我悬停时图表出现故障,在旧数据和新数据之间来回切换。谁能帮我弄清楚如何删除旧数据和 make/update 到图表不闪烁的新图表?我的代码如下所示。
let Conductivity = document.getElementById('Conductivity');
let StartFreq = document.getElementById('StartFreq');
let StopFreq = document.getElementById('StopFreq');
let a = document.getElementById('a');
let b = document.getElementById('b');
let unitInch = document.getElementById('unitInch');
let test = document.getElementById('test');
let diameter = document.getElementById('Diameter');
let ctx = document.getElementById('myChart').getContext('2d');
function generateLabels(){
// To generate the xa xis intervals
let xaxis = [];
for (let i = 0; i <= 10; i++) {
let valToAppend = Math.round((parseFloat(StartFreq.value) + (parseFloat(StopFreq.value)-parseFloat(StartFreq.value)) / 10 * i)*100)/100;
if (valToAppend <= parseFloat(StopFreq.value)){
xaxis.push(valToAppend)
}
}
return xaxis
}
function getFreq(){
let x = generateLabels();
let freq = [];
let start = x[0];
freq.push(start);
let end = x[x.length - 1];
for (let i=0; i < 4 * (end-start);i++){
let lastfreq = freq[freq.length - 1];
freq.push(lastfreq + 0.25)
}
// let rklen = freq.length;
return freq
}
function getRS(){
let RS = [];
let freq = getFreq();
freq.forEach(element =>{
let RStoAppend = Math.sqrt((2*Math.PI*(Math.pow(10,9)*element)*(4*Math.PI*Math.pow(10,-7)))/(2*(parseFloat(Conductivity.value)*Math.pow(10,7)))) ;
RS.push(RStoAppend)
});
return RS
}
function getRK(){
let RK = [];
let freq = getFreq();
freq.forEach(element => {
let RKtoappend = (2*Math.PI*(element * Math.pow(10,9))) / (3* Math.pow(10,8));
RK.push(RKtoappend)
});
return RK
}
function getRbeta(){
let Rbeta = [];
let RK = getRK();
RK.forEach(element => {
let Rbetatoappend = Math.sqrt(Math.pow(element,2) - Math.pow((Math.PI/(parseFloat(a.value)*25.4/1000)),2));
Rbeta.push(Rbetatoappend);
});
return Rbeta;
}
function getRatte(){
let Ratte = [];
let RS = getRS();
let RK = getRK();
let Rbeta = getRbeta();
for (let i = 0; i < RS.length ;i++){
let Rattetoappend = RS[i]*(2*(25.4/1000*parseFloat(b.value))*Math.pow(Math.PI,2)+Math.pow((parseFloat(a.value)*25.4/1000),3)*Math.pow(RK[i],2))/(Math.pow((parseFloat(a.value)*25.4/1000),3)*(25.4/1000*parseFloat(b.value))*Rbeta[i]*RK[i]*377)/(1000/25.4);
Ratte.push(Rattetoappend);
}
// test.innerHTML = '<td id="test">' + Ratte + '<td>';
return Ratte
}
function getRTE10(){
let RTE10 = [];
let Ratte = getRatte();
Ratte.forEach(element => {
if (isNaN(-20*Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))) {
RTE10.push(0)
}
else {
RTE10.push(-20 * Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))
}
});
return RTE10
}
//////////////////////// For CTE11/////////////
function getk(){
let k = [];
let freq = getFreq();
freq.forEach(element => {
k.push(2*Math.PI*element*Math.pow(10,9)/(3*Math.pow(10,8)))
});
return k
}
function getbeta(){
let beta = [];
let k = getk();
k.forEach(element => {
beta.push(Math.sqrt(Math.pow(element,2)-Math.pow((1.8412/(parseFloat(diameter.value)/2*25.4/1000)),2)))
});
return beta
}
function getTE11_1(){
let TE11_1 = [];
let k = getk();
let rs = getRS();
let beta = getbeta();
for (let i = 0; i < rs.length ;i++){
TE11_1.push(rs[i]*(Math.pow((1.8412/(parseFloat(diameter.value)/2*25.4/1000)),2)+Math.pow(k[i],2)/(Math.pow(1.8414,2)-1))/((parseFloat(diameter.value)/2*25.4/1000)*k[i]*beta[i]*377)/(1000/25.4));
}
return TE11_1
}
function getCTE11(){
let CTE11 = [];
let TE11_1 = getTE11_1();
TE11_1.forEach(element => {
if (isNaN(-20 * Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))) {
CTE11.push(0)
}
else {
CTE11.push(-20 * Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))
}
});
// test.innerHTML = '<td id="test">' + CTE11 + '<td>';
return CTE11
}
function getTM01(){
let TM01 = [];
let rs = getRS();
let freq = getFreq();
for (let i = 0; i < rs.length ;i++){
TM01.push(rs[i]/((parseFloat(diameter.value)/2 *25.4/1000)*377*Math.sqrt(1-Math.pow(((2.4049/(2*Math.PI*parseFloat(diameter.value)/2 *25.4/1000)*0.3)*Math.pow(10,9)/(freq[i]*Math.pow(10,9))),2)))/(1000/25.4));
}
return TM01
}
function getCTM01(){
let CTM01 = [];
let TM01 = getTM01();
TM01.forEach(element => {
if (isNaN(-20 * Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))) {
CTM01.push(0)
}
else {
CTM01.push(-20 * Math.log10(Math.exp(-element)) * parseFloat(unitInch.value))
}
});
return CTM01
}
function getAt2(){
let at2 = [];
let freq = getFreq();
freq.forEach(element =>{
at2.push(Math.pow(((3.8318/(2*Math.PI*parseFloat(diameter.value)/2 *25.4/1000)*0.3)*Math.pow(10,9)/(element*Math.pow(10,9))),2)+1/(Math.pow(3.8318,2)-1))
});
return at2
}
function getAt1(){
let at1 = [];
let freq = getFreq();
let rs = getRS();
for (let i = 0; i < rs.length ;i++){
at1.push(rs[i]/(parseFloat(diameter.value)/2 *25.4/1000*377*Math.sqrt(1-Math.pow(((3.8318/(2*Math.PI*parseFloat(diameter.value)/2 *25.4/1000)*0.3)*Math.pow(10,9)/(freq[i]*Math.pow(10,9))),2)))/(1000/25.4));
}
return at1
}
function getCTE01(){
let CTE01 = [];
let at1 = getAt1();
let at2 = getAt2();
for(let i = 0;i < at1.length; i++){
if (isNaN((-20*Math.log10(Math.exp(-(at1[i]*at2[i])))*parseFloat(unitInch.value)))) {
CTE01.push(0)
}
else {
CTE01.push(-20 * Math.log10(Math.exp(-(at1[i] * at2[i]))) * parseFloat(unitInch.value))
}
}
return CTE01
}
function getdata(){
let data =[];
let xaxis = getFreq();
let RTE10 = getRTE10();
let CTE11 = getCTE11();
let CTM01 = getCTM01();
let CTE01 = getCTE01();
data.push(xaxis,RTE10,CTE11,CTM01,CTE01);
return data
}
function draw_chart(data) {
let chart = new Chart(ctx, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
labels: data[0],
datasets: [{
label: 'R-TE10',
data: data[1],
pointStyle : 'line',
backgroundColor: 'transparent',
borderColor: 'blue',
pointRadius: '0'
},{
label: 'C-TE11',
data: data[2],
pointStyle : 'line',
backgroundColor: 'transparent',
borderColor: 'orange',
pointRadius: '0'
},{
label: 'C-TM01',
data: data[3],
pointStyle : 'line',
backgroundColor: 'transparent',
borderColor: 'green',
pointRadius: '0'
},{
label: 'C-TE01',
data: data[4],
pointStyle : 'line',
backgroundColor: 'transparent',
borderColor: 'red',
pointRadius: '0'
}]
},
// Configuration options go here
options: {
responsive : true,
scales: {
xAxes :[{
ticks: {
min: StartFreq,
max: StopFreq,
suggestedMin: StartFreq,
suggestedMax: StopFreq,
stepSize: 0.25,
}
}],
yAxes: [{
ticks: {
min:0,
max:10,
suggestedMin: 0,
suggestedMax: 10,
maxTicksLimit: 11,
stepSize : 1,
beginAtZero: true,
}
}]
}
}
});
}
function generateChart() {
// removeData(chart);
let data = getdata();
draw_chart(data);
}
HTML
<table class="inner">
<tr class="inner">
<td class="inner"> Attenuation (air) /</td>
<td class="inner"> <input class="numInput" type="number" id="unitInch"/></td>
<td class="inner">(in inches)</td>
</tr>
<tr class="inner">
<td class="inner" colspan="2">Rectangular WG</td>
<td class="inner">Circular WG</td>
<td class="inner">Material</td>
</tr>
<tr class="inner">
<td class="inner">a (inch)</td>
<td class="inner">b (inch)</td>
<td class="inner">Diameter (inch)</td>
<td class="inner">Conductivity ( x 10<sup>7</sup> S/m)</td>
<td class="inner">Start Freq (GHz)</td>
<td class="inner">Stop Freq (GHz)</td>
</tr>
<tr class="inner">
<td class="inner"><input class="numInput" type="number" id='a'/></td>
<td class="inner"><input class="numInput" type="number" id="b"/></td>
<td class="inner"><input class="numInput" type="number" id="Diameter"/></td>
<td class="inner"><input class="numInput" type="number" id="Conductivity"/></td>
<td class="inner"><input class="numInput" type="number" id="StartFreq"/></td>
<td class="inner"><input class="numInput" type="number" id="StopFreq"/></td>
</tr>
</table>
<button onclick="generateChart()"><strong>Generate Chart</strong></button>
<div id="chartsize">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.js"></script>
<script src="js/chart.js"></script>
** 顺便说一句,我的图表在我第一次加载页面时完全正常,然后当我更新时,图表在悬停时疯狂闪烁。 我添加了更多代码,以便你们可以重新创建图表并弄清楚。请忽略糟糕的风格,我是网络开发的新手...... **
这似乎是 Chart.js 的一个常见问题。典型的建议解决方案是销毁 chart
实例,或者删除 canvas
元素并在图表更新时创建一个新元素。
对于第一种可能的解决方案,您可以尝试对图表对象调用 destroy()
。例如,如果您的图表对象是 chart
,您可以调用 chart.destroy();
。来自 documentation:
Use this to destroy any chart instances that are created. This will clean up any references stored to the chart object within Chart.js, along with any associated event listeners attached by Chart.js. This must be called before the canvas is reused for a new chart.
然而,这似乎并不总是奏效。当我用您的代码测试它时,删除和创建 canvas
元素似乎有效。您可以使用如下所示的函数,并在您单击 "Generate Chart" 按钮时调用它:
function resetCanvas (){
$("canvas").remove();
$("#chartsize").append('<canvas id="myChart"><canvas>');
canvas = document.querySelector("#myChart");
ctx = canvas.getContext("2d");
};
请注意,您可能需要设置图表容器的高度和宽度。为简单起见,我将 jQuery 用于此功能。但如果需要,您可以使用 vanilla JS 重现它。
请参阅此处的 fiddle 以获取使用您的代码的示例:https://jsfiddle.net/fL1rd3wp/1/