jiggler / index.html
AstraOS's picture
Update index.html
693972b verified
<html>
<head>
<title>A test of courage</title>
<link href="https://fonts.googleapis.com/css2?family=Metal+Mania&display=swap" rel="stylesheet">
<div id="stop-instruction" class="unselectable" style="position: absolute; top: 8%; left: 50%; transform: translate(-50%, -50%); color: #ffa502; font-size: 24px; font-family: 'Metal Mania', cursive; text-shadow: 0 0 10px #d35400, 0 0 20px #d35400; visibility: hidden; text-align: center;">
Press 'Ctrl+R' to banish the spirit's jiggle!
</div>
<style>
.metal-mania-regular {
font-family: "Metal Mania", system-ui;
font-weight: 400;
font-style: normal;
}
.arrow {
position: absolute;
top: 30%;
left: 30%;
width: 12px;
visibility: hidden;
pointer-events: none;
z-index: 1000;
}
.pointer {
position: absolute;
top: 30%;
left: 30%;
width: 16px;
visibility: hidden;
pointer-events: none;
}
body {
overflow-y: hidden;
overflow-x: hidden;
margin:0;
padding:0;
background: #262626;
cursor: none;
}
.button {
background: #171515;
width: 100%;
height: 100%;
border-radius: 6px;
border-width: 0px;
font-size: 24px;
transform: translateY(0);
color: #ffa502;
box-shadow: 0 0 50px #d35400;
cursor: none;
transition: .5s;
}
.darkened {
background: #171515;
opacity: 0.2;
box-shadow: 0 0 0px 0px !important;
}
.hoverableMainButton:hover {
text-shadow: 0 0 5px #d35400;
box-shadow: 0 0 50px 20px #d35400;
}
button:focus{
outline: none;
}
.how {
background: #171515;
width: 100%;
height: 100%;
border-radius: 6px;
border-width: 0px;
font-size: 18px;
transform: translateY(0);
color: #ffa502;
box-shadow: 0 0 20px #d35400;
cursor: none;
}
#ouija {
box-shadow: 0 0 20px #d35400;
}
.unselectable {
user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
}
@media only screen and (max-width: 760px) {
.button {
display: none;
}
.mobile-warning {
display: block;
}
}
</style>
<script>
var recordingStatus = "off" // off, recording, replaying
var freshRecording = []
var prevTime = undefined
var prevX = undefined
var prevY = undefined
var offsetX = 0
var offsetY = 0
var userMoveCount = 0
var hideAllCursors = function() {
const pointer = document.getElementById("pointer")
const arrow = document.getElementById("arrow")
pointer.style.visibility = "hidden";
arrow.style.visibility = "hidden";
}
var paintCursorWithOffset = function(cursor, realX, realY) {
const w = window.innerWidth;
const h = window.innerHeight;
var x = realX + offsetX
var y = realY + offsetY
if (x > w-24) {
x = Math.max(realX, w-24)
}
if (y > h-24) {
y = Math.max(realY, h-24)
}
if (x < 0) {
x = 0
}
if (y < 0) {
y = 0
}
cursor.style.top = y + "px";
cursor.style.left = x + "px";
}
var mouseMovedOnBackground = function(event) {
const x = event.clientX
const y = event.clientY
if (recordingStatus === "recording") {
const time = Date.now()
const timeDiff = time - prevTime
const xDiff = x - prevX
const yDiff = y - prevY
prevTime = time
freshRecording.push([timeDiff, xDiff, yDiff])
}
prevX = x
prevY = y
const pointer = document.getElementById("pointer")
pointer.style.visibility = "hidden";
const arrow = document.getElementById("arrow")
arrow.style.visibility = "visible";
paintCursorWithOffset(arrow, prevX, prevY)
userMoveCount += 1
}
var mouseMovedOnButton = function(event) {
if (recordingStatus === "replaying") {
mouseMovedOnBackground(event);
return;
}
const x = event.clientX
const y = event.clientY
prevX = x
prevY = y
const arrow = document.getElementById("arrow")
arrow.style.visibility = "hidden";
const pointer = document.getElementById("pointer")
pointer.style.visibility = "visible";
paintCursorWithOffset(pointer, x, y)
userMoveCount += 1
}
var getCandidateVal = function(x, y, candidateX, candidateY) {
return Math.sqrt((x - candidateX) * (x-candidateX) + (y - candidateY) * (y - candidateY))
}
var choose = function(previousBestCandidate, candidateX, candidateY, x, y) {
const candidateVal = getCandidateVal(x, y, candidateX, candidateY)
if (!previousBestCandidate || candidateVal < previousBestCandidate.val) {
return {
'val': candidateVal,
'x': candidateX,
'y': candidateY
}
}
return previousBestCandidate
}
var mouseMovedOnHowdy = function(event) {
if (recordingStatus === "replaying") {
mouseMovedOnBackground(event);
return;
}
const x = event.clientX
const y = event.clientY
// Offset mouse to the nearest side of howdy-button.
const bounds = document.getElementById("how").getBoundingClientRect()
var bestCandidate = null
bestCandidate = choose(bestCandidate, bounds.left-10, y, x, y) // left
bestCandidate = choose(bestCandidate, x, bounds.top-10, x, y) // up
bestCandidate = choose(bestCandidate, x, bounds.bottom+10, x, y) // down
bestCandidate = choose(bestCandidate, bounds.right+10, y, x, y) // right
offsetX = bestCandidate.x - x
offsetY = bestCandidate.y - y
prevX = x
prevY = y
const pointer = document.getElementById("pointer")
pointer.style.visibility = "hidden";
const arrow = document.getElementById("arrow")
arrow.style.visibility = "visible";
paintCursorWithOffset(arrow, x, y)
userMoveCount += 1
}
var recordingIndex = 0
var step = 0
var recursiveTimerReplay = function() {
const rec = recordings[recordingIndex]
if (step >= rec.length) {
// Instead of stopping, just reset the step and move to the next recording
step = 0
recordingIndex = (recordingIndex + 1) % recordings.length
// Do not return, just let the recursive timer continue
}
const currTime = Date.now()
if (currTime - prevTime >= rec[step][0]) {
offsetX = offsetX + rec[step][1]
offsetY = offsetY + rec[step][2]
step = step + 1
paintCursorWithOffset(document.getElementById("arrow"), prevX, prevY)
prevTime = currTime
}
setTimeout(() => { recursiveTimerReplay() }, 0)
}
var replayMovements = function(event) {
const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
if (width < 800 || typeof(prevX) == "undefined" || userMoveCount < 5) {
alert("Sorry, we can't do the trick on your device. Please try again with a desktop/laptop that has a mouse attached and has screen width of at least 800 pixels.")
return
}
recordingStatus = "replaying"
arrow = document.getElementById("arrow")
paintCursorWithOffset(arrow, prevX, prevY)
document.getElementById("pointer").style.visibility = "hidden";
arrow.style.visibility = "visible";
document.getElementById("butt").classList.add("darkened")
document.getElementById("butt").classList.remove("hoverableMainButton")
document.getElementById("howdiv").style.visibility = "hidden";
document.getElementById("ouija").style.visibility = "hidden";
document.getElementById("stop-instruction").style.visibility = "visible";
prevTime = Date.now()
recursiveTimerReplay()
}
var recordMovements = function(event) {
const REC_TIME = 15000
freshRecording = []
recordingStatus = "recording"
prevTime = Date.now()
document.getElementById('recordButton').style.display = 'none';
document.getElementById('buttdiv').style.display = 'none';
for (var j=REC_TIME; j>0; j-=1000) {
const bah = REC_TIME - j
setTimeout(() => console.log(bah / 1000), bah)
}
setTimeout(() => {
document.getElementById('buttdiv').style.display = 'block';
recordingStatus = false;
recordings.push(freshRecording)
console.log('finished recording');
console.log(freshRecording)
}, REC_TIME)
}
document.addEventListener('contextmenu', e => {
if (recordingStatus == 'replaying') {
e.preventDefault();
}
});
</script>
</head>
<body>
<div id="bg" style="position: absolute; width: 100%; height: 100%"></div>
<button id="recordButton" style="position: absolute; top: 45%; left: 37%; z-index: 999; display: none;">
Record
</button>
<noscript><h1>This website requires JavaScript in order to do a trick. Please enable JavaScript and refresh.</h1></noscript>
<h1 class="mobile-warning" style="display: none;">
This website requires a laptop/desktop device with a mouse, and a sufficiently large screen. Try with another device?
</h1>
<div id="buttdiv" class="unselectable" style="position: absolute; width: 400px; height: 100px; top: 50%; left: 50%; margin: -50px 0 0 -200px;">
<button id="butt" class="button hoverableMainButton unselectable" tabindex="-1">
I'm not afraid to click<br>buttons on the internet
</button>
</div>
<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" title="Explanation video (all the answers you need are here)" style="display: none;"></a>
<div id="howdiv" class="unselectable" style="position: absolute; width: 200px; height: 50px; right: 50px; bottom: 50px; margin: -50px 0 0 -200px; visibility: visible;">
<button id="how" class="how unselectable" tabindex="-1">
How this works
</button>
</div>
<div id="ouija" class="unselectable" style="position: absolute; left: 50px; bottom: 50px; visibility: visible;">
<a href="https://ouija.attejuvonen.fi" target="_blank">
<img src="ouija.jpg" style="width: 100px; cursor: none;">
</a>
</div>
<script>
document.body.addEventListener('mouseleave', e => { hideAllCursors() })
document.getElementById('bg').addEventListener('mousemove', e => { mouseMovedOnBackground(e) })
document.getElementById('butt').addEventListener('mousemove', e => { mouseMovedOnButton(e) })
document.getElementById('butt').addEventListener('click', e => { replayMovements(e) })
document.getElementById('recordButton').addEventListener('click', e => { recordMovements(e) })
document.getElementById('how').addEventListener('mousemove', e => { mouseMovedOnHowdy(e) })
document.getElementById('how').addEventListener('mouseleave', e => { offsetX = 0; offsetY = 0; })
document.getElementById('ouija').addEventListener('mousemove', e => { mouseMovedOnButton(e) })
</script>
<script src="recordings.js"></script>
<img id="arrow" class="arrow" src="arrow_m.png" />
<img id="pointer" class="pointer" src="pointer.png" />
<script async defer data-domain="attejuvonen.fi" src="https://plausible.io/js/plausible.js"></script>
</body>
</html>