我如何根据数值更改ChartJS线条颜色?

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

How can I change ChartJS line color based on the value?

问题

我正在尝试执行与此Stack Overflow答案中提供的相同操作,https://stackoverflow.com/a/66943726/1108057

不幸的是,该答案适用于较旧版本的Chart.js,新版本不支持许多所需的元素,例如直接访问_meta属性。

我已经找到了如何在新版本中获取数据集的元数据的方法,但我无法弄清楚其余部分,因为我不知道它在以前的版本中是如何引用的。

plugins: [{
    id: 'redLineLoss',
    beforeRender: (x, options) => {
        const c = x;
        const dataset = x.data.datasets[1];
        const yScale = x.scales['y'];
        const yPos = yScale.getPixelForValue(0);

        const gradientFill = c.ctx.createLinearGradient(0, 0, 0, c.height);
        gradientFill.addColorStop(0, 'rgb(86,188,77)');
        gradientFill.addColorStop(yPos / c.height, 'rgb(86,188,77)');
        gradientFill.addColorStop(yPos / c.height, 'rgb(229,66,66)');
        gradientFill.addColorStop(1, 'rgb(229,66,66)');

        const datasetMeta = x.getDatasetMeta(1);

        console.log(datasetMeta['data']);

        // 现在我从数据集元数据中获取什么?

        //console.log(datasetMeta.dataset.getProps(['x', 'y']));

        //console.log(model[Object.keys(x.getDatasetMeta(1))]);

        //const model = x.data.datasets[1]._meta[Object.keys(dataset._meta)[1]].dataset._model;

        //model.borderColor = gradientFill;
    },
}],

我只想将此应用于图表中的特定数据集,而不是全部数据集。这就是我选择使用键1选择数据集的原因。

英文:

I am trying to do the same thing provided in this SO answer,
https://stackoverflow.com/a/66943726/1108057

Unfortunately that answer is for older versions of Chart.js and a lot of the needed elements are not supported in the new version, such as accessing _meta properties directly.

I was able to figure out how to get meta of the dataset in the new version, but I can't figure out the remaining part of it as I don't know what it was referencing in the previous version.

plugins: [{
    id: 'redLineLoss',
    beforeRender: (x, options) => {
        const c = x;
        const dataset = x.data.datasets[1];
        const yScale = x.scales['y'];
        const yPos = yScale.getPixelForValue(0);

        const gradientFill = c.ctx.createLinearGradient(0, 0, 0, c.height);
        gradientFill.addColorStop(0, 'rgb(86,188,77)');
        gradientFill.addColorStop(yPos / c.height, 'rgb(86,188,77)');
        gradientFill.addColorStop(yPos / c.height, 'rgb(229,66,66)');
        gradientFill.addColorStop(1, 'rgb(229,66,66)');

        const datasetMeta = x.getDatasetMeta(1);

        console.log(datasetMeta['data']);

        // STUCK HERE -- what do I get from the dataset meta now?

        //console.log(datasetMeta.dataset.getProps(['x', 'y']));

        //console.log(model[Object.keys(x.getDatasetMeta(1))]);

        //const model = x.data.datasets[1]._meta[Object.keys(dataset._meta)[1]].dataset._model;

        //model.borderColor = gradientFill;
    },
}],

I want to only apply this to a specific dataset in the chart, not all of them. That's why I am selecting the dataset with key 1.

答案1

得分: 1

解决方案 #1

pointBorderColorpointBackgroundColor 仅在您希望着色值的标记时才能正常工作。为此,您需要预先定义一个颜色数组,该数组来自值的数组。

您可以按段来为线状图的 borderColorbackgroundColor 着色。为此,您可以使用 segment.borderColorsegment.backgroundColor(当设置 fill: true 时)。这些设置调用一个函数,您需要将当前 "段" 的起始和结束值传递给该函数。我已经写了一个包含这些内容的示例,尽管我在这里定义了0值,以确保该段仅由正数或负数组成... 无论如何,这是示例:

Chart.js Github Issue #1493

const ctx = document.getElementById("myChart").getContext("2d")
const data = [10, 20, 0, -10, -20, 0, 5]
const colors = data.map((value) => value < 0 ? 'red' : 'green')

const chart = new Chart(ctx, {
  type: "line",
  data: {
    labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"],
    datasets: [{
      label: "示例数据集",
      data: data,
      fill: true, // 设置为true以使用backgroundColor
      segment: {
        borderColor: (part) => {
          const prevValue = part.p0.parsed.y // 起始值
          const nextValue = part.p1.parsed.y // 结束值
          return prevValue < 0 || nextValue < 0 ? "red" : "green" // 根据规则返回颜色
        },
        backgroundColor: (part) => {
          const prevValue = part.p0.parsed.y // 起始值
          const nextValue = part.p1.parsed.y // 结束值
          return prevValue < 0 || nextValue < 0 ? "red" : "green" // 根据规则返回颜色
        },
      },
      pointBorderColor: colors, // 使用颜色数组
      pointBackgroundColor: colors, // 使用颜色数组
    }]
  },
  options: {
    responsive: true,
    scales: {
      y: {
        ticks: {
          beginAtZero: true
        }
      }
    }
  },
})

解决方案 #2

要在 Chart.js 3.x 或更高版本中实现渐变填充,您可以使用名为 chartjs-plugin-gradient 的软件包,该软件包可用。我提供了下面的一个简单示例代码:

const ctx = document.getElementById("myChart").getContext("2d")
const gradient = window['chartjs-plugin-gradient'] // 调用 CDN 上的 "chartjs-plugin-gradient"

const chart = new Chart(ctx, {
  type: "line",
  data: {
    labels: ["Jan", "Feb", "Mar", "Apr", "May"],
    datasets: [{
      label: "示例数据集",
      data: [0, 1, 4, 16, 64],
      fill: true, // 设置为true以使用backgroundColor
      gradient: {
        // 可以设置渐变背景(需要 "fill: true")
        backgroundColor: {
          axis: 'y', // 'x' 或 'y'
          colors: {
            0: 'red',
            4: 'yellow',
            20: 'green'
          }
        },
        // 可以设置渐变线
        borderColor: {
          axis: 'y', // 'x' 或 'y'
          colors: {
            0: 'red',
            4: 'yellow',
            20: 'green'
          }
        }
      }
    }]
  },
  options: {
    responsive: true,
    scales: {
      y: {
        ticks: {
          beginAtZero: true
        }
      }
    }
  },
  plugins: [gradient] // 使用 "chartjs-plugin-gradient"
})

这是两个解决方案的代码部分,供您参考。

英文:

Solution # 1

The pointBorderColor and pointBackgroundColor work perfectly when you only want to color the markers of the values. To do this, you need to predefine an array of colors from the array of values.

You can color the borderColor or backgroundColor of a line chart on a segment-by-segment basis. For this, you have the option of using segment.borderColor or segment.backgroundColor (when fill: true is set). These settings invoke a function to which you pass the current opening and closing values of the "segment". I have written an example that includes these as well, although I had to define the 0 value here to ensure that the segment consists only of positive or negative numbers... anyway, here is the example:

Chart.js Github Issue #1493

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

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

const ctx = document.getElementById(&quot;myChart&quot;).getContext(&quot;2d&quot;)
const data = [10, 20, 0, -10, -20, 0, 5]
const colors = data.map((value) =&gt; value &lt; 0 ? &#39;red&#39; : &#39;green&#39;)
const chart = new Chart(ctx, {
type: &quot;line&quot;,
data: {
labels: [&quot;Jan&quot;, &quot;Feb&quot;, &quot;Mar&quot;, &quot;Apr&quot;, &quot;May&quot;, &quot;Jun&quot;, &quot;Jul&quot;],
datasets: [{
label: &quot;Sample Dataset&quot;,
data: data,
fill: true, // set true for &quot;backgroundColor&quot; using
segment: {
borderColor: (part) =&gt; {
const prevValue = part.p0.parsed.y // start value
const nextValue = part.p1.parsed.y // end value
return prevValue &lt; 0 || nextValue &lt; 0 ? &quot;red&quot; : &quot;green&quot; // return with a color by rule
},
backgroundColor: (part) =&gt; {
const prevValue = part.p0.parsed.y // start value
const nextValue = part.p1.parsed.y // end value
return prevValue &lt; 0 || nextValue &lt; 0 ? &quot;red&quot; : &quot;green&quot; // return with a color by rule
},
},
pointBorderColor: colors, // with array of colors
pointBackgroundColor: colors, // with array of colors
}]
},
options: {
responsive: true,
scales: {
y: {
ticks: {
beginAtZero: true
}
}
}
},
})

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

&lt;script src=&quot;https://cdn.jsdelivr.net/npm/chart.js&quot;&gt;&lt;/script&gt;
&lt;canvas id=&quot;myChart&quot;&gt;&lt;/canvas&gt;

<!-- end snippet -->

Solution # 2

To achieve gradient fill in Chart.js 3.x or higher versions, you can use the package called chartjs-plugin-gradient available at. I have provided a simple example code below:

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

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

const ctx = document.getElementById(&quot;myChart&quot;).getContext(&quot;2d&quot;)
const gradient = window[&#39;chartjs-plugin-gradient&#39;] // call CDN &quot;chartjs-plugin-gradient&quot;
const chart = new Chart(ctx, {
type: &quot;line&quot;,
data: {
labels: [&quot;Jan&quot;, &quot;Feb&quot;, &quot;Mar&quot;, &quot;Apr&quot;, &quot;May&quot;],
datasets: [{
label: &quot;Sample Dataset&quot;,
data: [0, 1, 4, 16, 64],
fill: true, // set true for &quot;backgroundColor&quot; using
gradient: {
// Can set gradient background (need &quot;fill: true&quot;)
backgroundColor: {
axis: &#39;y&#39;, // &#39;x&#39; or &#39;y&#39;
colors: {
// from value: color hex
0: &#39;red&#39;,
4: &#39;yellow&#39;,
20: &#39;green&#39;
}
},
// Can set gradient line
borderColor: {
axis: &#39;y&#39;, // &#39;x&#39; or &#39;y&#39;
colors: {
// from value: color hex
0: &#39;red&#39;,
4: &#39;yellow&#39;,
20: &#39;green&#39;
}
}
}
}]
},
options: {
responsive: true,
scales: {
y: {
ticks: {
beginAtZero: true
}
}
}
},
plugins: [gradient] // using &quot;chartjs-plugin-gradient&quot;
})

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

&lt;script src=&quot;https://cdn.jsdelivr.net/npm/chart.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/chartjs-plugin-gradient#.js&quot;&gt;&lt;/script&gt;
&lt;canvas id=&quot;myChart&quot;&gt;&lt;/canvas&gt;

<!-- end snippet -->

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

发表评论

匿名网友

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

确定