Skip to content

Commit ab29779

Browse files
committed
Pixel art fun with Alpine.js.
1 parent 937bf05 commit ab29779

File tree

8 files changed

+897
-449
lines changed

8 files changed

+897
-449
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ with.
1010

1111
## My JavaScript Demos - I Love JavaScript!
1212

13+
* [Pixel Art With Alpine.js](https://bennadel.github.io/JavaScript-Demos/demos/pixel-art-alpine)
1314
* [Movie Ranking With Sortable.js And Kendall Tau Distance](https://bennadel.github.io/JavaScript-Demos/demos/movie-rank)
1415
* [Using :scope To Identify The Host Element In A CSS Selector](https://bennadel.github.io/JavaScript-Demos/demos/scope-pseudo-class)
1516
* [Comparing Undefined Values In JavaScript](https://bennadel.github.io/JavaScript-Demos/demos/undefined-comparison)

demos/pixel-art-alpine/index.htm

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>
7+
Pixel Art With Alpine.js
8+
</title>
9+
<link rel="stylesheet" type="text/css" href="./main.css">
10+
<script type="text/javascript" src="./palette.js" defer></script>
11+
<script type="text/javascript" src="./main.js" defer></script>
12+
<script type="text/javascript" src="../../vendor/alpine/3.13.5/alpine.3.13.5.min.js" defer></script>
13+
</head>
14+
<body>
15+
16+
<main
17+
x-data="Demo"
18+
data-width="25"
19+
data-height="25"
20+
@mouseup.window="stopDrawing()"
21+
@hashchange.window="handleHashchange()"
22+
@keydown.meta.z.window="handleDo( event )"
23+
@keydown.ctrl.z.window="handleDo( event )">
24+
25+
<h1>
26+
<a href="./index.htm">Pixel Art With Alpine.js</a>
27+
</h1>
28+
29+
<!-- Rendered canvas. -->
30+
<div class="grid">
31+
<template x-for="( pixel, i ) in pixels" :key="i">
32+
<button
33+
@mousedown="startDrawing( $event, i )"
34+
@mouseenter="enterPixel( $event, i )"
35+
:style="{ backgroundColor: pixel?.hex }">
36+
</button>
37+
</template>
38+
</div>
39+
40+
<!-- Color palette. -->
41+
<div class="palette">
42+
<template x-for="option in palette.swatches">
43+
<button
44+
@mousedown="selectSwatch( option )"
45+
:title="option.name"
46+
:style="{ backgroundColor: option.hex }"
47+
:class="{ 'isSelected': ( option === foregroundSwatch ) }">
48+
</button>
49+
</template>
50+
</div>
51+
52+
<dl class="selected">
53+
<div>
54+
<dt>Name:</dt>
55+
<dd x-text="foregroundSwatch.name"></dd>
56+
</div>
57+
<div>
58+
<dt>Hex:</dt>
59+
<dd x-text="foregroundSwatch.hex"></dd>
60+
</div>
61+
</dl>
62+
63+
<div class="fillers">
64+
<button @click="clearCanvas()">
65+
Clear Canvas
66+
<span :style="{ backgroundColor: foregroundSwatch.hex }"></span>
67+
</button>
68+
<button @click="changeCanvasBackground()">
69+
Set Background
70+
<span :style="{ backgroundColor: foregroundSwatch.hex }"></span>
71+
</button>
72+
</div>
73+
74+
<div class="tuggers">
75+
<button @click="pullCanvasCenter()">
76+
Center
77+
</button>
78+
<button @click="pullCanvasUp()">
79+
Up
80+
</button>
81+
<button @click="pullCanvasDown()">
82+
Down
83+
</button>
84+
<button @click="pullCanvasLeft()">
85+
Left
86+
</button>
87+
<button @click="pullCanvasRight()">
88+
Right
89+
</button>
90+
</div>
91+
92+
<div class="tips">
93+
<p>
94+
Use <kbd>CMD</kbd>+Click to sample a pixel.
95+
</p>
96+
<p>
97+
Use <kbd>ALT</kbd>+Click to erase a pixel.
98+
</p>
99+
<p>
100+
Use <kbd>CMD+Z</kbd> to undo pixel and <kbd>Shift+CMD+Z</kbd> to redo pixel.
101+
</p>
102+
</div>
103+
104+
<div class="examples">
105+
<a href="#a,a,a:30,14:3,a:3,14:3,a:f,14,15:4,b,15:4,14,a:d,14,15:b,14,a:c,14,15:b,17,a:c,14,15:b,17,a:c,b,15:a,17,b,a:d,b,15:8,17,b,a:f,b,15:6,17,b,a:h,b,15:4,17,b,a:j,b,15:2,17,b,a:l,b,17,b,a:n,b,a:2h,d,a,d,a:3,d:2,c,a,c,d,c,a,c,d:2,a,d,a,d,a:4,d,b,d,a:3,d,b,d,a,d,b,d,a,d,a:3,d:2,b,a:4,d,b,d,a:3,d:2,b,a,d,b,d,a,d,a:3,d,b,d,a:4,c,d,c,a:3,d,b,d,a,c,d,c,a,c,d:2,a,d,b,d,a:5,b:2,a:3,b,a,b,a,b:3,a:2,b:2,a,b,a,b,a:r">Heart</a>
106+
<a href="#d,3j,3j:2y,c,3j:b,c,3j:b,c,3j:5,3i,3j,3i,3j:5,c,3j:a,c,3j:5,c,3i,c,3j:5,c,3j:a,c,3j:5,c,3i,c,3j:5,c,3j:a,c,3j:5,c,3i,c,3j:5,c,3j:a,c,3j,d,c,3j,3i,c,3h,c,3i,3j,c,d,3j,c,3j:a,c,3j,d:2,3j,2t,c,2t,c,2t,3j,d:2,3j,c,3j:a,3h,c,3i:3,c,2t,3j,2t,c,3i:3,c,3h,3j:b,3h,c:3,2t,3j:3,2t,c:3,3h,3j:d,3i:3,3j:5,3i:3,3j:32,d:2,c,3j,c,d,c,3j,c,d,c,3j,d:2,c,3j,c,d:2,3j:6,d,2t,d,3j,d,2t,d,3j,d,2t,d,3j,d,2t,d,3j,d,3i:2,3j:6,d:2,c,3j,d,2t,d,3j,d,2t,d,3j,d:2,c,3j,c,d,c,3j:6,d,2t,d,3j,d,2t,d,3j,d,2t,d,3j,d,2t,d,3j,3i:2,d,3j:6,d:2,c,3j,c,d,c,3j,c,d,c,3j,d:2,c,3j,d:2,c,3j:6,3i:3,3j,3i:3,3j,3i:3,3j,3i:7,3j:s">Boobs</a>
107+
<a href="#12,d,d:2d,3z:5,d:j,3z,12:5,3z,d:h,3z,12:7,3z,d:f,3z,12:2,3z,12:3,3z,12:2,3z,d:e,3z,12:9,3z,d:e,3z,12:9,3z,d:e,3z,12:2,3z,12:3,3z,12:2,3z,d:e,e,3z,12:2,3z:3,12:2,3z,e,d:f,e,3z,12:5,3z,e,d:h,e,3z:5,e,d:j,e:5,d:35,3z,e,3z,d,3z:3,d,3z:3,d,3z:3,d,3z:3,d:6,3z,e,3z,d,3z,e,3z,d,3z,e:2,d,3z,e:2,d,3z,e:2,d:6,3z:3,d,3z:3,d,3z:3,d,3z:3,d,3z:3,d:7,3z,d:2,3z,e,3z,d,e:2,3z,d,e:2,3z,d,e:2,3z,d:7,3z,d:2,3z,e,3z,d,3z:3,d,3z:3,d,3z:3,d:1h">Smile</a>
108+
</div>
109+
110+
</main>
111+
112+
</body>
113+
</html>

demos/pixel-art-alpine/main.css

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
*,
2+
*:before,
3+
*:after {
4+
box-sizing: border-box ;
5+
margin: 0 ;
6+
padding: 0 ;
7+
}
8+
9+
:root {
10+
--grid-size: 25 ;
11+
--pixel-size: 26px ;
12+
}
13+
14+
body {
15+
font-family: monospace ;
16+
font-size: 16px ;
17+
line-height: 1.4 ;
18+
}
19+
20+
main {
21+
align-items: center ;
22+
display: flex ;
23+
flex-direction: column ;
24+
gap: 30px ;
25+
padding: 30px ;
26+
27+
& h1 {
28+
margin: 0 0 0px 0 ;
29+
30+
& a {
31+
color: inherit ;
32+
text-decoration: none ;
33+
34+
&:hover {
35+
color: #ff1493 ;
36+
text-decoration: underline ;
37+
}
38+
}
39+
}
40+
}
41+
42+
.grid {
43+
background-color: #ffffff ;
44+
box-shadow: 0 0 1px 0 #999999 ;
45+
display: grid ;
46+
grid-template-columns: repeat( var( --grid-size ), 1fr ) ;
47+
height: calc( var( --grid-size ) * var( --pixel-size ) ) ;
48+
user-select: none ;
49+
width: calc( var( --grid-size ) * var( --pixel-size ) ) ;
50+
51+
& button {
52+
border: none ;
53+
box-shadow: inset 0 0 1px 0 #ffffff ;
54+
height: var( --pixel-size ) ;
55+
width: var( --pixel-size ) ;
56+
}
57+
}
58+
59+
.palette {
60+
box-shadow: 0 0 1px 0 #999999 ;
61+
display: flex ;
62+
flex-wrap: wrap ;
63+
min-height: 156px ;
64+
user-select: none ;
65+
width: calc( var( --grid-size ) * var( --pixel-size ) ) ;
66+
67+
& button {
68+
border: none ;
69+
box-shadow: inset 0 0 1px 0 #ffffff ;
70+
flex: 0 0 auto ;
71+
height: var( --pixel-size ) ;
72+
width: var( --pixel-size ) ;
73+
74+
&:last-child {
75+
flex-grow: 1 ;
76+
}
77+
78+
&.isSelected {
79+
box-shadow: 0 0 3px 5px #000000 ;
80+
outline: 2px solid #ffffff ;
81+
z-index: 2 ;
82+
}
83+
}
84+
}
85+
86+
.selected {
87+
display: flex ;
88+
font-size: 20px ;
89+
margin: 0 ;
90+
gap: 30px ;
91+
92+
& div {
93+
display: flex ;
94+
gap: 10px ;
95+
}
96+
97+
& dt {
98+
font-weight: 700 ;
99+
margin: 0 ;
100+
}
101+
102+
& dd {
103+
margin: 0 ;
104+
}
105+
}
106+
107+
.fillers {
108+
display: flex ;
109+
font-size: 20px ;
110+
gap: 13px ;
111+
112+
& button {
113+
align-items: center ;
114+
background-color: #333333 ;
115+
border: none ;
116+
border-radius: 4px ;
117+
color: #ffffff ;
118+
display: flex ;
119+
font: inherit ;
120+
gap: 13px ;
121+
padding: 10px 20px ;
122+
}
123+
124+
& span {
125+
box-shadow: 0 0 1px 1px #ffffff ;
126+
border-radius: 16px ;
127+
height: 16px ;
128+
width: 16px ;
129+
}
130+
}
131+
132+
.tuggers {
133+
display: flex ;
134+
font-size: 20px ;
135+
gap: 13px ;
136+
137+
& button {
138+
background-color: #ffffff ;
139+
border: 1px solid #333333 ;
140+
border-radius: 4px ;
141+
color: #333333 ;
142+
font: inherit ;
143+
padding: 10px 20px ;
144+
min-width: 100px ;
145+
}
146+
}
147+
148+
.tips {
149+
align-items: center ;
150+
display: flex ;
151+
flex-direction: column ;
152+
gap: 15px ;
153+
154+
& kbd {
155+
background-color: #232323 ;
156+
border-radius: 2px ;
157+
color: #ffffff ;
158+
display: inline-block ;
159+
padding: 0 3px ;
160+
}
161+
}
162+
163+
.examples {
164+
display: flex ;
165+
gap: 20px ;
166+
167+
& a {
168+
color: #ff1493 ;
169+
}
170+
}
171+

0 commit comments

Comments
 (0)