我正在使用這個Observable 帖子創建帶有D3.js的日歷熱圖。我的問題是日歷一旦創建就沒有出現。我在 StackBlitz上設定了一個演示,按照博客文章中的建議進行設定。我不確定我是否遺漏了帖子中的某些內容,或者某些內容設定不正確,但我們將不勝感激任何建議或指導。
index.js
import * as d3 from 'd3';
import dji from './dji.json';
import Calendar from './Calendar';
const chart = Calendar(dji, {
x: (d) => d.Date,
y: (d, i, data) => {
return i > 0 ? (d.Close - data[i - 1].Close) / data[i - 1].Close : NaN;
}, // relative change
yFormat: ' %', // show percent change on hover
weekday: 'weekday',
/* width, */
});
日歷.js
import * as d3 from 'd3';
export default function Calendar(
data,
{
x = ([x]) => x, // given d in data, returns the (temporal) x-value
y = ([, y]) => y, // given d in data, returns the (quantitative) y-value
title, // given d in data, returns the title text
width = 928, // width of the chart, in pixels
cellSize = 17, // width and height of an individual day, in pixels
weekday = 'monday', // either: weekday, sunday, or monday
formatDay = (i) => 'SMTWTFS'[i], // given a day number in [0, 6], the day-of-week label
formatMonth = '%b', // format specifier string for months (above the chart)
yFormat, // format specifier string for values (in the title)
colors = d3.interpolatePiYG,
} = {}
) {
// Compute values.
const X = d3.map(data, x);
const Y = d3.map(data, y);
const I = d3.range(X.length);
const countDay = weekday === 'sunday' ? (i) => i : (i) => (i 6) % 7;
const timeWeek = weekday === 'sunday' ? d3.utcSunday : d3.utcMonday;
const weekDays = weekday === 'weekday' ? 5 : 7;
const height = cellSize * (weekDays 2);
// Compute a color scale. This assumes a diverging color scheme where the pivot
// is zero, and we want symmetric difference around zero.
const max = d3.quantile(Y, 0.9975, Math.abs);
const color = d3.scaleSequential([-max, max], colors).unknown('none');
// Construct formats.
formatMonth = d3.utcFormat(formatMonth);
// Compute titles.
if (title === undefined) {
const formatDate = d3.utcFormat('%B %-d, %Y');
const formatValue = color.tickFormat(100, yFormat);
title = (i) => `${formatDate(X[i])}\n${formatValue(Y[i])}`;
}
if (title !== null) {
const T = d3.map(data, title);
title = (i) => T[i];
}
// Group the index by year, in reverse input order. (Assuming that the input is
// chronological, this will show years in reverse chronological order.)
const years = d3
.groups(I, (i) => {
const x = new Date(X[i]);
return x.getUTCFullYear();
})
.reverse();
function pathMonth(t) {
const d = Math.max(0, Math.min(weekDays, countDay(t.getUTCDay())));
const w = timeWeek.count(d3.utcYear(t), t);
return `${
d === 0
? `M${w * cellSize},0`
: d === weekDays
? `M${(w 1) * cellSize},0`
: `M${(w 1) * cellSize},0V${d * cellSize}H${w * cellSize}`
}V${weekDays * cellSize}`;
}
const svg = d3
.create('svg')
.attr('width', width)
.attr('height', height * years.length)
.attr('viewBox', [0, 0, width, height * years.length])
.attr('style', 'max-width: 100%; height: auto; height: intrinsic;')
.attr('font-family', 'sans-serif')
.attr('font-size', 10);
const year = svg
.selectAll('g')
.data(years)
.join('g')
.attr(
'transform',
(d, i) => `translate(40.5,${height * i cellSize * 1.5})`
);
year
.append('text')
.attr('x', -5)
.attr('y', -5)
.attr('font-weight', 'bold')
.attr('text-anchor', 'end')
.text(([key]) => key);
year
.append('g')
.attr('text-anchor', 'end')
.selectAll('text')
.data(weekday === 'weekday' ? d3.range(1, 6) : d3.range(7))
.join('text')
.attr('x', -5)
.attr('y', (i) => (countDay(i) 0.5) * cellSize)
.attr('dy', '0.31em')
.text(formatDay);
const cell = year
.append('g')
.selectAll('rect')
.data(
weekday === 'weekday'
? ([, I]) =>
I.filter((i) => {
const x = new Date(X[i]);
return ![0, 6].includes(x.getUTCDay());
})
: ([, I]) => I
)
.join('rect')
.attr('width', cellSize - 1)
.attr('height', cellSize - 1)
.attr('x', (i) => timeWeek.count(d3.utcYear(X[i]), X[i]) * cellSize 0.5)
.attr('y', (i) => {
const x = new Date(X[i]);
return countDay(x.getUTCDay()) * cellSize 0.5;
})
.attr('fill', (i) => color(Y[i]));
if (title) cell.append('title').text(title);
const month = year
.append('g')
.selectAll('g')
.data(([, I]) => d3.utcMonths(d3.utcMonth(X[I[0]]), X[I[I.length - 1]]))
.join('g');
month
.filter((d, i) => i)
.append('path')
.attr('fill', 'none')
.attr('stroke', '#fff')
.attr('stroke-width', 3)
.attr('d', pathMonth);
month
.append('text')
.attr(
'x',
(d) => timeWeek.count(d3.utcYear(d), timeWeek.ceil(d)) * cellSize 2
)
.attr('y', -5)
.text(formatMonth);
return Object.assign(svg.node(), { scales: { color } });
}
uj5u.com熱心網友回復:
添加元素
ObservableHQ 帖子的操作方式與傳統的 JavaScript 不同。如果運算式回傳一個 DOM 元素,它會自動顯示在帖子中。在該環境之外,在常規 JavaScript 中,您必須明確地將它們添加到您的 DOM 中。
在您的情況下,添加document.body.appendChild(chart);到index.js.
修復決議
執行此操作后,您會注意到僅顯示一列日期。日歷似乎需要日期物件,而不是日期字串。在這種情況下,您可以將 x 決議函式更改為index.js:
x: (d) => d.Date,
至
x: (d) => new Date(d.Date),
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513941.html
上一篇:如何通過將標題更改為類別并將所有值更改為一列來讀取多列CSV?
下一篇:D3調整鏈接文字位置
