PageSourceSearch

https://scrollhole.me/scripts/main.js

js scrollhole.me collected 2026-10-08 11:56:58 UTC 6,132 bytes, 271 lines download raw bytes

1let numRegions = 3, currentRegion = 0
2let center = { x:0, y:0 }
3let mouseCenter = { x:0, y:0 }
4let scaledCenter = { x:0.0, y:0.0 }
5const startTime = Tone.now()
6let gain = 0.9
7let position = 0
8let scroll = new Scroll(numRegions)
9
10let mouseFollow = { x: 0, y: 0 }
11let radialBackground
12
13// tone nodes
14let granularSynthesizer = []
15let granularGains = []
16let masterGain
17let lastTouchY
18
19let muteButton, unmuteButton, logo // images
20let isMuted = false
21
22let rColors = [
23  {
24    inner: {
25      h: 0,
26      s: 359,
27      b: 359,
28    },
29    outer: {
30      h: 180,
31      s: 359,
32      b: 359,
33    }
34  },
35  {
36    inner: {
37      h: 120,
38      s: 359,
39      b: 359,
40    },
41    outer: {
42      h: 300,
43      s: 359,
44      b: 359,
45    }
46  },
47  {
48    inner: {
49      h: 240,
50      s: 0,
51      b: 359,
52    },
53    outer: {
54      h: 60,
55      s: 0,
56      b: 359,
57    }
58  },
59]
60
61$(".tapForSound").click(function(e) {
62    e.stopPropagation() // This is the preferred method.
63    // return false        // This should not be used unless you do not want
64                         // any click events registering inside the div
65})
66
67function preload() {
68  masterGain = new Tone.Gain().toDestination()
69  // let soundFiles = ['./audio/stretchingStereo.mp3', './audio/bubblingOcean.mp3', './audio/grassStorm.mp3']
70  let soundFiles = ['./audio/stretchingMono.mp3', './audio/bubblingOceanMono.mp3', './audio/grassStormChimesMono.mp3']
71
72  for (let i = 0; i < soundFiles.length; i++) {
73    let buffer = new Tone.Buffer(soundFiles[i], function() {
74      let gs = new GranularSynthesizer(buffer)
75      let gg = new Tone.Gain()
76      gg.gain.value = 0.0
77
78      gs.connect(gg)
79      gg.connect(masterGain)
80      gs.start(0)
81
82      granularGains.push(gg)
83      granularSynthesizer.push(gs)
84    })
85  }
86
87  loadFont('./fonts/effects-eighty.otf')
88}
89
90function setup() {
91  let cvn = createCanvas(windowWidth, windowHeight)
92  cvn.style('display', 'block')
93
94  frameRate(40)
95
96  center.x = width / 2.0
97  center.y = height / 2.0
98  mouseFollow.x = center.x
99  mouseFollow.y = center.y
100
101  infShapes = new InfiniteShapes()
102
103  infShapes.updateGroup(10)
104
105  loadImages()
106
107  let bgCtr = { x: center.x, y: center.y }
108  radialBackground = new RadialBackground(center, rColors[0].inner, rColors[0].outer)
109
110  var options = {
111    preventDefault: true
112  }
113}
114
115function interpVals(v1, v2) {
116  let dist = (v2 - v1)
117  let val = v1 + dist * scroll.hueScalar
118
119  return ((val % 360) + 360) % 360
120}
121function interpColors(c1, c2) {
122  let h = interpVals(c1.h, c2.h)
123  let s = interpVals(c1.s, c2.s)
124  let b = interpVals(c1.b, c2.b)
125
126  return {
127    h: h,
128    s: s,
129    b: b,
130  }
131}
132
133
134let wheelDelta = 0
135let alpha = 0.0
136let alphaInc = 1.0 / 60.0
137
138function draw() {
139  clear()
140
141  let inner = interpColors(rColors[scroll.region].inner, rColors[scroll.nextRegion].inner)
142  let outer = interpColors(rColors[scroll.region].outer, rColors[scroll.nextRegion].outer)
143
144  mouseFollow = pointBetweenPoints({ x: mouseX, y: mouseY }, mouseFollow, 0.92)
145
146  if (alpha < 1.0) {
147    alpha += alphaInc
148  }
149
150  radialBackground.draw(mouseFollow, inner, outer, alpha)
151
152  scaledCenter.x = (mouseFollow.x / width - 0.5)
153  scaledCenter.y = (mouseFollow.y / height - 0.5)
154
155  if (isMuted) {
156    muteButton.hide()
157    unmuteButton.show()
158  } else {
159    unmuteButton.hide()
160    muteButton.show()
161  }
162
163  logo.show()
164
165  infShapes.draw(center, scaledCenter, scroll.region, scroll.nextRegion, scroll.inTransition, scroll.regionGain, scroll.nextRegionGain)
166  infShapes.update(scroll.regionPosition, scroll.regionIdx)
167  // adjust denominator of argument for speed
168  infShapes.scroll(scroll.value / 15000)
169
170  scroll.update()
171
172  // handle transition to a new region
173  if (scroll.inTransition && granularSynthesizer[scroll.region] && granularSynthesizer[scroll.nextRegion]) {
174    granularSynthesizer[scroll.region].update(scroll.value, scroll.stopped)
175    granularGains[scroll.region].gain.value = scroll.regionGain
176    granularSynthesizer[scroll.nextRegion].update(scroll.value, scroll.stopped)
177    granularGains[scroll.nextRegion].gain.value = scroll.nextRegionGain
178  } else if (granularSynthesizer[scroll.region]) {
179    granularSynthesizer[scroll.region].update(scroll.value, scroll.
179stopped)
180    granularGains[scroll.region].gain.value = scroll.regionGain
181  }
182
183  if (wheelDelta > 0) {
184    wheelDelta -= 3
185  } else if (wheelDelta < 0) {
186    wheelDelta += 3
187  }
188}
189
190function loadImages() {
191  // logo
192  logo = createImg('./img/scrollholeLogo.png')
193  logo.id('logo')
194  logo.size(476, 100)
195  logo.position(25, 25)
196
197  // mute button
198  unmuteButton = createImg('./img/unmuteButtonGreenBlack.png')
199  unmuteButton.id('unmute')
200  unmuteButton.size(80, 80)
201  unmuteButton.position(windowWidth - 110, 25)
202  unmuteButton.mousePressed(toggleMute)
203
204  muteButton = createImg('./img/muteButtonGreenBlack.png')
205  muteButton.id('mute')
206  muteButton.size(80, 80)
207  muteButton.position(windowWidth - 110, 25)
208  muteButton.mousePressed(toggleMute)
209
210  if (Tone.context.state !== 'running') {
211    isMuted = true
212  }
213}
214
215function mousePressed() {
216  //infShapes.clicked()
217}
218
219function mouseWheel(event) {
220  if (event.delta > 3 || event.delta < -3) {
221    scroll.scrollZoom(event.delta)
222  } else {
223    wheelDelta += event.delta
224    scroll.scrollZoom(wheelDelta)
225  }
226}
227
228// mobile interactions
229let lastMouseY = 0
230function touchMoved() {
231  let mouseYMapped = map(mouseY, 0, height, width/2.0, -width/2.0)
232  let mouseYDelta = lastMouseY - mouseYMapped
233  scroll.scrollZoom(mouseYDelta)
234  lastMouseY = mouseYMapped
235}
236
237function mouseClicked() {
238  if (Tone.context.state !== 'running') {
239    Tone.start()
240    isMuted = false
241  }
242}
243
244function touchStarted() {
245  if (Tone.context.state != 'running') {
246    Tone.start()
247    isMuted = false
248  }
249}
250
251function windowResized() {
252  resizeCanvas(windowWidth, windowHeight);
253  unmuteButton.position(windowWidth - 110, 25)
254  muteButton.position(windowWidth - 110, 25)
255}
256
257function toggleMute() {
258  isMuted = !isMuted
259  if (isMuted) {
260    masterGain.gain.value = 0.0
261  } else {
262    masterGain.gain.value = gain
263  }
264}
265
266function pointBetweenPoints(p1, p2, perc) {
267  return {
268    x: p1.x + perc * (p2.x - p1.x),
269    y: p1.y + perc * (p2.y - p1.y),
270  }
271}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.