提问人:punkish 提问时间:7/5/2023 最后编辑:punkish 更新时间:9/11/2023 访问量:276
使用 chartjs 的对数图表中的次要网格线
minor grid lines in log chart with chartjs
问:
更新:在线添加了一个工作小提琴,添加了一个工作代码片段:)
我正在从 转向 但坚持尝试在对数刻度图表中显示次要网格线。图表如下图所示(没有次要网格线)。我希望它有像第二张图片中那样的网格线。多次阅读文档没有给我答案。dygraphs
chartsjs
chartjs
const termFreqWithChartjs = (ctx, series, term, termFreq) => {
const config = {
type: 'line',
data: {
labels: termFreq.map(e => e.journalYear),
datasets: [
{
label: series.y1,
data: termFreq.map(e => e.total),
borderColor: 'red',
borderWidth: 1,
backgroundColor: 'rgba(255, 0, 0, 0.1)',
pointStyle: 'circle',
pointRadius: 3,
pointBorderColor: 'rgb(0, 0, 0)'
},
{
label: series.y2,
data: termFreq.map(e => e.withImages),
borderColor: 'blue',
borderWidth: 1,
backgroundColor: 'rgba(0, 0, 255, 0.1)',
pointStyle: 'circle',
pointRadius: 3,
pointBorderColor: 'rgb(0, 0, 0)'
}
]
},
options: {
interaction: {
intersect: false,
mode: 'x',
},
animation: false,
responsive: true,
scales: {
x: {
display: true,
},
y: {
display: true,
type: 'logarithmic',
grid: {
borderColor: 'grey',
tickColor: 'grey'
},
min: 1,
ticks: {
callback: function (value, index, values) {
if (value === 1000000) return "1M";
if (value === 100000) return "100K";
if (value === 10000) return "10K";
if (value === 1000) return "1K";
if (value === 100) return "100";
if (value === 10) return "10";
if (value === 1) return "1";
return null;
}
}
}
},
plugins: {
title: {
display: true,
text: `occurrence of '${term}' in text by year`,
},
legend: {
display: true,
position: 'chartArea',
labels: {
usePointStyle: true,
}
},
tooltip: {
enabled: true
}
}
}
};
let canvas = document.getElementById('termFreq');
if (canvas) {
termFreqChart.destroy();
termFreqChart = new Chart(canvas, config);
}
else {
canvas = document.createElement('canvas');
canvas.id = "termFreq";
canvas.width = 500;
canvas.height = 200;
ctx.appendChild(canvas);
termFreqChart = new Chart(canvas, config);
}
}
const termFreq = [
{
"journalYear": 1841,
"total": 3,
"withImages": 0
},
{
"journalYear": 1846,
"total": 2,
"withImages": 0
},
{
"journalYear": 1850,
"total": 2,
"withImages": 0
},
{
"journalYear": 1851,
"total": 26,
"withImages": 0
},
{
"journalYear": 1853,
"total": 5,
"withImages": 0
},
{
"journalYear": 1855,
"total": 7,
"withImages": 0
},
{
"journalYear": 1857,
"total": 27,
"withImages": 0
},
{
"journalYear": 1859,
"total": 30,
"withImages": 0
},
{
"journalYear": 1860,
"total": 4,
"withImages": 0
},
{
"journalYear": 1861,
"total": 9,
"withImages": 0
},
{
"journalYear": 1862,
"total": 18,
"withImages": 0
},
{
"journalYear": 1863,
"total": 4,
"withImages": 0
},
{
"journalYear": 1866,
"total": 12,
"withImages": 0
},
{
"journalYear": 1877,
"total": 1,
"withImages": 0
},
{
"journalYear": 1884,
"total": 2,
"withImages": 0
},
{
"journalYear": 1886,
"total": 12,
"withImages": 0
},
{
"journalYear": 1887,
"total": 2,
"withImages": 0
},
{
"journalYear": 1890,
"total": 5,
"withImages": 0
},
{
"journalYear": 1893,
"total": 4,
"withImages": 0
},
{
"journalYear": 1894,
"total": 9,
"withImages": 0
},
{
"journalYear": 1895,
"total": 3,
"withImages": 0
},
{
"journalYear": 1896,
"total": 1,
"withImages": 0
},
{
"journalYear": 1902,
"total": 3,
"withImages": 0
},
{
"journalYear": 1904,
"total": 14,
"withImages": 0
},
{
"journalYear": 1905,
"total": 10,
"withImages": 0
},
{
"journalYear": 1910,
"total": 1,
"withImages": 0
},
{
"journalYear": 1912,
"total": 1,
"withImages": 0
},
{
"journalYear": 1913,
"total": 3,
"withImages": 0
},
{
"journalYear": 1914,
"total": 7,
"withImages": 0
},
{
"journalYear": 1915,
"total": 5,
"withImages": 0
},
{
"journalYear": 1920,
"total": 1,
"withImages": 0
},
{
"journalYear": 1922,
"total": 8,
"withImages": 0
},
{
"journalYear": 1924,
"total": 1,
"withImages": 0
},
{
"journalYear": 1926,
"total": 5,
"withImages": 0
},
{
"journalYear": 1928,
"total": 5,
"withImages": 0
},
{
"journalYear": 1932,
"total": 2,
"withImages": 0
},
{
"journalYear": 1949,
"total": 3,
"withImages": 0
},
{
"journalYear": 1950,
"total": 1,
"withImages": 0
},
{
"journalYear": 1953,
"total": 2,
"withImages": 0
},
{
"journalYear": 1955,
"total": 3,
"withImages": 0
},
{
"journalYear": 1956,
"total": 1,
"withImages": 0
},
{
"journalYear": 1958,
"total": 2,
"withImages": 0
},
{
"journalYear": 1959,
"total": 1,
"withImages": 0
},
{
"journalYear": 1960,
"total": 2,
"withImages": 0
},
{
"journalYear": 1975,
"total": 2,
"withImages": 0
},
{
"journalYear": 1979,
"total": 136,
"withImages": 0
},
{
"journalYear": 1990,
"total": 27,
"withImages": 5
},
{
"journalYear": 1992,
"total": 3,
"withImages": 0
},
{
"journalYear": 1993,
"total": 1,
"withImages": 0
},
{
"journalYear": 1997,
"total": 1,
"withImages": 1
},
{
"journalYear": 2000,
"total": 251,
"withImages": 225
},
{
"journalYear": 2001,
"total": 14,
"withImages": 0
},
{
"journalYear": 2003,
"total": 141,
"withImages": 139
},
{
"journalYear": 2004,
"total": 2,
"withImages": 0
},
{
"journalYear": 2005,
"total": 62,
"withImages": 0
},
{
"journalYear": 2006,
"total": 16,
"withImages": 12
},
{
"journalYear": 2007,
"total": 79,
"withImages": 17
},
{
"journalYear": 2008,
"total": 42,
"withImages": 16
},
{
"journalYear": 2009,
"total": 141,
"withImages": 60
},
{
"journalYear": 2010,
"total": 111,
"withImages": 5
},
{
"journalYear": 2011,
"total": 62,
"withImages": 14
},
{
"journalYear": 2012,
"total": 100,
"withImages": 25
},
{
"journalYear": 2013,
"total": 137,
"withImages": 129
},
{
"journalYear": 2014,
"total": 54,
"withImages": 23
},
{
"journalYear": 2015,
"total": 139,
"withImages": 73
},
{
"journalYear": 2016,
"total": 166,
"withImages": 36
},
{
"journalYear": 2017,
"total": 87,
"withImages": 74
},
{
"journalYear": 2018,
"total": 79,
"withImages": 49
},
{
"journalYear": 2019,
"total": 142,
"withImages": 96
},
{
"journalYear": 2020,
"total": 84,
"withImages": 27
},
{
"journalYear": 2021,
"total": 907,
"withImages": 386
},
{
"journalYear": 2022,
"total": 79,
"withImages": 50
},
{
"journalYear": 2023,
"total": 3,
"withImages": 0
}
];
const series = {
x: "journal year",
y1: "total",
y2: "with images"
}
const ctx = document.getElementById('graphdiv');
termFreqWithChartjs(ctx, series, 'formica', termFreq);
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div id="graphdiv"></div>
答:
默认情况下,Chart.js 将为对数轴生成次要网格线。OP 的代码不显示任何次要网格线,因为该函数返回不合格的刻度;这导致该刻度和网格线被移除。
ticks.callback
null
一个可能的解决方案是将 in 替换为 ;这将保留刻度(和网格线),但不显示任何标签。一个缺点是,即使标签的大小为零,系统也会为其分配一个空间,这可能会影响标记的刻度;人们可能想要禁用 .
return null
return ''
ticks.callback
ticks.autoSkip: false
在那之后,真正的挑战是在视觉上区分次要网格线和主要网格线。解决方案来自这样一个事实,即大多数网格线设置都是可编写脚本的选项,可以分配功能,可用于使结果(选项,例如网格线颜色)适应运行时环境 - 在这种情况下,相应的刻度是次要的还是主要的。
我在下面的代码中确定了所有相关选项,这些选项可用于在视觉上区分次要网格线和刻度与主要网格线和刻度。您可以只保留其中的一部分,也可以不保留。
我还为函数中的刻度添加了一个可能的过滤器,更多是该功能的演示。也可以通过实际返回一些 s 来过滤 中的网格线。
options.scales.y.afterBuildTicks
ticks.callback
null
value
选项,提取:
const config = {
type: 'line',
data: {
// ............
},
options: {
// ..... other options
scales: {
x: // .....
y: {
display: true,
type: 'logarithmic',
grid: {
tickColor: function(data){ // color of the tick line
return data.tick.major ? 'rgb(196, 196, 196)' :
'rgba(196, 196, 196, 0)' // minor ticks not visible
},
lineWidth: function(data){ // the width of grid line
return data.tick.major ? 2 : 1
},
color:function(data){ // the color of the grid line
return data.tick.major ? 'rgb(196, 196, 196)' :
'rgba(196, 196, 196, 0.5)'
}
},
border:{
dash:function(data){
// dash pattern for grid lines
// (unexpected position for this option here)
return data.tick.major ? null : [5, 1]
}
},
min: 1,
afterBuildTicks: function(ax){
ax.ticks = ax.ticks.filter(({value})=>{
const r = value/ Math.pow(10, Math.floor(Math.log10(value)+1e-5));
return Math.abs(r - Math.round(r)) < 1e-5
})
// this eliminates tick values like 15 or 150 and only keeps
// those of the form n*10^m with n, m one digit integers
// this might not be necessary
},
ticks: {
callback: function (value, index, ticks) {
if (value === 1000000) return "1M";
if (value === 100000) return "100K";
if (value === 10000) return "10K";
if (value === 1000) return "1K";
if (value === 100) return "100";
if (value === 10) return "10";
if (value === 1) return "1";
return '';
}
}
}
},
// ......
}
}
完整运行示例,从 OP 分叉而来,高度增加以使对数次要网格线可见。
const termFreqWithChartjs = (ctx, series, term, termFreq) => {
const config = {
type: 'line',
data: {
labels: termFreq.map(e => e.journalYear),
datasets: [
{
label: series.y1,
data: termFreq.map(e => e.total),
borderColor: 'red',
borderWidth: 1,
backgroundColor: 'rgba(255, 0, 0, 0.1)',
pointStyle: 'circle',
pointRadius: 3,
pointBorderColor: 'rgb(0, 0, 0)'
},
{
label: series.y2,
data: termFreq.map(e => e.withImages),
borderColor: 'blue',
borderWidth: 1,
backgroundColor: 'rgba(0, 0, 255, 0.1)',
pointStyle: 'circle',
pointRadius: 3,
pointBorderColor: 'rgb(0, 0, 0)'
}
]
},
options: {
interaction: {
intersect: false,
mode: 'x',
},
animation: false,
responsive: true,
scales: {
x: {
display: true,
},
y: {
display: true,
type: 'logarithmic',
grid: {
tickColor: function(data){
return data.tick.major ? 'rgb(196, 196, 196)' :
'rgba(196, 196, 196, 0)' // minor ticks not visible
},
lineWidth: function(data){
return data.tick.major ? 2 : 1
},
color:function(data){
return data.tick.major ? 'rgb(196, 196, 196)' :
'rgba(196, 196, 196, 0.5)'
}
},
border:{
dash:function(data){
// dash line for grid lines
// (unexpected position for this option here)
return data.tick.major ? null : [5, 1]
}
},
min: 1,
afterBuildTicks: function(ax){
ax.ticks = ax.ticks.filter(({value})=>{
const r = value/ Math.pow(10, Math.floor(Math.log10(value)+1e-5));
return Math.abs(r - Math.round(r)) < 1e-5
})
// this eliminates tick values like 15 or 150 and only keeps
// those of the form n*10^m with n, m one digit integers
// this might not be necessary
},
ticks: {
autoSkip: false,
callback: function (value, index, ticks) {
if (value === 1000000) return "1M";
if (value === 100000) return "100K";
if (value === 10000) return "10K";
if (value === 1000) return "1K";
if (value === 100) return "100";
if (value === 10) return "10";
if (value === 1) return "1";
return '';
}
}
}
},
plugins: {
title: {
display: true,
text: `occurrence of '${term}' in text by year`,
},
legend: {
display: true,
position: 'chartArea',
labels: {
usePointStyle: true,
}
},
tooltip: {
enabled: true
}
}
}
};
let canvas = document.getElementById('termFreq');
if (canvas) {
termFreqChart.destroy();
termFreqChart = new Chart(canvas, config);
}
else {
canvas = document.createElement('canvas');
canvas.id = "termFreq";
canvas.width = 960;
canvas.height = 600;
ctx.appendChild(canvas);
termFreqChart = new Chart(canvas, config);
}
}
const termFreq = [
{
"journalYear": 1841,
"total": 3,
"withImages": 0
},
{
"journalYear": 1846,
"total": 2,
"withImages": 0
},
{
"journalYear": 1850,
"total": 2,
"withImages": 0
},
{
"journalYear": 1851,
"total": 26,
"withImages": 0
},
{
"journalYear": 1853,
"total": 5,
"withImages": 0
},
{
"journalYear": 1855,
"total": 7,
"withImages": 0
},
{
"journalYear": 1857,
"total": 27,
"withImages": 0
},
{
"journalYear": 1859,
"total": 30,
"withImages": 0
},
{
"journalYear": 1860,
"total": 4,
"withImages": 0
},
{
"journalYear": 1861,
"total": 9,
"withImages": 0
},
{
"journalYear": 1862,
"total": 18,
"withImages": 0
},
{
"journalYear": 1863,
"total": 4,
"withImages": 0
},
{
"journalYear": 1866,
"total": 12,
"withImages": 0
},
{
"journalYear": 1877,
"total": 1,
"withImages": 0
},
{
"journalYear": 1884,
"total": 2,
"withImages": 0
},
{
"journalYear": 1886,
"total": 12,
"withImages": 0
},
{
"journalYear": 1887,
"total": 2,
"withImages": 0
},
{
"journalYear": 1890,
"total": 5,
"withImages": 0
},
{
"journalYear": 1893,
"total": 4,
"withImages": 0
},
{
"journalYear": 1894,
"total": 9,
"withImages": 0
},
{
"journalYear": 1895,
"total": 3,
"withImages": 0
},
{
"journalYear": 1896,
"total": 1,
"withImages": 0
},
{
"journalYear": 1902,
"total": 3,
"withImages": 0
},
{
"journalYear": 1904,
"total": 14,
"withImages": 0
},
{
"journalYear": 1905,
"total": 10,
"withImages": 0
},
{
"journalYear": 1910,
"total": 1,
"withImages": 0
},
{
"journalYear": 1912,
"total": 1,
"withImages": 0
},
{
"journalYear": 1913,
"total": 3,
"withImages": 0
},
{
"journalYear": 1914,
"total": 7,
"withImages": 0
},
{
"journalYear": 1915,
"total": 5,
"withImages": 0
},
{
"journalYear": 1920,
"total": 1,
"withImages": 0
},
{
"journalYear": 1922,
"total": 8,
"withImages": 0
},
{
"journalYear": 1924,
"total": 1,
"withImages": 0
},
{
"journalYear": 1926,
"total": 5,
"withImages": 0
},
{
"journalYear": 1928,
"total": 5,
"withImages": 0
},
{
"journalYear": 1932,
"total": 2,
"withImages": 0
},
{
"journalYear": 1949,
"total": 3,
"withImages": 0
},
{
"journalYear": 1950,
"total": 1,
"withImages": 0
},
{
"journalYear": 1953,
"total": 2,
"withImages": 0
},
{
"journalYear": 1955,
"total": 3,
"withImages": 0
},
{
"journalYear": 1956,
"total": 1,
"withImages": 0
},
{
"journalYear": 1958,
"total": 2,
"withImages": 0
},
{
"journalYear": 1959,
"total": 1,
"withImages": 0
},
{
"journalYear": 1960,
"total": 2,
"withImages": 0
},
{
"journalYear": 1975,
"total": 2,
"withImages": 0
},
{
"journalYear": 1979,
"total": 136,
"withImages": 0
},
{
"journalYear": 1990,
"total": 27,
"withImages": 5
},
{
"journalYear": 1992,
"total": 3,
"withImages": 0
},
{
"journalYear": 1993,
"total": 1,
"withImages": 0
},
{
"journalYear": 1997,
"total": 1,
"withImages": 1
},
{
"journalYear": 2000,
"total": 251,
"withImages": 225
},
{
"journalYear": 2001,
"total": 14,
"withImages": 0
},
{
"journalYear": 2003,
"total": 141,
"withImages": 139
},
{
"journalYear": 2004,
"total": 2,
"withImages": 0
},
{
"journalYear": 2005,
"total": 62,
"withImages": 0
},
{
"journalYear": 2006,
"total": 16,
"withImages": 12
},
{
"journalYear": 2007,
"total": 79,
"withImages": 17
},
{
"journalYear": 2008,
"total": 42,
"withImages": 16
},
{
"journalYear": 2009,
"total": 141,
"withImages": 60
},
{
"journalYear": 2010,
"total": 111,
"withImages": 5
},
{
"journalYear": 2011,
"total": 62,
"withImages": 14
},
{
"journalYear": 2012,
"total": 100,
"withImages": 25
},
{
"journalYear": 2013,
"total": 137,
"withImages": 129
},
{
"journalYear": 2014,
"total": 54,
"withImages": 23
},
{
"journalYear": 2015,
"total": 139,
"withImages": 73
},
{
"journalYear": 2016,
"total": 166,
"withImages": 36
},
{
"journalYear": 2017,
"total": 87,
"withImages": 74
},
{
"journalYear": 2018,
"total": 79,
"withImages": 49
},
{
"journalYear": 2019,
"total": 142,
"withImages": 96
},
{
"journalYear": 2020,
"total": 84,
"withImages": 27
},
{
"journalYear": 2021,
"total": 907,
"withImages": 386
},
{
"journalYear": 2022,
"total": 79,
"withImages": 50
},
{
"journalYear": 2023,
"total": 3,
"withImages": 0
}
];
const series = {
x: "journal year",
y1: "total",
y2: "with images"
}
const ctx = document.getElementById('graphdiv');
termFreqWithChartjs(ctx, series, 'formica', termFreq);
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div id="graphdiv"></div>
评论
data.datasets[].backgroundColor
backgroundColor: 'rgba(0, 0, 255, 1)'
options.scales.y.afterBuildTicks
minorTickStepFraction
minorTickStepFraction
minorTickStepFraction = 1
chartjs
评论
grid.lineWidth
可编写脚本的事实并使用 ticks 回调。或者,按照@DouglasCunha的要求去做,并提供一个工作示例,让我们提供帮助......chartjs