Skip to content

Commit

Permalink
JS: mouse follower
Browse files Browse the repository at this point in the history
  • Loading branch information
sadanandpai committed Oct 9, 2024
1 parent 46b8d85 commit 01b50c8
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 57 deletions.
42 changes: 42 additions & 0 deletions apps/javascript/src/challenges/chess-board/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export function createBoard(rows: number, cols = rows) {
const gridDocFragment = document.createDocumentFragment();

for (let i = 0; i < rows; i++) {
const row = document.createElement('div');
for (let j = 0; j < cols; j++) {
const col = document.createElement('button');
col.dataset.x = String(i);
col.dataset.y = String(j);
col.classList.add('box');
row.appendChild(col);
}
gridDocFragment.appendChild(row);
}

return gridDocFragment;
}

export function setColor(element: HTMLElement | null) {
if (element) {
element.classList.add('selected');
}
}

export function getCell(board: HTMLDivElement, x: number, y: number): HTMLElement | null {
return board.querySelector(`[data-x='${x}'][data-y='${y}']`);
}

export function markBishopMoves(board: HTMLDivElement, x: number, y: number, size: number) {
const cell = getCell(board, x, y);
setColor(cell);

for (let i = x - 1, offset = 1, col = y; i >= 0; i--, offset++) {
setColor(board.querySelector(`[data-x='${i}'][data-y='${col - offset}']`));
setColor(board.querySelector(`[data-x='${i}'][data-y='${col + offset}']`));
}

for (let i = x + 1, offset = 1, col = y; i < size; i++, offset++) {
setColor(board.querySelector(`[data-x='${i}'][data-y='${col - offset}']`));
setColor(board.querySelector(`[data-x='${i}'][data-y='${col + offset}']`));
}
}
8 changes: 2 additions & 6 deletions apps/javascript/src/challenges/chess-board/index.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="../../logo.svg" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="index.js" type="module"></script>
<script src="../../helpers/header.js" type="module"></script>
<script src="index.ts" type="module"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body>
Expand Down
51 changes: 0 additions & 51 deletions apps/javascript/src/challenges/chess-board/index.js

This file was deleted.

32 changes: 32 additions & 0 deletions apps/javascript/src/challenges/chess-board/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { createBoard, markBishopMoves } from './helpers.ts';

const gridSize = 8;
const board = document.querySelector('.board') as HTMLDivElement;
const moveType = 'bishop';

function resetChessGrid() {
const elements = document.querySelector('.board')?.getElementsByClassName('selected');
while (elements && elements.length !== 0) {
elements[0].classList.remove('selected');
}
}

function onClick(event: MouseEvent) {
resetChessGrid();

const element = event.target as HTMLElement;
if (element.classList.contains('box')) {
const x = Number(element.dataset.x);
const y = Number(element.dataset.y);

switch (moveType) {
case 'bishop':
markBishopMoves(board, x, y, gridSize);
break;
}
}
}

const boardFragment = createBoard(gridSize);
board.appendChild(boardFragment);
document.addEventListener('click', onClick);
37 changes: 37 additions & 0 deletions apps/javascript/src/challenges/mouse-follower/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!doctype html>
<html lang="en">
<head>
<script src="../../helpers/header.js" type="module"></script>
<script src="index.ts" type="module"></script>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="container text-center">
<div id="follower"></div>
<p>
This pointer moves towards the mouse pointer. Try moving your mouse around the screen.<br />
This is an interactive challenge works with pointer devices.
</p>

<div class="form">
<div>
<label for="speed">Speed</label>
<input
type="range"
name="speed"
id="speed"
min="0.02"
max="0.3"
step="0.02"
value="0.1"
/>
</div>

<div>
<label for="cursor">Show cursor</label>
<input type="checkbox" name="cursor" id="cursor" checked />
</div>
</div>
</div>
</body>
</html>
29 changes: 29 additions & 0 deletions apps/javascript/src/challenges/mouse-follower/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const followerEl = document.getElementById('follower') as HTMLDivElement;
const speedEl = document.getElementById('speed') as HTMLInputElement;
const cursorEl = document.getElementById('cursor') as HTMLInputElement;

const currentPoint = { x: 0, y: 0 };
const targetPoint = { x: 0, y: 0 };
let cursorSpeed = speedEl.valueAsNumber;

function lerp() {
currentPoint.x += (targetPoint.x - currentPoint.x) * cursorSpeed;
currentPoint.y += (targetPoint.y - currentPoint.y) * cursorSpeed;
followerEl.style.transform = `translate(${currentPoint.x}px, ${currentPoint.y}px)`;
requestAnimationFrame(() => lerp());
}

speedEl.addEventListener('input', () => {
cursorSpeed = speedEl.valueAsNumber;
});

cursorEl.addEventListener('change', () => {
document.body.classList.toggle('no-cursor');
});

document.addEventListener('pointermove', (e) => {
targetPoint.x = e.clientX - 25;
targetPoint.y = e.clientY - 25;
});

lerp();
43 changes: 43 additions & 0 deletions apps/javascript/src/challenges/mouse-follower/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
body {
height: 100vh;
}

body.no-cursor,
body.no-cursor * {
cursor: none !important;
}

#follower {
position: fixed;
width: 50px;
height: 50px;
box-shadow: 0 0 8px 8px rgba(255, 0, 0, 0.5);
border-radius: 50%;
top: 0;
left: 0;
pointer-events: none;
}

p {
font-size: 1.5em;
color: #333;
text-align: center;
margin-top: 2rem;
}

.form {
display: flex;
flex-direction: column;
justify-content: center;
gap: 2rem;

div {
display: flex;
justify-content: center;
gap: 1rem;

label {
font-size: 1.5em;
}
}
}
10 changes: 10 additions & 0 deletions shared/data/content/js-challenges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,16 @@ const challenges: Map<string, IChallenge> = new Map([
isNew: true,
},
],
[
'mouse-follower',
{
title: 'Mouse Follower',
link: 'mouse-follower/',
difficulty: EDifficulty.Medium,
developer: 'sadanandpai',
tags: [],
},
],
[
'finance-tracker',
{
Expand Down

0 comments on commit 01b50c8

Please sign in to comment.