-
Notifications
You must be signed in to change notification settings - Fork 0
/
venn.js
211 lines (186 loc) · 5.88 KB
/
venn.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
let randColors = [];
let randX = [];
let randY = [];
let randR = [];
let opacity = 80;
let activeCourse = null;
let highlightedCircles = [];
// Initialize the Venn Diagram in the center
function setup() {
const canvasContainer = select("#venn-diagram");
const canvas = createCanvas(windowWidth, windowHeight);
canvas.parent(canvasContainer);
// Generate random values for colors, positions, and radii for each area of study
areasOfStudy.forEach((area, index) => {
randColors[index] = [
random(100, 255),
random(100, 255),
random(100, 255),
opacity,
];
randR[index] = random(100, 200);
randY[index] = random(height * 0.25, height * 0.8);
randX[index] = random(width * 0.3, width * 0.7);
area.x = randX[index];
area.y = randY[index];
area.r = randR[index];
area.color = randColors[index];
});
renderCourseList();
renderAreas();
plotCourseDots();
}
function draw() {
// Clear the background and redraw areas and highlighted circles
background(250);
renderAreas();
// Draw any highlighted circles from the active course
highlightedCircles.forEach((area) => {
fill(area.color[0], area.color[1], area.color[2], 100); // Higher opacity for highlight
stroke(area.color[0], area.color[1], area.color[2]);
ellipse(area.x, area.y, area.r * 2);
});
if (activeCourse) {
drawConnections();
}
plotCourseDots();
}
function renderAreas() {
areasOfStudy.forEach((area) => {
fill(...area.color);
noStroke();
ellipse(area.x, area.y, area.r * 2);
});
}
function renderCourseList() {
const courseListDiv = select("#course-list");
courses.forEach((course) => {
const courseItem = createDiv(course.name)
.parent(courseListDiv)
.addClass("p-2 my-2 cursor-pointer hover:shadow rounded text-gray-800");
courseItem.mousePressed(() => toggleCourseDescription(course, courseItem));
});
}
function toggleCourseDescription(course, courseItem) {
// Clear the shadow class from all items first
if (highlightedCircles.length > 0) {
highlightedCircles = [];
}
selectAll("#course-list div").forEach((el) => {
el.removeClass("shadow-lg");
el.removeClass("border");
el.removeClass("border-gray-900");
});
if (activeCourse === course) {
activeCourse = null;
clearHighlights();
} else {
activeCourse = course;
highlightTags(course.tags);
plotCourseDots();
courseItem.addClass("shadow-lg border border-gray-900"); // Add shadow class to highlight the selected course
}
}
function highlightTags(tags) {
clearHighlights();
tags.forEach((tag) => {
const area = areasOfStudy.find((area) => area.tag === tag);
if (area) {
highlightedCircles.push(area); // Add area to highlighted circles array
displayDescription(area);
}
});
}
function clearHighlights() {
selectAll(".description").forEach((el) => el.remove());
background(255);
renderAreas();
plotCourseDots();
}
function displayDescription(area) {
const descriptionBox = select("#description-box");
const descriptionDiv = createDiv()
.parent(descriptionBox)
.addClass(
"description p-2 mb-2 shadow-lg rounded bg-slate-50 bg-opacity-50"
);
descriptionDiv.html(`<strong>${area.name}</strong>: ${area.description}`);
}
function plotCourseDots() {
courses.forEach((course) => {
let avgX = 0;
let avgY = 0;
let count = 0;
// Calculate the average center based on the tagged areas
course.tags.forEach((tag) => {
const area = areasOfStudy.find((area) => area.tag === tag);
if (area) {
avgX += area.x;
avgY += area.y;
count++;
}
});
if (count > 0) {
avgX /= count;
avgY /= count;
r = map(randX[count], width * 0.3, width * 0.7, 10, 155);
g = map(randY[count], width * 0.2, width * 0.8, 50, 255);
b = map(randR[count], 100, 200, 10, 255);
// Set dot color based on whether the course is active
if (activeCourse === course) {
fill(255, 0, 0); // Red dot for the active course
} else {
fill(r, g, b, 50);
}
noStroke();
ellipse(avgX, avgY, 10, 10); // Dot size is 10 pixels
// Store the average position to use in connection drawing
course.avgX = avgX;
course.avgY = avgY;
}
});
}
function drawConnections() {
if (activeCourse) {
// Connect Course List Item to Dot
const courseListItem = document.querySelector(
`#course-list div:nth-child(${courses.indexOf(activeCourse) + 1})`
);
if (courseListItem) {
const courseItemPos = courseListItem.getBoundingClientRect();
strokeWeight(1);
stroke(0); // Fixed red color for this line
line(
courseItemPos.right,
courseItemPos.top + courseItemPos.height / 2,
activeCourse.avgX,
activeCourse.avgY
);
}
// Connect the centers of tagged circles
let lastCenter = null;
activeCourse.tags.forEach((tag) => {
const area = areasOfStudy.find((area) => area.tag === tag);
if (area) {
// Set stroke to the area's color for line between centers
stroke(area.color[0] - 50, area.color[1] - 50, area.color[2] - 50, 150);
strokeWeight(2);
line(activeCourse.avgX, activeCourse.avgY, area.x, area.y);
}
});
// Connect Area Circles to Area Descriptions
const descriptionBox = document.getElementById("description-box");
if (descriptionBox) {
const descriptions = descriptionBox.querySelectorAll(".description");
activeCourse.tags.forEach((tag, index) => {
const area = areasOfStudy.find((area) => area.tag === tag);
if (area) {
const desc = descriptions[index];
const rect = desc.getBoundingClientRect();
stroke(area.color[0], area.color[1], area.color[2], 150); // Line color matches highlighted circle
line(area.x, area.y, rect.left, rect.top + rect.height / 2);
}
});
}
}
}