Published
Edited
Sep 24, 2019
Insert cell
Insert cell
chart = {
const dataset = [
{start: new Date("2019-09-23 1:00 AM"), target: 70},
{start: new Date("2019-09-23 8:00 AM"), target: 75},
{start: new Date("2019-09-23 9:00 PM"), target: 70},
{start: new Date("2019-09-23 1:00 PM"), target: 75},
{start: new Date("2019-09-23 5:00 PM"), target: 70},
{start: new Date("2019-09-23 6:00 PM"), target: 65},
]

var xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, function(d) {
return d.x_pos
})]).range([0, width]);
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("stroke-width", 2);
const axis = svg.append("g")
.attr('id', 'xAxis')
.call(xAxis)

function drawCircleGroups(dataset) {
const circleContainer = svg.append('g').attr('id','circleContainer')
var group = circleContainer.selectAll('g')
.data(dataset)
.enter()
.append("g")
.attr('id', d => d.target)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("click", removeElement);
group.append("circle")
.attr("cx", d => x(d.start))
.attr("cy", 55)
.attr("r", 30)
.attr("fill", "red")

group.append("text")
.attr("x", function(d) { return x(d.start) - 10; })
.attr("y", function(d) { return 60; })
.style("fill", "white")
.text(function(d) { return d.target })
}
drawCircleGroups(dataset)
// when clicking on the axis (not on a circle group) then add a new circle
axis.on("click", function() {
var coords = d3.mouse(this);

console.log("x is ", x.invert(d3.event.x))
var newData = {
start: x.invert(d3.event.x),
target: 0
};

console.log(newData)
dataset.push(newData);
drawCircleGroups(dataset);
// group.append("circle")
// .attr("cx", function(d) {
// return x(d.start);
// })
// .attr("cy", function(d) {
// return 55;
// })
// .attr("r", 30)
// .style("fill", "red")
// .attr('id', function(d, i) {
// return 'circle_' + i;
// })
// .call(d3.drag()
// .on("start", dragstarted)
// .on("drag", dragged)
// .on("end", dragended))
// .on("click", removeElement);

// group.append("text")
// .data(dataset)
// .enter()
// .append("text")
// .attr("x", function(d) { return x(d.start) - 10; })
// .attr("y", function(d) { return 60; })
// .style("fill", "white")
// .text(function(d) { return d.target })
// .call(d3.drag()
// .on("drag", dragged))
// .on("click", removeElement)
})

function dragstarted(d) {
d3.select(this).raise().attr("stroke", "black");
}

function dragged(d) {
d3.select(this).selectAll('circle') // .selectAll("circle") not working....
.attr("cx", d.x = d3.event.x)
.attr("cy", d.y = 55);
d3.select(this).selectAll('text') // .selectAll("text") not working....
.attr("x", d.x = d3.event.x - 10)
.attr("y", d.y = 60);
}

function dragended(d) {
d3.select(this).attr("stroke", null);
}

function removeElement(d) {
d3.event.stopPropagation()
d3.select(this)
.remove();
}
return svg.node();
}
Insert cell
x = d3.scaleTime()
.domain([new Date("2019, 9, 23 12:00 AM"), new Date("2019, 9, 23, 11:59 PM")])
.rangeRound([margin.left, width - margin.right])
Insert cell
interval = d3.timeHour.every(1)
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(g => g.append("g")
.call(d3.axisBottom(x)
.ticks(interval)
.tickSize(-height + margin.top + margin.bottom)
.tickFormat(() => null))
.call(g => g.select(".domain")
.attr("fill", "#ddd")
.attr("stroke", null))
.call(g => g.selectAll(".tick line")
.attr("stroke", "#fff")
.attr("stroke-opacity", d => d <= d3.timeHour(d) ? 1 : 0.5)))
.call(g => g.append("g")
.call(d3.axisBottom(x)
.ticks(d3.timeHour)
.tickPadding(0))
.attr("text-anchor", null)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll("text").attr("x", 6)))
Insert cell
margin = ({top: 10, right: 0, bottom: 20, left: 0})
Insert cell
height = 120
Insert cell
d3 = require("d3@5")
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