Skip to content

Commit 41d56b4

Browse files
committed
feat: 🎸 Add tags cloud for skills
1 parent bae1f28 commit 41d56b4

File tree

8 files changed

+406
-42
lines changed

8 files changed

+406
-42
lines changed

‎site/data/cloud.json

Lines changed: 178 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,196 @@
11
{
22
"cloud": [
33
{
4-
"weight": 30,
4+
"id": "cloud-vuejs",
5+
"weight": 10,
56
"text": "Vue.js",
67
"label": "DossierFacile, Chapitô"
78
},
89
{
9-
"weight": 30,
10+
"id": "cloud-reactjs",
11+
"weight": 10,
1012
"text": "React.js",
11-
"label": " "
13+
"label": ""
1214
},
1315
{
14-
"weight": 30,
16+
"id": "cloud-java",
17+
"weight": 10,
1518
"text": "Java",
1619
"label": "Filbleu, TAO, Chapitô, DossierFacile, Wegrow, LeroySomer"
1720
},
1821
{
19-
"text": "PostgreSQL",
20-
"weight": 15,
22+
"id": "cloud-kotlin",
23+
"weight": 10,
24+
"text": "Kotlin",
25+
"label": ""
26+
},
27+
{
28+
"id": "cloud-springboot",
29+
"weight": 10,
30+
"text": "SpringBoot",
31+
"label": "Chapitô, DossierFacile, Wegrow"
32+
},
33+
{
34+
"id": "cloud-nodejs",
35+
"weight": 10,
36+
"text": "Node.js",
37+
"label": "Virtuo"
38+
},
39+
{
40+
"id": "android",
41+
"weight": 9,
42+
"text": "Android",
43+
"label": "Filbleu, TAO, Chapitô"
44+
},
45+
{
46+
"id": "cloud-ios",
47+
"weight": 9,
48+
"text": "iOS",
49+
"label": "Filbleu, TAO, Chapitô"
50+
},
51+
{
52+
"id": "cloud-swift",
53+
"weight": 9,
54+
"text": "Swift",
55+
"label": "Filbleu, TAO, Chapitô"
56+
},
57+
{
58+
"id": "cloud-angular",
59+
"weight": 8,
60+
"text": "Angular",
61+
"label": "Soletanche, Eutelmed, Wegrow, Fizzer"
62+
},
63+
{
64+
"id": "cloud-docker",
65+
"weight": 8,
66+
"text": "Docker",
67+
"label": ""
68+
},
69+
{
70+
"id": "cloud-kubernetes",
71+
"weight": 8,
72+
"text": "Kubernetes",
73+
"label": "Chapitô, Filbleu, TAO, Wakiki"
74+
},
75+
{
76+
"id": "cloud-typescript",
77+
"weight": 8,
78+
"text": "Typescript",
79+
"label": "Tous ou presque"
80+
},
81+
{
82+
"id": "cloud-keycloak",
83+
"weight": 7,
84+
"text": "Keycloak",
85+
"label": "DossierFacile, Wakiki"
86+
},
87+
{
88+
"id": "cloud-javascript",
89+
"weight": 7,
90+
"text": "Javascript",
91+
"label": ""
92+
},
93+
{
94+
"id": "cloud-golang",
95+
"weight": 5,
96+
"text": "Golang",
97+
"label": "Projets perso"
98+
},
99+
{
100+
"id": "cloud-html",
101+
"weight": 5,
102+
"text": "html",
103+
"label": "Tous ou presque"
104+
},
105+
{
106+
"id": "cloud-css",
107+
"weight": 5,
108+
"text": "css",
109+
"label": "Tous ou presque"
110+
},
111+
{
112+
"id": "cloud-sass",
113+
"weight": 5,
114+
"text": "sass",
115+
"label": "Tous ou presque"
116+
},
117+
{
118+
"id": "cloud-git",
119+
"weight": 5,
120+
"text": "Git",
121+
"label": "Évidemment"
122+
},
123+
{
124+
"id": "cloud-postgresql",
125+
"weight": 5,
126+
"text": "Postgresql",
127+
"label": ""
128+
},
129+
{
130+
"id": "cloud-githubaction",
131+
"weight": 5,
132+
"text": "Github action",
133+
"label": "DossierFacile"
134+
},
135+
{
136+
"id": "cloud-gitlabci",
137+
"weight": 5,
138+
"text": "Gitlab CI",
139+
"label": ""
140+
},
141+
{
142+
"id": "cloud-matomo",
143+
"weight": 3,
144+
"text": "Matomo",
21145
"label": "DossierFacile, Chapitô"
146+
},
147+
{
148+
"id": "cloud-mysql",
149+
"weight": 3,
150+
"text": "MySQL (MariaDB)",
151+
"label": ""
152+
},
153+
{
154+
"id": "cloud-mongo",
155+
"weight": 3,
156+
"text": "Mongo",
157+
"label": ""
158+
},
159+
{
160+
"id": "cloud-clevercloud",
161+
"weight": 1,
162+
"text": "Clever Cloud",
163+
"label": "Wegrow"
164+
},
165+
{
166+
"id": "cloud-scalingo",
167+
"weight": 1,
168+
"text": "Scalingo",
169+
"label": "DossierFacile"
170+
},
171+
{
172+
"id": "cloud-elasticsearch",
173+
"weight": 1,
174+
"text": "ElasticSearch",
175+
"label": "Carrefour"
176+
},
177+
{
178+
"id": "cloud-jquery",
179+
"weight": 2,
180+
"text": "JQuery",
181+
"label": "LeroySomer"
182+
},
183+
{
184+
"id": "cloud-hibernate",
185+
"weight": 2,
186+
"text": "Hibernate",
187+
"label": "DossierFacile, Wegrow, Chapitô, Eutelmed, Soletanche"
188+
},
189+
{
190+
"id": "cloud-hugo",
191+
"weight": 1,
192+
"text": "Hugo",
193+
"label": "Ce site :)"
22194
}
23195
]
24196
}

‎site/layouts/blog/li.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{{ $baseurl := .Site.BaseURL }}
22

3-
<div>
3+
<div class="blog-snippet-container">
4+
<div class="blog-snippet">
45
{{ if .Truncated }}
56
<a title="En savoir plus sur {{ .Title }}" href="{{ .Permalink }}">
67
{{ end }}
@@ -32,4 +33,5 @@ <h2>
3233
</a>
3334
{{ end }}
3435
</div>
36+
</div>
3537
</div>

‎site/layouts/partials/cloud.html

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
<section id="cloud">
22
<div class="wrapper">
3-
{{ range .Site.Data.cloud.cloud }}
4-
<div title="{{ .label }}">{{ .text }}</div>
5-
{{ end }}
3+
<div>
4+
{{ range (shuffle (.Site.Data.cloud.cloud)) }}
5+
<span class="cspan" id="{{ .id }}" title="{{ .label }}">{{ .text }}</span>
6+
{{ end }}
7+
</div>
8+
<div class="cloud">
9+
10+
</div>
611
</div>
12+
<script type="module" src="/js/cloud.js"></script>
713
</section>

‎site/layouts/partials/head.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@
2323
{{ if .IsHome }}
2424
<script src="https://identity.netlify.com/v1/netlify-identity-widget.js"></script>
2525
{{ end }}
26+
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
2627
</head>

‎site/static/js/cloud.js

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
2+
(async function($) {
3+
4+
const isOverlapping = function(element, otherElements) {
5+
const isOverlapping = (first, second) => {
6+
const fLeft = first.offsetLeft, fRight = fLeft + first.offsetWidth,
7+
sLeft = second.offsetLeft, sRight = sLeft + second.offsetWidth;
8+
const fTop = first.offsetTop, fBottom = fTop + first.offsetHeight,
9+
sTop = second.offsetTop, sBottom = sTop + second.offsetHeight;
10+
return !(fLeft >= sRight || sLeft >= fRight || fTop >= sBottom || sTop >= fBottom);
11+
};
12+
return otherElements.some((otherElement) => isOverlapping(element, otherElement));
13+
};
14+
15+
function isIntoView(elem)
16+
{
17+
var documentViewTop = $(window).scrollTop();
18+
var documentViewBottom = documentViewTop + $(window).height();
19+
20+
var elementTop = $(elem).offset().top;
21+
var elementBottom = elementTop + $(elem).height();
22+
23+
return ((elementBottom <= documentViewBottom) && (elementTop >= documentViewTop));
24+
}
25+
26+
$.fn.wordCloud = function(word_array) {
27+
var $this = this;
28+
var width = $this.width();
29+
var height = $this.height();
30+
var center = {
31+
x: width / 2.0,
32+
y: height / 2.0
33+
};
34+
35+
var step = 1.0;
36+
var placedWords = [];
37+
var ratio = width / height;
38+
39+
var drawTag = function(word) {
40+
$(`#${word.id}`).fadeOut(500, function() {
41+
$(`#${word.id}`).remove();
42+
});
43+
var radius = Math.random();
44+
45+
var wSpan = $("<span>").addClass("word w" + word.weight).append(word.text);
46+
47+
$this.append(wSpan);
48+
49+
var wWidth = wSpan.width();
50+
var wHeight = wSpan.height();
51+
var left = center.x - wWidth / 2.0;
52+
var top = center.y - wHeight / 2.0;
53+
54+
var word_style = wSpan[0].style;
55+
word_style.transitionDuration = "0.0s";
56+
word_style.position = "absolute";
57+
word_style.left = left + "px";
58+
word_style.top = top + "px";
59+
60+
while (isOverlapping(wSpan[0], placedWords)) {
61+
word_style.opacity = "0";
62+
radius += step;
63+
left = center.x - (wWidth / 2.0) + (radius * Math.cos(radius)) * ratio;
64+
top = center.y + radius * Math.sin(radius) - (wHeight / 2.0);
65+
word_style.left = left + "px";
66+
word_style.top = top + "px";
67+
}
68+
69+
word_style.transitionDuration = "1.0s";
70+
word_style.opacity = "1";
71+
72+
placedWords.push(wSpan[0]);
73+
};
74+
75+
var runWord = function(i) {
76+
if (i >= word_array.length) {
77+
return;
78+
}
79+
if (isIntoView($(".cloud"))) {
80+
drawTag(word_array[i]);
81+
setTimeout(() => {
82+
runWord(i + 1);
83+
}, 150);
84+
} else {
85+
setTimeout(() => {
86+
runWord(i);
87+
}, 500);
88+
}
89+
};
90+
runWord(0);
91+
92+
return $this;
93+
};
94+
95+
const data = await (await fetch("/data/cloud.json")).json();
96+
const cloud = data.cloud.sort(function(a, b) { return a.text < b.text ? 1 : -1; });
97+
var started = false;
98+
99+
const runWhenInView = function() {
100+
if (isIntoView($(".cloud")) && !started) {
101+
started = true;
102+
$(".cloud").wordCloud(cloud);
103+
}
104+
};
105+
106+
runWhenInView();
107+
$(window).on("scroll", runWhenInView);
108+
109+
110+
})(jQuery);

0 commit comments

Comments
 (0)