Skip to content

Commit d652f63

Browse files
authored
Punk Blockie (#30)
1 parent 456127e commit d652f63

File tree

4 files changed

+58
-11
lines changed

4 files changed

+58
-11
lines changed

packages/nextjs/app/builders/[address]/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { UserChallengesTable } from "../_component/UserChallengesTable";
22
import { UserSocials } from "../_component/UserSocials";
3+
import { PunkBlockie } from "~~/components/PunkBlockie";
34
import { findUserChallengesByAddress } from "~~/services/database/repositories/userChallenges";
45
import { findUserByAddress } from "~~/services/database/repositories/users";
56

@@ -15,6 +16,7 @@ export default async function BuilderPage({ params }: { params: { address: strin
1516

1617
return (
1718
<div className="flex flex-col gap-8">
19+
<PunkBlockie address={userAddress} scale={2} />
1820
<UserSocials user={user} />
1921
<UserChallengesTable challenges={challenges} />
2022
</div>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from "react";
2+
import { blo } from "blo";
3+
4+
// punk size with scale = 1
5+
const PUNK_SIZE = 112;
6+
// punk size pixels in the original file
7+
const ORIGINAL_PUNK_SIZE = 24;
8+
const PUNK_SIZE_RATIO = PUNK_SIZE / ORIGINAL_PUNK_SIZE;
9+
10+
interface PunkBlockieProps {
11+
address: string;
12+
scale?: number;
13+
width?: number;
14+
className?: string;
15+
}
16+
17+
export const PunkBlockie = ({ address, scale, width, className }: PunkBlockieProps) => {
18+
const part1 = address?.slice(2, 22);
19+
const part2 = address?.slice(-20);
20+
21+
const backgroundPositionX = parseInt(part1, 16) % 100;
22+
const backgroundPositionY = parseInt(part2, 16) % 100;
23+
24+
const computedScale = width ? width / PUNK_SIZE : (scale ?? 1);
25+
26+
return (
27+
<div
28+
className={`relative block overflow-hidden m-0 ${className}`}
29+
style={{
30+
width: PUNK_SIZE * computedScale,
31+
height: PUNK_SIZE * computedScale,
32+
}}
33+
>
34+
<div className="opacity-40 absolute inset-0">
35+
{/* eslint-disable-next-line @next/next/no-img-element */}
36+
<img alt={address} src={blo(address as `0x${string}`, PUNK_SIZE * computedScale)} />
37+
</div>
38+
<div
39+
className="absolute inset-0 bg-no-repeat [image-rendering:pixelated]"
40+
style={{
41+
backgroundImage: "url(/punks.png)",
42+
backgroundSize: `${2400 * PUNK_SIZE_RATIO * computedScale}px ${2400 * PUNK_SIZE_RATIO * computedScale}px`,
43+
backgroundPosition: `${-PUNK_SIZE * backgroundPositionX * computedScale}px ${-PUNK_SIZE * backgroundPositionY * computedScale}px`,
44+
}}
45+
/>
46+
</div>
47+
);
48+
};
Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
11
"use client";
22

3+
import { PunkBlockie } from "../PunkBlockie";
34
import { AvatarComponent } from "@rainbow-me/rainbowkit";
4-
import { blo } from "blo";
55

6-
// Custom Avatar for RainbowKit
7-
export const BlockieAvatar: AvatarComponent = ({ address, ensImage, size }) => (
6+
export const BlockieAvatar: AvatarComponent = ({ address, ensImage, size }) => {
7+
if (!ensImage) {
8+
return <PunkBlockie address={address} width={size} className="rounded-full" />;
9+
}
10+
811
// Don't want to use nextJS Image here (and adding remote patterns for the URL)
912
// eslint-disable-next-line @next/next/no-img-element
10-
<img
11-
className="rounded-full"
12-
src={ensImage || blo(address as `0x${string}`)}
13-
width={size}
14-
height={size}
15-
alt={`${address} avatar`}
16-
/>
17-
);
13+
return <img className="rounded-full" src={ensImage} width={size} height={size} alt={`${address} avatar`} />;
14+
};

packages/nextjs/public/punks.png

828 KB
Loading

0 commit comments

Comments
 (0)