Public
Edited
Apr 30
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
async function* yamamotoChart(data) {
// function myChart(data) { // 1行目と同じ意味
// const width = 800;
const height = (width * 150) / 215;
const margin = { top: height * 0.05, right: 30, bottom: 30, left: 120 };

const dataOfDatesTimes = getDataOfDatesTimes(data);
//const locations = d3.group(data, (d) => d.location);
const xScale = d3
.scaleLinear()
.domain([0, 2])
.range([margin.left, width - margin.right]);

const yScale = d3
.scaleBand()
.domain([...dataOfDatesTimes.keys()])
.range([margin.top, height - margin.bottom]);

const arcGenerator = d3
.arc()
.innerRadius(9) // 内側の半径
.outerRadius(10) // 外側の半径
.startAngle(Math.PI / 2) // スタートの角度
.endAngle((Math.PI * 3) / 2); // 終わりの角度

const arcGenerator_1 = d3
.arc()
.innerRadius(0) // 内側の半径を0で指定すると半円
.outerRadius(9)
.startAngle(Math.PI / 2)
.endAngle((Math.PI * 3) / 2);

const dow = (d) => "日月火水木金土".at(new Date(d).getDay());

const xAxis = d3
.axisBottom()
.scale(xScale)
//.ticks(4)
.tickFormat(() => "");
// .tickSize(-(height - margin.top - margin.bottom));
const yAxis = d3
.axisLeft()
.scale(yScale)
//.ticks(7)
.tickFormat(() => "");
// .tickSize(-(width - margin.left - margin.right));

const svg = d3.create("svg").attr("width", width).attr("height", height);

svg
.append("rect")
.attr("width", width)
.attr("height", height)
.attr("fill", "white");

svg
.append("g")
.attr("class", "xAxis")
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(xAxis);
svg
.append("g")
.attr("class", "yAxis")
.attr("transform", `translate(${margin.left}, 0)`)
.call(yAxis);

const dayG = svg
.selectAll("g.day")
.data(dataOfDatesTimes)
.join("g")
.attr("class", "day")
.attr("transform", (d) => `translate(0, ${yScale(d[0])})`);
dayG
.append("line")
.attr("x1", 0) // 左端
.attr("x2", width) // 右端(widthはSVGエリアの幅)
.attr("y1", height * 0.065)
.attr("y2", height * 0.065)
.style("stroke", "black");

const timeG = dayG
.selectAll("g.time")
.data((d) => d[1])
.join("g")
.attr("class", "time")
.attr("transform", (d) => `translate(${xScale(d[0])}, 0)`);

const circleX = d3.scaleBand().range([10, xScale(1) - xScale(0) - 10]);

// pendulum
const pendulum = timeG
.selectAll("g")
.data((d) => d[1])
.join("g")
.attr("transform", (d, i, nodes) => {
circleX.domain(d3.range(nodes.length));
return `translate(${circleX(i) + circleX.bandwidth() / 2}, ${
yScale.bandwidth() / 2
})`;
})
.append("g");
const locationXScale = (location) => (location == "自宅" ? 20 : 0);

pendulum
.append("line")
.attr("y2", (d) => yScale.bandwidth() / 2 - locationXScale(d.location))

.attr("stroke", "#000");

timeG
.selectAll("path")
.data((d) => d[1])
.join("path")
.attr("transform", (d, i, nodes) => {
circleX.domain(d3.range(nodes.length));
return `translate(${circleX(i) + circleX.bandwidth() / 2}, ${
yScale.bandwidth() / 2
}) `;
})

.attr("d", arcGenerator) // さっき作った形を指定する
.attr("fill", "black"); // 塗りつぶしの色指定

pendulum.append("circle").attr("r", 9).attr("fill", "white");

pendulum
.append("path")
.attr("d", starD)
.attr("fill", (d) => colorScale(d.drink))
//.attr("transform", "scale(0.02)");
.attr(
"transform",
(d) =>
`translate(-14, ${
yScale.bandwidth() / 2 - locationXScale(d.location) - 5
}) scale(0.025)`
);

svg
.selectAll("g.xAxis, g.yAxis")
.selectAll("line, path")
.attr("stroke", "white")
.attr("opacity", 0.5);
svg.selectAll("g.xAxis, g.yAxis").selectAll("text").attr("font-size", 16);

const angle = d3
.scaleOrdinal()
.domain(["あたたかい", "つめたい", "常温"])
.range([-45, 45, 0])
.unknown(0); // 未知の値に対するデフォルトの色

// animation
while (true) {
yield svg.node();
await pendulum
.transition()
.duration(1500)
.ease(d3.easeSinInOut)
//.attr("transform", "rotate(-45)")
.attr("transform", (d) => `rotate(${angle(d.temperature)})`)
.transition()
.duration(1500)
.ease(d3.easeSinInOut)
.attr("transform", "rotate(0)")
.end();
}
}
Insert cell
yamamotoLegend = {
const height = (width * 100) / 215;

const data = drinks;
const temperatureData = ["あたたかい", "つめたい", "常温", "その他"];
const locationData = ["自宅", "その他"];
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

const g = svg
.append("g")
.selectAll("g")
.data(data)
.join("g")
.attr("transform", (d, i) => `translate(10, ${20 + i * 20})`);

//g.append("circle").attr("r", 10).attr("fill",colorScale);
g.append("path")
.attr("d", starD)
.attr("fill", colorScale)
.attr("transform", "scale(0.02)");

g.append("text")
.attr("x", 30)
.attr("dy", 20)
.text((d) => d);

const lineG = svg
.append("g")
.selectAll("g")
.data(temperatureData)
.join("g")
.attr("transform", (d, i) => `translate(300, ${20 + i * 70})`);

lineG
.append("text")
.attr("x", 80)
.attr("dy", 55)
.text((d) => d);

lineG
.append("line")
.attr("stroke", "black")
.attr("x1", 40)
.attr("x2", angle)
.attr("y1", 40)
.attr("y2", 70);

// 容器の凡例
const locationG = svg
.append("g")
.selectAll("g")
.data(locationData)
.join("g")
.attr("transform", (d, i) => `translate(550, ${20 + i * 70})`);

locationG
.append("line")

.attr("stroke", "black")
.attr("x1", 40)
.attr("x2", 40)
.attr("y1", 40)
.attr("y2", locationXScale);

locationG
.append("text")
.attr("x", 60)
.attr("dy", 55)

.text((d) => d);

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more