radames commited on
Commit
304976c
โ€ข
1 Parent(s): 1d701d3

fancy cursors

Browse files
frontend/src/lib/App.svelte CHANGED
@@ -5,6 +5,7 @@
5
  import Menu from '$lib/Menu.svelte';
6
  import type { Room } from '@liveblocks/client';
7
  import { onDestroy } from 'svelte';
 
8
  import { currZoomTransform, myPresence, others } from '$lib/store';
9
 
10
  /**
@@ -12,7 +13,7 @@
12
  * Check in src/routes/index.svelte to see the setup code.
13
  */
14
 
15
- // export let room: Room;
16
 
17
  // // Get initial values for presence and others
18
  // let myPresence = room.getPresence();
@@ -32,15 +33,19 @@
32
  // unsubscribeMyPresence();
33
  // unsubscribeOthers();
34
  // });
 
 
 
 
 
35
  $: {
36
- console.log('myPresence', $myPresence.cursor);
37
- // console.log('others', $others);
38
  }
39
- const r = 10;
40
  function round(p, n) {
41
  return p % n < n / 2 ? p - (p % n) : p + n - (p % n);
42
  }
43
- const grid = 10;
44
 
45
  // Update cursor presence to current pointer location
46
  function handlePointerMove(event: PointerEvent) {
@@ -64,17 +69,6 @@
64
  cursor: null
65
  };
66
  }
67
-
68
- const COLORS = [
69
- '#E57373',
70
- '#9575CD',
71
- '#4FC3F7',
72
- '#81C784',
73
- '#FFF176',
74
- '#FF8A65',
75
- '#F06292',
76
- '#7986CB'
77
- ];
78
  </script>
79
 
80
  <!-- Show the current user's cursor location -->
@@ -84,28 +78,45 @@
84
  : 'Move your cursor to broadcast its position to other people in the room.'}
85
  </div>
86
  <div
87
- class="relative z-0 w-screen h-screen"
88
  on:pointerleave={handlePointerLeave}
89
  on:pointermove={handlePointerMove}
90
  >
91
  <Canvas />
92
 
93
  <main class="z-10 relative">
 
94
  {#if $myPresence?.cursor}
95
- <Frame x={$myPresence.cursor.x} y={$myPresence.cursor.y} transform={$currZoomTransform} />
 
 
 
 
 
 
 
 
 
 
 
96
  {/if}
97
 
98
  <!-- When others connected, iterate through others and show their cursors -->
99
  {#if others}
100
  {#each [...$others] as { connectionId, presence } (connectionId)}
101
  {#if presence?.cursor}
102
- <Frame x={presence.cursor.x} y={presence.cursor.y} transform={$currZoomTransform} />
 
 
 
 
 
103
 
104
  <Cursor
105
- color={COLORS[connectionId % COLORS.length]}
 
106
  x={presence.cursor.x}
107
  y={presence.cursor.y}
108
- transform={$currZoomTransform}
109
  />
110
  {/if}
111
  {/each}
 
5
  import Menu from '$lib/Menu.svelte';
6
  import type { Room } from '@liveblocks/client';
7
  import { onDestroy } from 'svelte';
8
+ import { COLORS, EMOJIS } from '$lib/constants';
9
  import { currZoomTransform, myPresence, others } from '$lib/store';
10
 
11
  /**
 
13
  * Check in src/routes/index.svelte to see the setup code.
14
  */
15
 
16
+ export let room: Room;
17
 
18
  // // Get initial values for presence and others
19
  // let myPresence = room.getPresence();
 
33
  // unsubscribeMyPresence();
34
  // unsubscribeOthers();
35
  // });
36
+
37
+ // $: {
38
+ // console.log('myPresence', $myPresence);
39
+ // console.log('others', $others);
40
+ // }
41
  $: {
42
+ console.log('Sefl', room.getSelf());
 
43
  }
44
+ const r = 8;
45
  function round(p, n) {
46
  return p % n < n / 2 ? p - (p % n) : p + n - (p % n);
47
  }
48
+ const grid = 8;
49
 
50
  // Update cursor presence to current pointer location
51
  function handlePointerMove(event: PointerEvent) {
 
69
  cursor: null
70
  };
71
  }
 
 
 
 
 
 
 
 
 
 
 
72
  </script>
73
 
74
  <!-- Show the current user's cursor location -->
 
78
  : 'Move your cursor to broadcast its position to other people in the room.'}
79
  </div>
80
  <div
81
+ class="relative z-0 w-screen h-screen cursor-none"
82
  on:pointerleave={handlePointerLeave}
83
  on:pointermove={handlePointerMove}
84
  >
85
  <Canvas />
86
 
87
  <main class="z-10 relative">
88
+
89
  {#if $myPresence?.cursor}
90
+ <!-- <Frame
91
+ color={COLORS[0]}
92
+ x={$myPresence.cursor.x}
93
+ y={$myPresence.cursor.y}
94
+ transform={$currZoomTransform}
95
+ /> -->
96
+ <Cursor
97
+ emoji={EMOJIS[0]}
98
+ color={COLORS[0]}
99
+ x={$myPresence.cursor.x}
100
+ y={$myPresence.cursor.y}
101
+ />
102
  {/if}
103
 
104
  <!-- When others connected, iterate through others and show their cursors -->
105
  {#if others}
106
  {#each [...$others] as { connectionId, presence } (connectionId)}
107
  {#if presence?.cursor}
108
+ <!-- <Frame
109
+ color={COLORS[1 + (connectionId % (COLORS.length - 1))]}
110
+ x={presence.cursor.x}
111
+ y={presence.cursor.y}
112
+ transform={$currZoomTransform}
113
+ /> -->
114
 
115
  <Cursor
116
+ emoji={EMOJIS[1 + (connectionId % (EMOJIS.length - 1))]}
117
+ color={COLORS[1 + (connectionId % (COLORS.length - 1))]}
118
  x={presence.cursor.x}
119
  y={presence.cursor.y}
 
120
  />
121
  {/if}
122
  {/each}
frontend/src/lib/Canvas.svelte CHANGED
@@ -10,9 +10,6 @@
10
  let containerEl: HTMLDivElement;
11
  let canvasCtx: CanvasRenderingContext2D;
12
 
13
- $:{
14
- console.log($currZoomTransform)
15
- }
16
  const margin = { top: 100, right: 100, bottom: 100, left: 100 };
17
  const extent = [
18
  [-margin.left, -margin.top],
@@ -21,7 +18,7 @@
21
  onMount(() => {
22
  const scale = width / containerEl.clientWidth;
23
  const zoomHandler = zoom()
24
- .scaleExtent([1 / scale, 2])
25
  .translateExtent([
26
  [0, 0],
27
  [width, height]
@@ -32,7 +29,7 @@
32
 
33
  select(canvasEl.parentElement)
34
  .call(zoomHandler as any)
35
- .call(zoomHandler.scaleTo as any, 1 / scale)
36
  .on('pointermove', handlePointerMove)
37
  .on('pointerleave', handlePointerLeave);
38
 
@@ -47,7 +44,6 @@
47
 
48
  function zoomed(e: Event) {
49
  const transform = ($currZoomTransform = e.transform);
50
- console.log(canvasEl.style.transform, transform);
51
  canvasEl.style.transform = `translate(${transform.x}px, ${transform.y}px) scale(${transform.k})`;
52
  }
53
  function handlePointerMove(e: PointerEvent) {
 
10
  let containerEl: HTMLDivElement;
11
  let canvasCtx: CanvasRenderingContext2D;
12
 
 
 
 
13
  const margin = { top: 100, right: 100, bottom: 100, left: 100 };
14
  const extent = [
15
  [-margin.left, -margin.top],
 
18
  onMount(() => {
19
  const scale = width / containerEl.clientWidth;
20
  const zoomHandler = zoom()
21
+ .scaleExtent([1 / scale, 2])
22
  .translateExtent([
23
  [0, 0],
24
  [width, height]
 
29
 
30
  select(canvasEl.parentElement)
31
  .call(zoomHandler as any)
32
+ // .call(zoomHandler.scaleTo as any, 1 / scale)
33
  .on('pointermove', handlePointerMove)
34
  .on('pointerleave', handlePointerLeave);
35
 
 
44
 
45
  function zoomed(e: Event) {
46
  const transform = ($currZoomTransform = e.transform);
 
47
  canvasEl.style.transform = `translate(${transform.x}px, ${transform.y}px) scale(${transform.k})`;
48
  }
49
  function handlePointerMove(e: PointerEvent) {
frontend/src/lib/Cursor.svelte CHANGED
@@ -1,10 +1,8 @@
1
  <script lang="ts">
2
  import { spring } from 'svelte/motion';
3
- import type { ZoomTransform } from 'd3-zoom';
4
-
5
- export let transform: ZoomTransform;
6
 
7
  export let color = '';
 
8
  export let x = 0;
9
  export let y = 0;
10
 
@@ -20,24 +18,29 @@
20
  $: coords.set({ x, y });
21
  </script>
22
 
23
- <svg
24
- class="block cursor z-0"
25
- fill="none"
26
- height="36"
27
- style={`transform: translateX(${$coords.x}px) translateY(${$coords.y}px) scale(${transform.k})`}
28
- viewBox="0 0 24 36"
29
- width="24"
30
- xmlns="http://www.w3.org/2000/svg"
31
  >
32
- <path
33
- d="M5.65376 12.3673H5.46026L5.31717 12.4976L0.500002 16.8829L0.500002 1.19841L11.7841 12.3673H5.65376Z"
34
- fill={color}
35
- />
36
- </svg>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  <style lang="postcss" scoped>
39
- .cursor {
40
- @apply absolute top-0 left-0;
41
- /* transform-origin: 0 0; */
42
- }
43
  </style>
 
1
  <script lang="ts">
2
  import { spring } from 'svelte/motion';
 
 
 
3
 
4
  export let color = '';
5
+ export let emoji = '';
6
  export let x = 0;
7
  export let y = 0;
8
 
 
18
  $: coords.set({ x, y });
19
  </script>
20
 
21
+ <div
22
+ class="absolute top-0 left-0 grid grid-cols-3"
23
+ style={`transform: translateX(${$coords.x}px) translateY(${$coords.y}px);`}
 
 
 
 
 
24
  >
25
+ <svg
26
+ class="block z-0 col-span-2 row-span-2"
27
+ width="40"
28
+ viewBox="0 0 15 15"
29
+ fill="currentColor"
30
+ xmlns="http://www.w3.org/2000/svg"
31
+ >
32
+ <path
33
+ d="M0.91603 0.916054L7.09131 14.9234L8.89871 8.89873L14.9234 7.09133L0.91603 0.916054Z"
34
+ fill="#FFB800"
35
+ />
36
+ </svg>
37
+ <div
38
+ class="absolute right-0 text-4xl col-start-2 row-start-2"
39
+ style={`text-shadow: 0px 5px 5px ${color}`}
40
+ >
41
+ {emoji}
42
+ </div>
43
+ </div>
44
 
45
  <style lang="postcss" scoped>
 
 
 
 
46
  </style>
frontend/src/lib/Frame.svelte CHANGED
@@ -1,5 +1,7 @@
1
  <script lang="ts">
2
  import { spring } from 'svelte/motion';
 
 
3
  import type { ZoomTransform } from 'd3-zoom';
4
 
5
  export let transform: ZoomTransform;
@@ -20,13 +22,21 @@
20
  </script>
21
 
22
  <div
23
- class="frame z-0"
24
- style={`transform: translateX(${$coords.x}px) translateY(${$coords.y}px) scale(${transform.k})`}
25
- />
 
 
 
 
 
 
 
 
26
 
27
  <style lang="postcss" scoped>
28
  .frame {
29
- @apply pointer-events-none touch-none absolute top-0 left-0 border-2 border-sky-500 bg-gradient-to-b from-sky-200 w-[512px] h-[512px];
30
  transform-origin: 0 0;
31
  }
32
  </style>
 
1
  <script lang="ts">
2
  import { spring } from 'svelte/motion';
3
+ import LoadingIcon from '$lib/LoadingIcon.svelte';
4
+
5
  import type { ZoomTransform } from 'd3-zoom';
6
 
7
  export let transform: ZoomTransform;
 
22
  </script>
23
 
24
  <div
25
+ class="frame z-0 flex relative"
26
+ style={`transform: translateX(${$coords.x}px) translateY(${$coords.y}px) scale(${transform.k});
27
+ background-image: linear-gradient(${color}, rgba(255,255,255,0));
28
+ color: ${color};
29
+ `}
30
+ >
31
+ <LoadingIcon />
32
+ <h2 class="text-lg">Click to paint</h2>
33
+
34
+ <div class="absolute bottom-0 font-bold">A cat on grass</div>
35
+ </div>
36
 
37
  <style lang="postcss" scoped>
38
  .frame {
39
+ @apply pointer-events-none touch-none absolute top-0 left-0 border-2 border-sky-500 w-[512px] h-[512px];
40
  transform-origin: 0 0;
41
  }
42
  </style>
frontend/src/lib/LoadingIcon.svelte ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <svg
2
+ xmlns="http://www.w3.org/2000/svg"
3
+ fill="none"
4
+ width="50"
5
+ viewBox="0 0 24 24"
6
+ class="animate-spin max-w-[1rem] inline-block"
7
+ >
8
+ <path
9
+ fill="currentColor"
10
+ d="M20 12a8 8 0 0 1-8 8v4a12 12 0 0 0 12-12h-4Zm-2-5.3a8 8 0 0 1 2 5.3h4c0-3-1.1-5.8-3-8l-3 2.7Z"
11
+ />
12
+ </svg>
frontend/src/lib/constants.ts ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import colors from 'tailwindcss/colors';
2
+
3
+ export const COLORS = Object.values(colors)
4
+ .filter((e) => typeof e === 'object')
5
+ .map((e) => e['200'])
6
+ .slice(0, 18);
7
+
8
+ // all animal emojis list
9
+ export const EMOJIS = [
10
+ '๐Ÿถ',
11
+ '๐Ÿฑ',
12
+ '๐Ÿญ',
13
+ '๐Ÿน',
14
+ '๐Ÿฐ',
15
+ '๐ŸฆŠ',
16
+ '๐Ÿป',
17
+ '๐Ÿผ',
18
+ '๐Ÿจ',
19
+ '๐Ÿฏ',
20
+ '๐Ÿฆ',
21
+ '๐Ÿฎ',
22
+ '๐Ÿฒ',
23
+ '๐ŸŒš',
24
+ '๐ŸŒ',
25
+ '๐ŸŒž',
26
+ '๐ŸŒ›',
27
+ '๐ŸŒœ'
28
+ ];
frontend/src/lib/store.ts CHANGED
@@ -1,5 +1,4 @@
1
  import { writable, get } from 'svelte/store';
2
- import { onDestroy } from 'svelte';
3
  import type { Room } from '@liveblocks/client';
4
 
5
  import { type ZoomTransform, zoomIdentity } from 'd3-zoom';
 
1
  import { writable, get } from 'svelte/store';
 
2
  import type { Room } from '@liveblocks/client';
3
 
4
  import { type ZoomTransform, zoomIdentity } from 'd3-zoom';
frontend/src/routes/+page.svelte CHANGED
@@ -30,11 +30,16 @@
30
  },
31
  initialStorage: {}
32
  });
 
 
 
 
33
  const unsubscribePresence = createPresenceStore(room);
34
  return () => {
35
  if (client && room) {
36
  client.leave(roomId);
37
  unsubscribePresence();
 
38
  }
39
  };
40
  });
 
30
  },
31
  initialStorage: {}
32
  });
33
+ const unsubscribe = room.subscribe('history', (e) => {
34
+ // Do something
35
+ console.log('history', e);
36
+ });
37
  const unsubscribePresence = createPresenceStore(room);
38
  return () => {
39
  if (client && room) {
40
  client.leave(roomId);
41
  unsubscribePresence();
42
+ unsubscribe();
43
  }
44
  };
45
  });