zeroed-some/sketch / 57d48f1

Browse files

init sketch

Authored by espadonne
SHA
57d48f1896cf6fffbc16325f06afe4c99f98c53d
Tree
be6f09f

4 changed files

StatusFile+-
A css/styles.css 56 0
A deploy.sh 17 0
A index.html 24 0
A js/app.js 120 0
css/styles.cssadded
@@ -0,0 +1,56 @@
1
+body {
2
+      font-family: sans-serif;
3
+      text-align: center;
4
+      margin: 0;
5
+      padding: 1rem;
6
+      background: #202124;
7
+      color: #eee
8
+    }
9
+
10
+    h1 {
11
+      margin-top: 0;
12
+      padding-top: 1rem
13
+    }
14
+
15
+    canvas {
16
+      border: 1px solid #555;
17
+      background: #111;
18
+      cursor: crosshair
19
+    }
20
+
21
+    .toolbar {
22
+      margin-top: .8rem;
23
+      display: flex;
24
+      justify-content: center;
25
+      align-items: center;
26
+      gap: 1rem;
27
+    }
28
+
29
+    button,
30
+    input[type=range] {
31
+      margin: 0 .5rem
32
+    }
33
+
34
+    /* Color wheel styles */
35
+    .color-picker-wrapper {
36
+      position: relative;
37
+      display: inline-block;
38
+    }
39
+
40
+    #colorWheel {
41
+      width: 150px;
42
+      height: 150px;
43
+      border-radius: 50%;
44
+      cursor: crosshair;
45
+      border: 2px solid #444;
46
+    }
47
+
48
+    .color-preview {
49
+      width: 30px;
50
+      height: 30px;
51
+      border-radius: 50%;
52
+      border: 2px solid #666;
53
+      display: inline-block;
54
+      vertical-align: middle;
55
+      margin-left: 10px;
56
+    }
deploy.shadded
@@ -0,0 +1,17 @@
1
+#!/usr/bin/env bash
2
+set -euo pipefail
3
+PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
4
+STAMP=$(date +%Y-%m-%d-%H%M%S)
5
+OUT=~/builds/$STAMP
6
+mkdir -p "$OUT"
7
+
8
+rsync -az --delete --exclude deploy.sh --exclude .git \
9
+      "$PROJECT_DIR"/ "$OUT"/
10
+
11
+rsync -az --delete "$OUT"/ /var/www/sketch.musicsian.com/releases/$STAMP/
12
+
13
+sudo ln -nfs /var/www/sketch.musicsian.com/releases/$STAMP \
14
+            /var/www/sketch.musicsian.com/current
15
+sudo restorecon -Rv /var/www/sketch.musicsian.com/releases/$STAMP >/dev/null
16
+sudo systemctl reload nginx
17
+echo "✓ Deployed $STAMP to sketch.musicsian.com"
index.htmladded
@@ -0,0 +1,24 @@
1
+<!doctype html>
2
+<html lang="en">
3
+<head>
4
+  <meta charset="utf-8">
5
+  <title>ASCII Sketch</title>
6
+  <link rel="stylesheet" href="css/styles.css">
7
+</head>
8
+<body>
9
+  <h1>🖋️ sketch 🖋️</h1>
10
+  <p>Draw by dragging — every stroke prints a random ASCII char.</p>
11
+  <canvas id="board" width="800" height="600"></canvas>
12
+  <div class="toolbar">
13
+    <button id="clear">Clear</button>
14
+    <label>Size
15
+      <input type="range" id="size" min="12" max="64" value="24">
16
+    </label>
17
+    <div class="color-picker-wrapper">
18
+      <canvas id="colorWheel"></canvas>
19
+      <div class="color-preview" id="colorPreview"></div>
20
+    </div>
21
+  </div>
22
+  <script src="js/app.js"></script>
23
+</body>
24
+</html>
js/app.jsadded
@@ -0,0 +1,120 @@
1
+// Main canvas setup
2
+    const canvas = document.getElementById('board')
3
+    const ctx = canvas.getContext('2d')
4
+    const chars = [
5
+      '@', '#', '$', '%', '&', '*', '+', '=',
6
+      '~', '?', 'Ω', '∞', '¶', '§', '★', '☆'
7
+    ]
8
+    let drawing = false
9
+    let currentColor = '#0f0'
10
+
11
+    // Color wheel setup
12
+    const colorWheel = document.getElementById('colorWheel')
13
+    const colorCtx = colorWheel.getContext('2d')
14
+    const colorPreview = document.getElementById('colorPreview')
15
+    colorWheel.width  = 150
16
+    colorWheel.height = 150
17
+
18
+    // Draw color wheel
19
+    function drawColorWheel() {
20
+      const centerX = colorWheel.width  / 2
21
+      const centerY = colorWheel.height / 2
22
+      const radius = Math.min(centerX, centerY) - 2
23
+
24
+      for (let angle = 0; angle < 360; angle++) {
25
+        const startAngle = (angle - 1) * Math.PI / 180
26
+        const endAngle = angle * Math.PI / 180
27
+        
28
+        colorCtx.beginPath()
29
+        colorCtx.moveTo(centerX, centerY)
30
+        colorCtx.arc(centerX, centerY, radius, startAngle, endAngle)
31
+        colorCtx.closePath()
32
+        
33
+        const gradient = colorCtx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radius)
34
+        gradient.addColorStop(0, 'white')
35
+        gradient.addColorStop(0.7, `hsl(${angle}, 100%, 50%)`)
36
+        gradient.addColorStop(1,   `hsl(${angle}, 100%, 25%)`)
37
+        
38
+        colorCtx.fillStyle = gradient
39
+        colorCtx.fill()
40
+      }
41
+    }
42
+
43
+    // Get color from wheel position
44
+    function getColorFromWheel(x, y) {
45
+      const centerX = colorWheel.width / 2
46
+      const centerY = colorWheel.height / 2
47
+      const dx = x - centerX
48
+      const dy = y - centerY
49
+      const distance = Math.sqrt(dx * dx + dy * dy)
50
+      const maxRadius = Math.min(centerX, centerY) - 2
51
+      
52
+      if (distance > maxRadius) return null
53
+      
54
+      let angle = Math.atan2(dy, dx) * 180 / Math.PI
55
+      angle = (angle + 360) % 360
56
+      
57
+      const saturation = Math.min(100, (distance / maxRadius) * 100)
58
+      const lightness = 50 - (distance / maxRadius) * 25
59
+      
60
+      return `hsl(${angle}, ${saturation}%, ${lightness}%)`
61
+    }
62
+
63
+    // Color wheel interaction
64
+    colorWheel.addEventListener('click', (e) => {
65
+      const rect = colorWheel.getBoundingClientRect()
66
+      const x = e.clientX - rect.left
67
+      const y = e.clientY - rect.top
68
+      const color = getColorFromWheel(x, y)
69
+      
70
+      if (color) {
71
+        currentColor = color
72
+        colorPreview.style.backgroundColor = color
73
+      }
74
+    })
75
+
76
+    // Drawing functions
77
+    function randomChar() {
78
+      return chars[Math.floor(Math.random() * chars.length)]
79
+    }
80
+
81
+    function getFont() {
82
+      return `${sizeInput.value}px monospace`
83
+    }
84
+
85
+    function draw(e) {
86
+      if (!drawing) return
87
+      const rect = canvas.getBoundingClientRect()
88
+      const x = e.clientX - rect.left
89
+      const y = e.clientY - rect.top
90
+      ctx.font = getFont()
91
+      ctx.fillStyle = currentColor
92
+      ctx.fillText(randomChar(), x, y)
93
+    }
94
+
95
+    // Mouse events
96
+    canvas.addEventListener('mousedown',  () => (drawing = true))
97
+    canvas.addEventListener('mouseup',    () => (drawing = false))
98
+    canvas.addEventListener('mouseleave', () => (drawing = false))
99
+    canvas.addEventListener('mousemove', draw)
100
+
101
+    // Touch support
102
+    canvas.addEventListener('touchstart', e => {
103
+      drawing = true
104
+      draw(e.touches[0])
105
+    })
106
+    canvas.addEventListener('touchmove', e => {
107
+      draw(e.touches[0])
108
+      e.preventDefault()
109
+    })
110
+    canvas.addEventListener('touchend', () => (drawing = false))
111
+
112
+    // Controls
113
+    const clearBtn = document.getElementById('clear')
114
+    clearBtn.onclick = () => ctx.clearRect(0, 0, canvas.width, canvas.height)
115
+
116
+    const sizeInput = document.getElementById('size')
117
+
118
+    // Initialize
119
+    drawColorWheel()
120
+    colorPreview.style.backgroundColor = currentColor