为什么我的图表更新功能似乎没有起作用?

huangapple go评论74阅读模式
英文:

why my chart update function doest seem to do anything?

问题

Here's the translated content you requested:

我不知道为什么在 destroy() 正常工作的情况下图表更新不起作用也许是因为它在函数中并且稍后被导出我不知道

let labelArr = [];
let dataArr = [];

let data = {
  labels: labelArr,
  datasets: [
    {
      data: dataArr,
      label: "# of Amount",
      borderWidth: 1,
      borderColor: "#01a001",
      backgroundColor: "#01a001",
    },
  ],
};

let config = {
  type: "line",
  data,
  options: {
    scales: {
      y: {
        beginAtZero: false,
      },
    },
  },
};

function initChart(currentAccount) {
  currentAccount.transactions.forEach((t) => {
    const dateReady = currentUser.dateCreator(t.date);
    labelArr.push(dateReady);
    dataArr.push(t.amount);
  });
}

let chartUI = new Chart(document.getElementById("chart"), config);

function destroy(chartUI) {
  chartUI.data.datasets[0].data = [];
  chartUI.data.labels = [];
  labelArr = [];
  dataArr = [];
  chartUI.destroy();
}

function render(currentAccount, chartUI) {
  chartUI = new Chart(document.getElementById("chart"), config);

  currentAccount.transactions.forEach((t) => {
    const dateReady = currentUser.dateCreator(t.date);
    labelArr.push(dateReady);
    dataArr.push(t.amount);

    chartUI.data.datasets[0].data = dataArr;
    chartUI.data.labels = labelArr;
  });
  chartUI.update();
}

我要提醒您,这段代码中可能涉及到特定上下文和函数,我只能提供翻译,无法理解其完整含义。

英文:

i dont know why chart update doesnt work when destroy() is working fine.maybe it is becouse it is in functions and it is later exported idk


let labelArr = [];
let dataArr = [];
let data = {
labels: labelArr,
datasets: [
{
data: dataArr,
label: "# of Amount",
borderWidth: 1,
borderColor: "#01a001",
backgroundColor: "#01a001",
},
],
};
let config = {
type: "line",
data,
options: {
scales: {
y: {
beginAtZero: false,
},
},
},
};
function initChart(currentAccount) {
currentAccount.transactions.forEach((t) => {
const dateReady = currentUser.dateCreator(t.date);
labelArr.push(dateReady);
dataArr.push(t.amount);
});
}
let chartUI = new Chart(document.getElementById("chart"), config);
function destroy(chartUI) {
chartUI.data.datasets[0].data = [];
chartUI.data.labels = [];
labelArr = [];
dataArr = [];
chartUI.destroy();
}
function render(currentAccount, chartUI) {
chartUI = new Chart(document.getElementById("chart"), config);
currentAccount.transactions.forEach((t) => {
const dateReady = currentUser.dateCreator(t.date);
labelArr.push(dateReady);
dataArr.push(t.amount);
chartUI.data.datasets[0].data = dataArr;
chartUI.data.labels = labelArr;
});
chartUI.update();
}

i want to update it on click like that:

export const initSettings = function (currentAccount) {
initChart(currentAccount);
};
export const updateUI = function (currentAccount) {
destroy(chartUI);
render(currentAccount, chartUI);
};

i expect to update but instead of it i get canvas is already in use

  Lorem ipsum dolor sit amet consectetur adipisicing elit. Ab eius esse repudiandae maxime, velit expedita id temporibus dicta consequatur eum.

i expect to update but instead of it i get canvas is already in use

答案1

得分: 1

以下是您代码中需要翻译的部分:

"你的代码中的错误在于render函数。你将chartUI作为参数传递给函数,然后在函数内部将其赋值为new Chart。因此,在函数内部和外部的chartUI的值是不同的(你可能假设分配的值将在函数范围之外可用,就像其他编程语言中的引用一样)。

然后,destroy函数始终在同一个chartUI对象上调用,并且实际上没有销毁render中创建的真正活动的chartUI对象。

你可以通过在destroy函数中记录chartUI.canvas来验证这一点 - 你会发现第一次从HTML中获取画布元素,但第二次画布是null - 这是因为chartUI引用的对象与之前的调用相同,而不是new Chart创建的新对象。

因此,一个快速的修复方法是在render函数的末尾添加return chartUI;

function render(currentAccount, chartUI) {
chartUI = new Chart(document.getElementById("chart"), config);
//...................
chartUI.update();
return chartUI;
}

然后在updateUI中使用以下代码来恢复新创建的图表对象:

chartUI = render(currentAccount, chartUI);

updateUI中;jsFiddle

然而,对于你正在使用的数据类型(在我的经验中几乎没有真正需要),完全不需要销毁和重新创建的模式;它还会导致视觉过渡不流畅。

只需分配新数据并调用update即可,就像这个片段中的示例一样:

//...(代码片段的其余部分)
const chartUI = new Chart(document.getElementById("chart"), config);
function render(currentAccount, chartUI) {
//...(代码片段的其余部分)
chartUI.update();
}
//...(代码片段的其余部分)

希望这对你有所帮助。

英文:

The error in your code is in the function render. You send the chartUI to the function as an argument and then inside the function you assign it a new Chart. Thus, the value of chartUI in the function and the value outside are different (you probably assumed the assigned value will be available outside the scope of the function, like it's the case with references in other programming languages).

Then, the destroy function is always called on the same chartUI object, and has no effect in actually destroying the real active chartUI which was created in render.

You can verify this by logging chartUI.canvas in the destroy function - you'll see that the first time you get the canvas element from the html, but the second time the canvas is null - that's because the object referenced by chartUI is the same from the previous call and not the new one created by new Chart.

So, a quick fix would be to add a return chartUI; at the end of the function render:

function render(currentAccount, chartUI) {
chartUI = new Chart(document.getElementById("chart"), config);
//...................
chartUI.update();
return chartUI;
}

and then recover the newly created chart object with:

chartUI = render(currentAccount, chartUI);

in updateUI; jsFiddle.

However, the whole destroy and recreate pattern is not required for the type of data you are using (and in my experience hardly anytime actually); it also results in a non-smooth visual transition.

It is sufficient to just assign new data and call update, like in this snippet:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let t0 = Date.now();
const currentAccountGen = ()=&gt;{t0 += 2*24*1000*3600; return {
transactions: Array.from({length: 10},
(_, i)=&gt;({date: t0+i*24*1000*3600, amount: 10+2*Math.random()+3*Math.cos(i/10*Math.PI)}))
}};
let labelArr = [];
let dataArr = [];
let data = {
labels: labelArr,
datasets: [
{
data: dataArr,
label: &quot;# of Amount&quot;,
borderWidth: 1,
borderColor: &quot;#01a001&quot;,
backgroundColor: &quot;#01a001&quot;,
},
],
};
let config = {
type: &quot;line&quot;,
data,
options: {
scales: {
x: {
type: &quot;time&quot;,
},
y: {
//    beginAtZero: false, // default
},
},
},
};
const chartUI = new Chart(document.getElementById(&quot;chart&quot;), config);
function render(currentAccount, chartUI) {
labelArr = [];
dataArr = [];
currentAccount.transactions.forEach((t) =&gt; {
const dateReady = /*currentUser.dateCreator*/(t.date);
labelArr.push(dateReady);
dataArr.push(t.amount);
});
chartUI.data.datasets[0].data = dataArr;
chartUI.data.labels = labelArr;
chartUI.update();
}
render(currentAccountGen(), chartUI);
const hi = setInterval(function(){
render(currentAccountGen(), chartUI);
}, 1000)
function stop(){
clearInterval(hi);
document.querySelector(&#39;#stopBut&#39;).disabled = true;
}

<!-- language: lang-html -->

&lt;button id=&#39;stopBut&#39; onclick=&quot;stop()&quot;&gt;Stop&lt;/button&gt;
&lt;div style=&quot;height:250px&quot;&gt;
&lt;canvas id=&quot;chart&quot;&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.3.0/chart.umd.js&quot; integrity=&quot;sha512-CMF3tQtjOoOJoOKlsS7/2loJlkyctwzSoDK/S40iAB+MqWSaf50uObGQSk5Ny/gfRhRCjNLvoxuCvdnERU4WGg==&quot; crossorigin=&quot;anonymous&quot; referrerpolicy=&quot;no-referrer&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0/dist/chartjs-adapter-date-fns.bundle.min.js&quot;&gt;&lt;/script&gt;

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年5月6日 22:30:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76189434.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定