Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
xuanx1 committed Oct 26, 2024
2 parents c0bf103 + d818512 commit 5cfeec8
Showing 1 changed file with 83 additions and 115 deletions.
198 changes: 83 additions & 115 deletions treemap/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -451,16 +451,21 @@ async function fetchData() {

console.log(root.leaves());

// Create group ID (ocean + newGroup)
const groupIDs = root
.leaves()
.map((d) => d.parent.data[0].replace(/\s+/g, '-') + '_' + d.data[0]);

// Create a group for each node
const nodes = svg
.selectAll('g')
.data(root.leaves())
.enter()
.append('g')
.attr('class', (d, i) => {
return root.leaves()[i].parent.data[0]; // Assuming this returns the class name
})
.attr('transform', (d) => `translate(${d.x0},${d.y0})`);
.attr('transform', (d) => `translate(${d.x0},${d.y0})`)
.attr('id', (d, i) => {
return `${groupIDs[i]}`;
});

// Define colourScale
const colourScale = d3
Expand Down Expand Up @@ -758,35 +763,35 @@ async function fetchData() {

function getDetailedData(ocean) {
switch (ocean) {
case 'Pacific':
case 'Pacific Ocean':
return {
Predator: pPredator,
Prey: pPrey,
Others: pOthers,
};
case 'Atlantic':
case 'Atlantic Ocean':
return {
Predator: atPredator,
Prey: atPrey,
Others: atOthers,
};
case 'Indian':
case 'Indian Ocean':
return {
Predator: iPredator,
Prey: iPrey,
Others: iOthers,
};
case 'South':
case 'South Ocean':
return {
Predator: sPredator,
Others: sOthers,
};
case 'North':
case 'North Sea':
return {
Predator: nPredator,
Others: nOthers,
};
case 'Arctic':
case 'Arctic Ocean':
return {
Predator: arPredator,
};
Expand Down Expand Up @@ -831,6 +836,66 @@ async function fetchData() {
//tree map description disappear when zoom in
description.transition().duration(500).style('opacity', 0);

// Aggregate the data for the selected ocean and archetype
const selectedSeaname = d.parent.data[0];
const selectedNewGroup = d.data[0];
let rolledupData = getDetailedData(selectedSeaname)[selectedNewGroup];
rolledupData = Array.from(rolledupData, ([key, value]) => ({
name: key,
value,
}));
rolledupData = rolledupData.sort((a, b) => b.value - a.value);

const secondTreemapRoot = d3
.hierarchy({ children: rolledupData }, (d) => d.children)
.sum((d) => d.value);

d3.treemap().size([width, height]).padding(3).round(true)(
secondTreemapRoot
);

// Create a group for each node
const groupID = `${selectedSeaname.replace(
/\s+/g,
'-'
)}_${selectedNewGroup}`;
const secondTreemap = d3.select(`#${groupID}`);

if (secondTreemap.empty()) {
secondTreemap = svg.append('g').attr('id', groupID);
}

secondTreemap
.selectAll('rect')
.data(secondTreemapRoot.leaves(), (d) => d.data.name)
.enter()
.append('rect')
.attr('class', 'detailed-node')
.attr('x', (d) => d.x0)
.attr('y', (d) => d.y0)
.attr('width', (d) => d.x1 - d.x0)
.attr('height', (d) => d.y1 - d.y0)
.attr('fill-opacity', 0.9)
.attr('stroke', 'none')
.attr('id', (d, i) => {
return `${groupID}_${d.data.name}`;
})
.attr('fill', colourScale(selectedSeaname));

secondTreemap
.selectAll('text')
.data(secondTreemapRoot.leaves(), (d) => d.data.name)
.enter()
.append('text')
.text((d) => d.data.name)
.attr('class', 'detailed-node')
.attr('x', (d) => d.x0 + 10)
.attr('y', (d) => d.y0 + 25)
.style('font-family', "'Open Sans', sans-serif")
.style('font-weight', 'regular')
.style('fill', 'white')
.style('font-size', '14px');

// Secondary Legend, appears when zoomed in and hides when zoom out --------------------------------------------
// Depth
const legendDepth = {
Expand Down Expand Up @@ -1036,103 +1101,6 @@ async function fetchData() {
.transition()
.duration(1200)
.style('opacity', 1);

// Fetch detailed data and update the treemap
const detailedData = getDetailedData(
'Pacific',
'Atlantic',
'Indian',
'South',
'North',
'Arctic'
);
console.log('Detailed Data:', detailedData);

if (Object.keys(detailedData).length > 0) {
const detailedRoot = d3
.hierarchy({
children: Object.entries(detailedData).map(([key, value]) => ({
name: key,
children: Array.from(value, ([depthRange, count]) => ({
name: getDepthRange(depthRange),
value: count,
})),
})),
})
.sum((d) => d.value)
.sort((a, b) => b.value - a.value);

console.log('Detailed Root:', detailedRoot);

treemapLayout(detailedRoot);

const detailedNodes = svg.selectAll(".detailed-node")
.data(detailedRoot.leaves())
.enter()
.append("g")
.attr("class", "detailed-node")
.attr("transform", node => `translate(${node.x0},${node.y0})`);


detailedNodes.append("rect")
.attr("width", node => node.x1 - node.x0)
.attr("height", node => node.y1 - node.y0)
.attr("fill", node => {
const parentColor = colourScale(node.parent.data.name);
const shade = d3.scaleLinear()
.domain([0, (detailedRoot.children ? detailedRoot.children.length : 1) - 1])
.range([0.3, 0.7]); // Make the shade range darker and wider
return d3.color(parentColor).darker(shade(detailedRoot.children ? detailedRoot.children.indexOf(node) : 1));
})
.attr("fill-opacity", 1)
.attr("stroke", "none");

detailedNodes.append("text")
.attr("x", 10)
.attr("y", 25)
.style("font-family", "'Open Sans', sans-serif")
.style("font-weight", "regular")
.style("fill", "white")
.style("font-size", node => {
const fontSize = Math.min((node.x1 - node.x0) / 5, (node.y1 - node.y0) / 5, 16);
return fontSize < 10 ? "0px" : `${fontSize}px`;
})
.text(node => getDepthRange(node.data.value))
.each(function(node) {
const bbox = this.getBBox();
if (bbox.width > (node.x1 - node.x0) || bbox.height > (node.y1 - node.y0)) {
d3.select(this).remove();
}
});

// Add fade-in and scale animation for the detailed nodes
setTimeout(() => {
detailedNodes.style("opacity", 0)
.attr("transform", node => `translate(${x(node.x0)},${y(node.y0)}) scale(0.1)`)
.transition()
.duration(1500)
.style("opacity", 0.9)
.attr("transform", node => `translate(${x(node.x0)},${y(node.y0)}) scale(1)`);
}, 2000);

detailedNodes.append("text")
.attr("x", 10)
.attr("y", 25)
.style("font-family", "'Open Sans', sans-serif")
.style("font-weight", "regular")
.style("fill", "white")
.style("font-size", node => {
const fontSize = Math.min((x(node.x1) - x(node.x0)) / 5, (y(node.y1) - y(node.y0)) / 5, 16);
return fontSize < 10 ? "0px" : `${fontSize}px`;
})
.text(node => getDepthRange(node.data.name))
.each(function(node) {
const bbox = this.getBBox();
if (bbox.width > (x(node.x1) - x(node.x0)) || bbox.height > (y(node.y1) - y(node.y0))) {
d3.select(this).remove();
}
});
}
}

nodes.on('click', function (event, d) {
Expand Down Expand Up @@ -1240,13 +1208,13 @@ async function fetchData() {
.html(
//find a way to make it flexible
`
<a href="${mergedData.record_link}" target="_blank">
<img src="${mergedData.thumbnail}" alt="Fish Thumbnail" style="width: 100px; height: auto; border-radius: 5px;"></a>
<br/><strong style="color: #098094;">${mergedData.common_name}</strong>
<br/><i style="color: #808080; font-size: 10pt;">${mergedData.title}</i>
<br/>Archetype: <strong style="color: #098094;">${mergedData.newGroup}</strong>
<br/>Depth: <strong style="color: #098094;">${mergedData.depth} m</strong>
<br/><br/><img src="https://stamen-tiles.a.ssl.fastly.net/watercolor/${mergedData.longitude}/${mergedData.latitude}/10/256.png" alt="Map" style="width: 100%; border-radius: 5px;">
<a href="${imgData.record_link}" target="_blank">
<img src="${imgData.thumbnail}" alt="Fish Thumbnail" style="width: 100px; height: auto; border-radius: 5px;"></a>
<br/><strong style="color: #098094;">${fishData.common_name}</strong>
<br/><i style="color: #808080; font-size: 10pt;">${fishData.title}</i>
<br/>Archetype: <strong style="color: #098094;">${fishData.newGroup}</strong>
<br/>Depth: <strong style="color: #098094;">${fishData.depth} m</strong>
<br/><br/><img src="https://stamen-tiles.a.ssl.fastly.net/watercolor/${fishData.longitude}/${fishData.latitude}/10/256.png" alt="Map" style="width: 100%; border-radius: 5px;">
`
);
})
Expand Down Expand Up @@ -1353,7 +1321,7 @@ async function fetchData() {
.style('text-align', 'center')
.style('padding-top', '50px')
.text(
'Major Studio I | Exercise 2: Qualitative Representation | Tak | Bella | Xuan'
'Major Studio I | Exercise 2: Qualitative Representation | Hyeonjeong | Xuan'
);
} catch (error) {
console.error('Error fetching or processing data:', error);
Expand Down

0 comments on commit 5cfeec8

Please sign in to comment.