Skip to content

Commit 3c10d4a

Browse files
committed
Draft design of sponsor social card.
1 parent f3bacc8 commit 3c10d4a

File tree

3 files changed

+348
-0
lines changed

3 files changed

+348
-0
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
import { getEntry } from "astro:content";
3+
import SponsorLogo from "@components/SponsorLogo.astro";
4+
import { Image } from "astro:assets";
5+
import { sponsorLogos } from "@data/sponsorLogos";
6+
import { ta } from "date-fns/locale";
7+
8+
const { slug:sponsorId } = Astro.props;
9+
10+
const sponsor = await getEntry("sponsors", sponsorId);
11+
12+
if (!sponsor) {
13+
throw new Error(`Sponsor with ID "${sponsorId}" not found`);
14+
}
15+
16+
const {
17+
name: title,
18+
url: website,
19+
logo_padding = false,
20+
} = sponsor.data;
21+
22+
23+
const logo = sponsorLogos[sponsor.id];
24+
// Assuming logo.width and logo.height are known
25+
const targetWidth = 400;
26+
const aspectRatio = logo.width / logo.height;
27+
const targetHeight = targetWidth / aspectRatio;
28+
const maxHeight = 240;
29+
const realHeight = targetHeight < maxHeight? targetHeight : maxHeight;
30+
31+
const x = 650 - targetWidth/ 2;
32+
const y = 650 - realHeight / 2;
33+
---
34+
<svg width="900" height="900" class="h-full w-full -z-10">
35+
<image href="/social/bg.png" width="900" height="900" />
36+
</svg>
37+
<svg width="900" height="900">
38+
<defs>
39+
<clipPath id="curvedCornerClip">
40+
<path
41+
d="
42+
m 885 885 l -240 0 a 240 240 0 0 1 -240 -240 a 240 240 0 0 1 240 -240 a 240 240 0 0 1 240 240 z
43+
"
44+
/>
45+
</clipPath>
46+
</defs>
47+
48+
<path
49+
d="
50+
m 885 885 l -240 0 a 240 240 0 0 1 -240 -240 a 240 240 0 0 1 240 -240 a 240 240 0 0 1 240 240 z
51+
"
52+
fill="white"
53+
/>
54+
55+
<image
56+
class="sponsor_logo"
57+
href={logo.src}
58+
x={x}
59+
y={y}
60+
width={targetWidth}
61+
height={realHeight}
62+
style={{
63+
padding: logo_padding ? logo_padding : undefined,
64+
}}
65+
clip-path="url(#curvedCornerClip)"
66+
preserveAspectRatio="xMidYMid meet"
67+
/>
68+
</svg>
69+
<p
70+
class="box fit-text"
71+
>
72+
Thank you to our sponsor
73+
</p>
74+
75+
<p lang="en" class="box2 fit-text">
76+
{title}
77+
</p>
78+
79+
80+
<style>
81+
.box {
82+
margin-top:250px;
83+
width: 630px;
84+
height: 150px;
85+
font-size: 100px;
86+
color: rgb(239, 215, 123);
87+
padding: 1rem;
88+
}
89+
90+
.box2 {
91+
92+
width: 420px;
93+
height: 200px;
94+
font-size: 70px;
95+
color:white;
96+
padding: 2rem;
97+
}
98+
99+
.box3 {
100+
margin-top:280px;
101+
width: 800px;
102+
height: 300px;
103+
font-size: 100px;
104+
color: rgb(239, 215, 123);
105+
padding: 1rem;
106+
}
107+
108+
.box4 {
109+
110+
width: 580px;
111+
height: 200px;
112+
font-size: 70px;
113+
color:white;
114+
padding: 2rem;
115+
}
116+
117+
118+
.box, .box2, .box3, .box4 {
119+
box-sizing: border-box;
120+
overflow: hidden;
121+
display: flex;
122+
align-items: center;
123+
justify-content: center;
124+
text-align: center;
125+
font-family: Inter, sans-serif !important;
126+
font-weight: bold;
127+
line-height: 1em;
128+
}
129+
130+
.sponsor_logo {
131+
max-height:120px;
132+
}
133+
</style>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
import { getCollection, type CollectionEntry } from "astro:content";
3+
import SocialMediaSponsorCard from "@components/SocialMediaSponsorCard.astro";
4+
5+
6+
const sponsors = await getCollection("sponsors");
7+
type Sponsor = CollectionEntry<"sponsors">;
8+
---
9+
<!DOCTYPE html>
10+
<html lang="en">
11+
<head>
12+
<meta charset="utf-8" />
13+
<meta name="viewport" content="width=device-width,initial-scale=1" />
14+
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
15+
<link rel="preconnect" href="https://fonts.googleapis.com">
16+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
17+
<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet">
18+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html2canvas.min.js"></script>
19+
</head>
20+
<body class="overflow-auto">
21+
{
22+
sponsors.map((entry: Sponsor) => (
23+
<a href=`/media/card/${entry.data.slug}`>
24+
<div class="social relative w-[900px] h-[900px] overflow-hidden" data-slug={entry.data.slug}>
25+
<SocialMediaSponsorCard slug={entry.id} />
26+
</div>
27+
</a>
28+
))
29+
}
30+
31+
</body>
32+
</html>
33+
34+
<style is:global>
35+
36+
.social {
37+
width: 900px;
38+
height: 900px;
39+
}
40+
41+
.social svg {
42+
position: absolute;
43+
top:0;
44+
left:0;
45+
width: 100%;
46+
height: 100%;
47+
object-fit: contain;
48+
}
49+
50+
body * {
51+
font-family: Inter, sans-serif;
52+
}
53+
54+
.avatar {
55+
object-position:50% 25%;
56+
}
57+
58+
</style>
59+
60+
<script is:inline>
61+
function fitText(container) {
62+
let fontSize = 100; // Start big
63+
container.style.fontSize = fontSize + 'px';
64+
65+
while (
66+
(container.scrollWidth > container.clientWidth || container.scrollHeight > container.clientHeight)
67+
&& fontSize > 5
68+
) {
69+
fontSize -= 1;
70+
container.style.fontSize = fontSize + 'px';
71+
}
72+
}
73+
74+
function fitAllText() {
75+
const boxes = document.querySelectorAll('.fit-text');
76+
boxes.forEach(box => fitText(box));
77+
}
78+
79+
fitAllText();
80+
81+
window.addEventListener('resize', fitAllText);
82+
</script>
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
import { getCollection} from "astro:content";
3+
import SocialMediaSponsorCard from "@components/SocialMediaSponsorCard.astro";
4+
import { slugify } from "@utils/content";
5+
6+
7+
8+
export async function getStaticPaths() {
9+
const entries = await getCollection("sponsors");
10+
return entries.map((entry) => ({
11+
params: { slug: slugify(entry.data.name)},
12+
props: { entry },
13+
}));
14+
}
15+
16+
const { entry } = Astro.props;
17+
---
18+
<!DOCTYPE html>
19+
<html lang="en">
20+
<head>
21+
<meta charset="utf-8" />
22+
<meta name="viewport" content="width=device-width,initial-scale=1" />
23+
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
24+
<link rel="preconnect" href="https://fonts.googleapis.com">
25+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
26+
<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet">
27+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html2canvas.min.js"></script>
28+
</head>
29+
<body class="overflow-auto">
30+
{
31+
entry &&
32+
<div class="social relative w-[900px] h-[900px] overflow-hidden">
33+
<SocialMediaSponsorCard entry={entry} slug={slugify(entry.data.name)} />
34+
</div>
35+
}
36+
37+
</body>
38+
</html>
39+
40+
<style is:global>
41+
42+
.social {
43+
width: 900px;
44+
height: 900px;
45+
}
46+
47+
.social svg {
48+
position: absolute;
49+
top:0;
50+
left:0;
51+
width: 100%;
52+
height: 100%;
53+
object-fit: contain;
54+
}
55+
56+
body * {
57+
font-family: Inter, sans-serif;
58+
}
59+
60+
.avatar {
61+
object-position:50% 25%;
62+
}
63+
64+
</style>
65+
66+
<script is:inline>
67+
function fitText(container) {
68+
let fontSize = 100; // Start big
69+
container.style.fontSize = fontSize + 'px';
70+
71+
while (
72+
(container.scrollWidth > container.clientWidth || container.scrollHeight > container.clientHeight)
73+
&& fontSize > 5
74+
) {
75+
fontSize -= 1;
76+
container.style.fontSize = fontSize + 'px';
77+
}
78+
}
79+
80+
function fitAllText() {
81+
const boxes = document.querySelectorAll('.fit-text');
82+
boxes.forEach(box => fitText(box));
83+
}
84+
85+
fitAllText();
86+
87+
window.addEventListener('resize', fitAllText);
88+
</script>
89+
90+
<script is:inline define:vars={{slug: entry.data.slug}}>
91+
document.addEventListener('DOMContentLoaded', () => {
92+
document.querySelectorAll('.social').forEach((socialDiv, index) => {
93+
94+
socialDiv.addEventListener('click', () => {
95+
const svgs = socialDiv.querySelectorAll('svg');
96+
97+
if (svgs.length === 0) {
98+
alert('No SVGs found!');
99+
return;
100+
}
101+
102+
const xmlns = "http://www.w3.org/2000/svg";
103+
const combinedSvg = document.createElementNS(xmlns, "svg");
104+
combinedSvg.setAttribute("xmlns", xmlns);
105+
combinedSvg.setAttribute("width", "900");
106+
combinedSvg.setAttribute("height", "900");
107+
combinedSvg.setAttribute("viewBox", "0 0 900 900");
108+
109+
svgs.forEach(svg => {
110+
const g = document.createElementNS(xmlns, "g");
111+
g.innerHTML = svg.innerHTML;
112+
combinedSvg.appendChild(g);
113+
});
114+
115+
const serializer = new XMLSerializer();
116+
const svgString = serializer.serializeToString(combinedSvg);
117+
118+
const blob = new Blob([svgString], {type: "image/svg+xml"});
119+
const url = URL.createObjectURL(blob);
120+
121+
const a = document.createElement('a');
122+
a.href = url;
123+
a.download = slug ? `social-${slug}.svg` : `social-${index +1}.svg`;
124+
a.style.display = "none";
125+
document.body.appendChild(a);
126+
a.click();
127+
128+
URL.revokeObjectURL(url);
129+
document.body.removeChild(a);
130+
});
131+
});
132+
});
133+
</script>

0 commit comments

Comments
 (0)