chart = {
let employees;
let employeeNav;
const h = 700;
let faggruppe;
const fgIds = [40, 31];
const fills = ["blue", "red"];
const svg = d3
.create("svg")
.attr("width", w)
.attr("height", h)
.style("background", "#f4f4f5");
const t = svg.transition().duration(1000);
const alleAnsatte = svg.append("rect");
const design = svg.append("rect");
const teknologer = svg.append("rect");
const faggruppePadding = width * 0.08;
alleAnsatte
.style("fill", "black")
.attr("height", 20)
.attr("width", 20)
.attr("x", width - faggruppePadding)
.attr("y", 10)
.on("click", showAllEmployees);
design
.data([{ fgId: fgIds[0] }])
.style("fill", "blue")
.attr("height", 20)
.attr("width", 20)
.attr("x", width - faggruppePadding)
.attr("y", 40) // y position of the top-left corner
.on("click", filterFaggruppe);
teknologer
.data([{ fgId: fgIds[1] }])
.style("fill", "red") // rect's fill color
.attr("height", 20) // rect's height (in pixels)
.attr("width", 20) // rect's width (in pixels)
.attr("x", width - faggruppePadding) // x position of the top-left corner
.attr("y", 70) // y position of the top-left corner
.on("click", filterFaggruppe);
showAllEmployees();
return svg.node();
// ALL
function showAllEmployees() {
// const steps = 3;
// console.log(
// d3.range(steps).map(function (num) {
// return (num / steps) * (2 * Math.PI);
// })
// );
const t = svg.transition().duration(1000);
employees = svg
.selectAll("g")
.data(flatData, (d) => d.empId) //
.join(
(enter) =>
enter
.append("g")
.on("click", showSelected)
.attr("class", "circle-group")
.style("opacity", 0)
.style("fill", "none")
.attr("transform", (d) => `translate(${d.t.x},${d.t.y})`)
// Circle
// .append("circle")
// .attr("cx", 0)
// .attr("cy", 0)
// .attr("r", radius * 1.2)
// .attr("stroke-width", 2)
// .attr("stroke", (d) => (d.fgId === 40 ? "blue" : "red"))
.call((g) => drawProfilePic(g))
.call((g) => g.transition(t).style("opacity", 1)),
(update) =>
update
// .call((g) => g.select("circle").transition(t).attr("r", radius))
//.call((g) => g.transition(t).attr("r", radius))
.call((g) =>
g
.transition(t)
// .style("fill", "black")
.attr("transform", (d) => `translate(${d.t.x},${d.t.y})`)
),
(exit) => exit.remove()
)
.on("click", showSelected);
return employees;
}
// FAGGRUPPE SELECTION
function filterFaggruppe(d, e) {
const t = svg.transition().duration(700);
const faggruppe = e.fgId;
const filteredData = flatData.filter((emp) => emp.fgId === faggruppe);
console.log("filtered data", filteredData);
employees = svg.selectAll("g");
employees
.data(filteredData, (d) => d.empId)
.join(
(enter) =>
enter
.append("g")
.attr("class", "circle-group")
.style("opacity", 0)
// .style("fill", fills[fgIds.indexOf(faggruppe)])
// Re-append circle to G
// .call((g) =>g.append("circle").attr("cx", 0).attr("cy", 0).attr("r", radius))
.call((g) => drawProfilePic(g))
// //Add transition to G
.call((g) => g.transition(t).style("opacity", 1))
.attr(
"transform",
(d, i) =>
`translate(${radius * 1.5 + radius * 2.2 * (i % 10)},${
radius * 1.5 + Math.floor(i / 10) * (radius * 2.2)
})`
)
.on("click", showSelected),
(update) =>
update
.call((g) =>
g
.transition(t)
.style("opacity", 1)
// .style("fill", fills[fgIds.indexOf(faggruppe)])
.attr(
"transform",
(d, i) =>
`translate(${radius * 1.5 + radius * 2.2 * (i % 10)},${
radius * 1.5 + Math.floor(i / 10) * (radius * 2.2)
})`
)
) // Update circe
.call((g) => g.selectAll("circle").transition(t).attr("r", radius)),
(exit) => exit.remove()
);
}
// SELECTED
function showSelected(d, e) {
const filteredData = flatData.filter(
(employee) => employee.empId === e.empId
);
const t = svg.transition().duration(1000);
employees = svg
.selectAll("g")
.data(filteredData, (d) => d.empId)
.join(
(enter) => enter,
(update) =>
update
// .call((g) =>
// .attr("cy", 0)
// .attr("r", radius)
.transition(t)
//.attr("transform", (d) => `scale(2)`)
.attr("transform", (d) => `translate(${w / 2},${h / 2}) scale(4)`),
//.call(
//(g) => g.transition(t).attr("transform", (d) => `scale(4)`)
// (g) =>
// g
// .transition(t)
// .attr("transform", (d) => `translate(${w / 2},${h / 2})`)
//)
//.style("fill", "green")
// .call((g) => g.select("circle").transition(t).attr("r", 70)),
// .call((g) => g.transition(t).attr("r", 70))
//.on("click", faggruppe ? filterFaggruppe : showAllEmployees),
(exit) => exit.transition().duration(400).style("opacity", 0).remove()
);
}
// SELECTED
function drawProfilePic(g) {
// g.each((d) =>
// g
// .append("circle")
// .attr("cx", 0)
// .attr("cy", 0)
// .attr("r", radius * 1.2)
// .attr("stroke", (d) => (d.fgId === 40 ? "blue" : "red"))
// .attr("stroke-width", 2)
// );
g.append("defs")
.append("clipPath")
.attr("id", "employee_pfp")
.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", radius);
g.append("image")
.attr("x", (d) => (-1 * (radius * 2)) / Math.pow(2, 1))
.attr("y", (d) => (-1 * (radius * 2)) / Math.pow(2, 1))
.attr("height", radius * 2)
.attr("width", radius * 2)
.attr("clip-path", "url(#employee_pfp)")
.attr("href", `${kavianPfp}`);
g.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", radius)
.attr("stroke-width", 1.5)
.attr("fill", "none")
.attr("stroke", (d) => (d.fgId === 40 ? "blue" : "red"));
}
// EMPLOYEE NAV (Identical to filters, actually)
// Select clicked employeePfp. No need to append anything new right?
// (Maybe new group)
// Scale, Translate and Transition circle to center, fade all.
// Create flyCircle data
// Append flyCircle/Button to Employee circle.
// + and X don't need data. But they have different onFunctions..
//EmployeeNavButtons
}