Public
Edited
Jan 14, 2024
1 fork
Insert cell
Insert cell
viewof dataOfPerson = Inputs.radio(people, { label: "Person", value: people.get('Tsuchiya') })
Insert cell
dataOfPerson
Insert cell
pendulalumChart(dataOfPerson)
Insert cell
async function * pendulalumChart(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 xScale = d3
.scaleLinear()
.domain([0, 4])
.range([margin.left, width - margin.right]);

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

// const drinks = d3.group(data, (d) => d.drink);
// const color = d3
// .scaleOrdinal()
// .domain([...drinks.keys()])
// .range(d3.schemeCategory10);

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

const xAxis = d3
.axisBottom()
.scale(xScale)
.ticks(4)
.tickFormat((d) => [0, 6, 12, 18, 24][d])
.tickSize(-(height - margin.top - margin.bottom));
const yAxis = d3
.axisLeft()
.scale(yScale)
.ticks(7)
.tickFormat((d) => d3.timeFormat(`%m月%d日`)(d) + ` (${dow(d)})`)
.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("opacity", 0.1);

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])})`);

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');

pendulum.append('line')
.attr('y2', yScale.bandwidth()/2)
.attr('stroke', '#000');
pendulum.append('circle')
.attr('cy', yScale.bandwidth()/2)
.attr("r", 10)
.attr("fill", (d) => colorScale(d.drink))
.attr("opacity", 0.5);
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);


// animation
while (true) {
yield svg.node();
await pendulum.transition()
.duration(1500)
.ease(d3.easeSinInOut)
.attr('transform', 'rotate(45)')
.transition()
.duration(1500)
.ease(d3.easeSinInOut)
.attr('transform', 'rotate(-45)')
.end();
}
}
Insert cell
import {getDataOfDatesTimes, colorScale, people} from "@sugi2000lab/d3-js-introdunction-part-4-d3-js-4"
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