move.gl 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +38 -0
- package/css/move.gl.css +2 -0
- package/css/move.gl.min.css +2 -0
- package/package.json +55 -0
- package/scss/classes/_animations.scss +576 -0
- package/scss/classes/_index.scss +0 -0
- package/scss/classes/_transforms.scss +124 -0
- package/scss/classes/keyboard.scss +18 -0
- package/scss/classes/screensaver.scss +15 -0
- package/scss/dev/_banner.scss +36 -0
- package/scss/dev/_debug.scss +18 -0
- package/scss/dev/_deprecation.scss +10 -0
- package/scss/dev/_index.scss +8 -0
- package/scss/dev/_modules.scss +24 -0
- package/scss/effects/_filter.scss +176 -0
- package/scss/effects/_index.scss +23 -0
- package/scss/effects/_opacity.scss +62 -0
- package/scss/effects/_shadow.scss +175 -0
- package/scss/functions/_index.scss +0 -0
- package/scss/functions/scenes/_bubble.scss +19 -0
- package/scss/functions/scenes/_index.scss +20 -0
- package/scss/index.scss +0 -0
- package/scss/keyframes/_beat.scss +26 -0
- package/scss/keyframes/_index.scss +0 -0
- package/scss/maps/_index.scss +0 -0
- package/scss/maps/_mouse.scss +96 -0
- package/scss/mixins/_accessibility.scss +70 -0
- package/scss/mixins/_boot.scss +51 -0
- package/scss/mixins/_hover.scss +51 -0
- package/scss/mixins/_index.scss +0 -0
- package/scss/mixins/_selection.scss +321 -0
- package/scss/mixins/_shape.scss +44 -0
- package/scss/mixins/_touch.scss +95 -0
- package/scss/mixins/animations/--hover.scss +107 -0
- package/scss/mixins/animations/_base.scss +337 -0
- package/scss/mixins/animations/_beat.scss +119 -0
- package/scss/mixins/animations/_blink.scss +151 -0
- package/scss/mixins/animations/_bounce.scss +192 -0
- package/scss/mixins/animations/_elastic.scss +65 -0
- package/scss/mixins/animations/_fade.scss +154 -0
- package/scss/mixins/animations/_flash.scss +177 -0
- package/scss/mixins/animations/_flip.scss +72 -0
- package/scss/mixins/animations/_float.scss +126 -0
- package/scss/mixins/animations/_glow.scss +179 -0
- package/scss/mixins/animations/_heartbeat.scss +175 -0
- package/scss/mixins/animations/_hinge.scss +119 -0
- package/scss/mixins/animations/_index.scss +37 -0
- package/scss/mixins/animations/_jello.scss +129 -0
- package/scss/mixins/animations/_jiggle.scss +163 -0
- package/scss/mixins/animations/_lightspeed.scss +130 -0
- package/scss/mixins/animations/_nod.scss +161 -0
- package/scss/mixins/animations/_pop.scss +150 -0
- package/scss/mixins/animations/_pulse.scss +213 -0
- package/scss/mixins/animations/_ripple.scss +169 -0
- package/scss/mixins/animations/_roll.scss +261 -0
- package/scss/mixins/animations/_rotate.scss +428 -0
- package/scss/mixins/animations/_rubber.scss +116 -0
- package/scss/mixins/animations/_scale.scss +113 -0
- package/scss/mixins/animations/_shake.scss +182 -0
- package/scss/mixins/animations/_slide.scss +294 -0
- package/scss/mixins/animations/_spin.scss +219 -0
- package/scss/mixins/animations/_sway.scss +167 -0
- package/scss/mixins/animations/_swing.scss +247 -0
- package/scss/mixins/animations/_tada.scss +233 -0
- package/scss/mixins/animations/_twist.scss +177 -0
- package/scss/mixins/animations/_wave.scss +166 -0
- package/scss/mixins/animations/_wobble.scss +254 -0
- package/scss/mixins/animations/_zoom.scss +166 -0
- package/scss/mixins/effects/_filter.scss +148 -0
- package/scss/mixins/effects/_index.scss +0 -0
- package/scss/mixins/effects/_shadow.scss +21 -0
- package/scss/mixins/loaders/_index.scss +0 -0
- package/scss/mixins/loaders/_progress.scss +174 -0
- package/scss/mixins/loaders/_spinner.scss +101 -0
- package/scss/mixins/loaders/circle_01.scss +22 -0
- package/scss/mixins/loaders/circle_02.scss +19 -0
- package/scss/mixins/loaders/circle_03.scss +29 -0
- package/scss/mixins/loaders/circle_inner_01.scss +33 -0
- package/scss/mixins/loaders/circle_inner_02.scss +33 -0
- package/scss/mixins/loaders/circle_inner_03.scss +34 -0
- package/scss/mixins/mouse/_cursor.scss +182 -0
- package/scss/mixins/mouse/_index.scss +0 -0
- package/scss/mixins/mouse/_pointer.scss +258 -0
- package/scss/mixins/scroll/_index.scss +0 -0
- package/scss/mixins/scroll/_scroll.scss +104 -0
- package/scss/mixins/scroll/_scrollbar.scss +249 -0
- package/scss/mixins/transforms/_flip.scss +76 -0
- package/scss/mixins/transforms/_index.scss +23 -0
- package/scss/mixins/transforms/_matrix.scss +1 -0
- package/scss/mixins/transforms/_perspective.scss +11 -0
- package/scss/mixins/transforms/_rotate.scss +101 -0
- package/scss/mixins/transforms/_scale.scss +11 -0
- package/scss/mixins/transforms/_skew.scss +13 -0
- package/scss/mixins/transforms/_translate.scss +13 -0
- package/scss/mixins/transitions/_index.scss +0 -0
- package/scss/mixins/transitions/_transition.scss +13 -0
- package/scss/variables/_animation.scss +91 -0
- package/scss/variables/_index.scss +0 -0
- package/ts/ARContent.ts +27 -0
- package/ts/ARInteraction.ts +34 -0
- package/ts/AdaptiveUI.ts +25 -0
- package/ts/ContentStreaming.ts +20 -0
- package/ts/Draggable.ts +71 -0
- package/ts/DynamicEnvironment.ts +60 -0
- package/ts/Gesture.ts +168 -0
- package/ts/ImmersiveAudio.ts +40 -0
- package/ts/InteractiveCanvas.ts +177 -0
- package/ts/InteractiveVideo.ts +29 -0
- package/ts/Keyboard.ts +162 -0
- package/ts/RealTimeCollaboration.ts +25 -0
- package/ts/Screensaver.ts +140 -0
- package/ts/SpatialNavigation.ts +38 -0
- package/ts/UserProfile.ts +27 -0
- package/ts/VRExperience.ts +58 -0
- package/ts/VideoOverlay.ts +116 -0
- package/ts/index.ts +0 -0
package/ts/AdaptiveUI.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title Adaptive UI Elements Handler
|
|
3
|
+
* @notice Dynamically adjusts UI components based on user interactions and environmental contexts.
|
|
4
|
+
* @dev Utilizes event listeners and media queries to adapt the UI for different user needs and device capabilities.
|
|
5
|
+
*/
|
|
6
|
+
class AdaptiveUIHandler {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.setupResponsiveListeners();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
private setupResponsiveListeners() {
|
|
12
|
+
window.addEventListener('resize', this.adjustLayout);
|
|
13
|
+
window.addEventListener('orientationchange', this.adjustLayout);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
private adjustLayout = () => {
|
|
17
|
+
if (window.innerWidth < 600) {
|
|
18
|
+
console.log("Switching to mobile layout");
|
|
19
|
+
// Adjust UI for mobile layout.
|
|
20
|
+
} else {
|
|
21
|
+
console.log("Switching to desktop layout");
|
|
22
|
+
// Adjust UI for desktop layout.
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title Dynamic Content Streaming Handler
|
|
3
|
+
* @notice Manages the streaming and dynamic loading of content into web applications, optimizing for network and rendering performance.
|
|
4
|
+
* @dev Utilizes service workers and caching strategies to manage content delivery and updates.
|
|
5
|
+
*/
|
|
6
|
+
class ContentStreamingHandler {
|
|
7
|
+
constructor(private baseUrl: string) {}
|
|
8
|
+
|
|
9
|
+
public async streamContent(contentPath: string) {
|
|
10
|
+
const response = await fetch(`${this.baseUrl}/${contentPath}`);
|
|
11
|
+
if (!response.ok) {
|
|
12
|
+
throw new Error('Failed to load content: ' + response.statusText);
|
|
13
|
+
}
|
|
14
|
+
return response.blob(); // Return the raw data for further processing or direct display
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public updateContentCache(contentId: string, data: Blob) {
|
|
18
|
+
// Use IndexedDB or local storage to cache content for offline use or quicker loading
|
|
19
|
+
}
|
|
20
|
+
}
|
package/ts/Draggable.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Copyright 2024 Scape Agency BV
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// Draggable Element Class
|
|
5
|
+
// Creating draggable elements on the screen can enhance interactivity, especially for applications that involve organizing or direct manipulation of elements, such as dashboards or graphic editors.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @title Draggable Element Handler
|
|
10
|
+
* @notice Provides functionality to make an element draggable within the confines of its parent container.
|
|
11
|
+
* @dev Supports both mouse and touch interactions, ensuring usability across different devices.
|
|
12
|
+
*/
|
|
13
|
+
class Draggable {
|
|
14
|
+
private element: HTMLElement;
|
|
15
|
+
private isDragging: boolean = false;
|
|
16
|
+
private startX: number;
|
|
17
|
+
private startY: number;
|
|
18
|
+
private boundRect: DOMRect;
|
|
19
|
+
|
|
20
|
+
constructor(elementId: string) {
|
|
21
|
+
this.element = document.getElementById(elementId) as HTMLElement;
|
|
22
|
+
this.boundRect = this.element.parentElement!.getBoundingClientRect();
|
|
23
|
+
this.attachEventListeners();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private attachEventListeners() {
|
|
27
|
+
this.element.addEventListener('mousedown', this.startDrag);
|
|
28
|
+
this.element.addEventListener('touchstart', this.startDrag, { passive: false });
|
|
29
|
+
|
|
30
|
+
document.addEventListener('mouseup', this.stopDrag);
|
|
31
|
+
document.addEventListener('touchend', this.stopDrag);
|
|
32
|
+
|
|
33
|
+
document.addEventListener('mousemove', this.drag);
|
|
34
|
+
document.addEventListener('touchmove', this.drag, { passive: false });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private startDrag = (event: MouseEvent | TouchEvent) => {
|
|
38
|
+
if (event instanceof TouchEvent) {
|
|
39
|
+
event = event.touches[0];
|
|
40
|
+
}
|
|
41
|
+
this.isDragging = true;
|
|
42
|
+
this.startX = event.clientX - this.element.offsetLeft;
|
|
43
|
+
this.startY = event.clientY - this.element.offsetTop;
|
|
44
|
+
event.preventDefault();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
private drag = (event: MouseEvent | TouchEvent) => {
|
|
48
|
+
if (!this.isDragging) return;
|
|
49
|
+
if (event instanceof TouchEvent) {
|
|
50
|
+
event = event.touches[0];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let x = event.clientX - this.startX;
|
|
54
|
+
let y = event.clientY - this.startY;
|
|
55
|
+
|
|
56
|
+
// Constrain the movement within the bounds of the element's parent
|
|
57
|
+
x = Math.max(this.boundRect.left, Math.min(x, this.boundRect.right - this.element.offsetWidth));
|
|
58
|
+
y = Math.max(this.boundRect.top, Math.min(y, this.boundRect.bottom - this.element.offsetHeight));
|
|
59
|
+
|
|
60
|
+
this.element.style.left = `${x}px`;
|
|
61
|
+
this.element.style.top = `${y}px`;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
private stopDrag = () => {
|
|
65
|
+
if (this.isDragging) {
|
|
66
|
+
this.isDragging = false;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
new Draggable('draggableElement');
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title Dynamic Environment Handler
|
|
3
|
+
* @notice Controls dynamic changes in the virtual environment to enhance immersion.
|
|
4
|
+
* @dev Manages environmental effects like lighting, weather, and background changes.
|
|
5
|
+
*/
|
|
6
|
+
class DynamicEnvironmentHandler {
|
|
7
|
+
private environmentSettings: any;
|
|
8
|
+
|
|
9
|
+
constructor(private scene: any) {
|
|
10
|
+
this.environmentSettings = {
|
|
11
|
+
lighting: 'daylight',
|
|
12
|
+
weather: 'clear'
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public changeLighting(type: string) {
|
|
17
|
+
// Change lighting type in the scene
|
|
18
|
+
this.environmentSettings.lighting = type;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public changeWeather(type: string) {
|
|
22
|
+
// Implement weather changes such as rain, snow, or fog
|
|
23
|
+
this.environmentSettings.weather = type;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public updateEnvironment() {
|
|
27
|
+
// Apply the changes to the scene based on current settings
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @title Environmental Effects Handler
|
|
36
|
+
* @notice Manages and applies dynamic environmental effects within immersive web applications.
|
|
37
|
+
* @dev Provides an API to change environmental conditions programmatically.
|
|
38
|
+
*/
|
|
39
|
+
class EnvironmentalEffectsHandler {
|
|
40
|
+
private scene: any; // This would be your 3D scene object from a library like Three.js
|
|
41
|
+
|
|
42
|
+
constructor(scene: any) {
|
|
43
|
+
this.scene = scene;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public changeWeather(weatherType: string) {
|
|
47
|
+
console.log(`Changing weather to ${weatherType}`);
|
|
48
|
+
// Implementation depends on how weather effects are visualized. This could involve changing textures, particle systems, etc.
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public toggleDayNight(isNight: boolean) {
|
|
52
|
+
console.log(`Setting environment to ${isNight ? "night" : "day"}`);
|
|
53
|
+
// Adjust lighting, skybox, and other environmental factors to reflect day or night
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public triggerLightning() {
|
|
57
|
+
console.log("Triggering lightning effect");
|
|
58
|
+
// Activate a lightning effect with visuals and sound
|
|
59
|
+
}
|
|
60
|
+
}
|
package/ts/Gesture.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// Copyright 2024 Scape Agency BV
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// Touch Gesture Handler Class
|
|
5
|
+
// A class for handling touch gestures can interpret user input like swipes, taps, and pinch actions, which are common in mobile and modern web applications.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @title Touch Gesture Handler Class
|
|
10
|
+
* @notice Manages touch interactions on a specified element, interpreting various gestures like taps, swipes, and pinches.
|
|
11
|
+
* @dev This class attaches touch event listeners to an element and interprets common gestures by analyzing touch points.
|
|
12
|
+
*/
|
|
13
|
+
class TouchGestureHandler {
|
|
14
|
+
private element: HTMLElement;
|
|
15
|
+
private startTouches: TouchList | null = null;
|
|
16
|
+
private isSwiping = false;
|
|
17
|
+
private isPinching = false;
|
|
18
|
+
|
|
19
|
+
constructor(elementId: string) {
|
|
20
|
+
this.element = document.getElementById(elementId) as HTMLElement;
|
|
21
|
+
this.addTouchListeners();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private addTouchListeners() {
|
|
25
|
+
this.element.addEventListener('touchstart', this.handleTouchStart, false);
|
|
26
|
+
this.element.addEventListener('touchmove', this.handleTouchMove, false);
|
|
27
|
+
this.element.addEventListener('touchend', this.handleTouchEnd, false);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private handleTouchStart = (event: TouchEvent) => {
|
|
31
|
+
if (event.touches.length === 1) {
|
|
32
|
+
this.startTouches = event.touches;
|
|
33
|
+
console.log("Tap started or potential swipe:", event.touches);
|
|
34
|
+
} else if (event.touches.length > 1) {
|
|
35
|
+
this.startTouches = event.touches;
|
|
36
|
+
console.log("Pinch started or potential rotation:", event.touches);
|
|
37
|
+
this.isPinching = true;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
private handleTouchMove = (event: TouchEvent) => {
|
|
42
|
+
if (event.touches.length === 1 && this.startTouches && !this.isPinching) {
|
|
43
|
+
const dx = event.touches[0].clientX - this.startTouches[0].clientX;
|
|
44
|
+
const dy = event.touches[0].clientY - this.startTouches[0].clientY;
|
|
45
|
+
if (Math.abs(dx) > 10 || Math.abs(dy) > 10) {
|
|
46
|
+
this.isSwiping = true;
|
|
47
|
+
console.log(`Swipe detected: deltaX = ${dx}, deltaY = ${dy}`);
|
|
48
|
+
}
|
|
49
|
+
} else if (event.touches.length > 1 && this.isPinching) {
|
|
50
|
+
const startDistance = this.getDistance(this.startTouches[0], this.startTouches[1]);
|
|
51
|
+
const currentDistance = this.getDistance(event.touches[0], event.touches[1]);
|
|
52
|
+
const scale = currentDistance / startDistance;
|
|
53
|
+
console.log(`Pinch scaling factor: ${scale}`);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
private handleTouchEnd = (event: TouchEvent) => {
|
|
58
|
+
if (this.isSwiping) {
|
|
59
|
+
console.log("Swipe ended");
|
|
60
|
+
this.isSwiping = false;
|
|
61
|
+
} else if (this.isPinching) {
|
|
62
|
+
console.log("Pinch ended");
|
|
63
|
+
this.isPinching = false;
|
|
64
|
+
} else {
|
|
65
|
+
console.log("Tap confirmed");
|
|
66
|
+
}
|
|
67
|
+
this.startTouches = null;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Calculates the distance between two touch points.
|
|
72
|
+
* @param touch1 First touch point.
|
|
73
|
+
* @param touch2 Second touch point.
|
|
74
|
+
* @returns Distance in pixels.
|
|
75
|
+
*/
|
|
76
|
+
private getDistance(touch1: Touch, touch2: Touch): number {
|
|
77
|
+
const dx = touch2.clientX - touch1.clientX;
|
|
78
|
+
const dy = touch2.clientY - touch1.clientY;
|
|
79
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
new TouchGestureHandler('touchElement');
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @title Advanced Gesture Recognition Handler
|
|
93
|
+
* @notice Handles complex gestures for interactive applications, enhancing user experience with intuitive controls.
|
|
94
|
+
* @dev Utilizes pointer events to detect and interpret various gestures.
|
|
95
|
+
*/
|
|
96
|
+
class AdvancedGestureRecognition {
|
|
97
|
+
private element: HTMLElement;
|
|
98
|
+
private ongoingTouches: Map<number, Touch> = new Map();
|
|
99
|
+
|
|
100
|
+
constructor(elementId: string) {
|
|
101
|
+
this.element = document.getElementById(elementId) as HTMLElement;
|
|
102
|
+
this.attachEventListeners();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private attachEventListeners() {
|
|
106
|
+
this.element.addEventListener('pointerdown', this.handleGestureStart, { passive: false });
|
|
107
|
+
this.element.addEventListener('pointermove', this.handleGestureMove, { passive: false });
|
|
108
|
+
this.element.addEventListener('pointerup', this.handleGestureEnd, { passive: false });
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private handleGestureStart = (event: PointerEvent) => {
|
|
112
|
+
this.ongoingTouches.set(event.pointerId, event);
|
|
113
|
+
console.log("Gesture started:", event.pointerType);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
private handleGestureMove = (event: PointerEvent) => {
|
|
117
|
+
if (this.ongoingTouches.has(event.pointerId)) {
|
|
118
|
+
const startEvent = this.ongoingTouches.get(event.pointerId)!;
|
|
119
|
+
const dx = event.clientX - startEvent.clientX;
|
|
120
|
+
const dy = event.clientY - startEvent.clientY;
|
|
121
|
+
console.log(`Gesture moved: ${dx}px horizontal, ${dy}px vertical`);
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
private handleGestureEnd = (event: PointerEvent) => {
|
|
126
|
+
this.ongoingTouches.delete(event.pointerId);
|
|
127
|
+
console.log("Gesture ended");
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* @title Advanced Interaction Controls
|
|
136
|
+
* @notice Enhances user interactions within immersive environments with sophisticated input methods.
|
|
137
|
+
* @dev Integrates gesture recognition, voice commands, and potentially eye tracking for advanced control.
|
|
138
|
+
*/
|
|
139
|
+
class AdvancedInteractionControls {
|
|
140
|
+
constructor() {
|
|
141
|
+
this.initializeGestureControls();
|
|
142
|
+
this.initializeVoiceCommands();
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private initializeGestureControls() {
|
|
146
|
+
console.log("Gesture controls initialized.");
|
|
147
|
+
// Setup gesture recognition logic or integrate with a library like Hammer.js
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private initializeVoiceCommands() {
|
|
151
|
+
console.log("Voice command system initialized.");
|
|
152
|
+
// Setup voice recognition using APIs like the Web Speech API
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public onGestureRecognized(gesture: string) {
|
|
156
|
+
console.log(`Gesture recognized: ${gesture}`);
|
|
157
|
+
// Respond to specific gestures
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
public onVoiceCommand(command: string) {
|
|
161
|
+
console.log(`Voice command received: ${command}`);
|
|
162
|
+
// Execute actions based on voice commands
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title Immersive Audio Handler
|
|
3
|
+
* @notice Provides control over spatial and immersive audio in web applications.
|
|
4
|
+
*/
|
|
5
|
+
class ImmersiveAudioHandler {
|
|
6
|
+
private audioContext: AudioContext;
|
|
7
|
+
private listener: AudioListener;
|
|
8
|
+
private soundSources: Map<string, AudioBufferSourceNode> = new Map();
|
|
9
|
+
|
|
10
|
+
constructor() {
|
|
11
|
+
this.audioContext = new AudioContext();
|
|
12
|
+
this.listener = this.audioContext.listener;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public loadSound(url: string, id: string): Promise<void> {
|
|
16
|
+
return fetch(url)
|
|
17
|
+
.then(response => response.arrayBuffer())
|
|
18
|
+
.then(buffer => this.audioContext.decodeAudioData(buffer))
|
|
19
|
+
.then(decodedBuffer => {
|
|
20
|
+
const source = this.audioContext.createBufferSource();
|
|
21
|
+
source.buffer = decodedBuffer;
|
|
22
|
+
source.connect(this.audioContext.destination);
|
|
23
|
+
this.soundSources.set(id, source);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public playSound(id: string) {
|
|
28
|
+
const source = this.soundSources.get(id);
|
|
29
|
+
if (source) {
|
|
30
|
+
source.start();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public stopSound(id: string) {
|
|
35
|
+
const source = this.soundSources.get(id);
|
|
36
|
+
if (source) {
|
|
37
|
+
source.stop();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Copyright 2024 Scape Agency BV
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
// Interactive Canvas Class
|
|
6
|
+
// A class for an interactive canvas can enable users to draw, which is
|
|
7
|
+
// beneficial for applications like signature pads, drawing tools, or educational apps.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @title Interactive Canvas for Drawing
|
|
12
|
+
* @notice This class enables drawing functionalities on a canvas element, supporting features like brush customization, undo/redo actions, and touch responsiveness.
|
|
13
|
+
* @dev Implements event listeners for both mouse and touch interactions, provides methods for brush customization, and maintains a history stack for undo/redo capabilities.
|
|
14
|
+
*/
|
|
15
|
+
class InteractiveCanvas {
|
|
16
|
+
private canvas: HTMLCanvasElement;
|
|
17
|
+
private context: CanvasRenderingContext2D;
|
|
18
|
+
private painting: boolean = false;
|
|
19
|
+
private brushSize: number = 5;
|
|
20
|
+
private brushColor: string = '#000000';
|
|
21
|
+
private lineOpacity: number = 1.0;
|
|
22
|
+
private history: ImageData[] = [];
|
|
23
|
+
private historyStep: number = 0;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Constructs an InteractiveCanvas instance linked to a specific canvas element.
|
|
27
|
+
* @param canvasId The DOM ID of the canvas element.
|
|
28
|
+
*/
|
|
29
|
+
constructor(canvasId: string) {
|
|
30
|
+
this.canvas = document.getElementById(canvasId) as HTMLCanvasElement;
|
|
31
|
+
this.context = this.canvas.getContext('2d')!;
|
|
32
|
+
this.setupCanvas();
|
|
33
|
+
this.attachEventListeners();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Sets up the canvas drawing context and adjusts the canvas size to its initial container.
|
|
38
|
+
*/
|
|
39
|
+
private setupCanvas() {
|
|
40
|
+
this.context.lineWidth = this.brushSize;
|
|
41
|
+
this.context.lineCap = 'round';
|
|
42
|
+
this.context.strokeStyle = this.brushColor;
|
|
43
|
+
this.context.globalAlpha = this.lineOpacity;
|
|
44
|
+
window.addEventListener('resize', this.resizeCanvas);
|
|
45
|
+
this.resizeCanvas();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Attaches necessary event listeners for mouse and touch interactions.
|
|
50
|
+
*/
|
|
51
|
+
private attachEventListeners() {
|
|
52
|
+
this.canvas.addEventListener('mousedown', this.startPaint);
|
|
53
|
+
this.canvas.addEventListener('mouseup', this.endPaint);
|
|
54
|
+
this.canvas.addEventListener('mousemove', this.paint);
|
|
55
|
+
this.canvas.addEventListener('touchstart', this.startPaint, { passive: false });
|
|
56
|
+
this.canvas.addEventListener('touchend', this.endPaint);
|
|
57
|
+
this.canvas.addEventListener('touchmove', this.paint, { passive: false });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Adjusts the canvas size to fit its container, ensuring that it is responsive to window size changes.
|
|
62
|
+
*/
|
|
63
|
+
private resizeCanvas = () => {
|
|
64
|
+
this.canvas.width = this.canvas.offsetWidth;
|
|
65
|
+
this.canvas.height = this.canvas.offsetHeight;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Initiates painting on the canvas, records the initial position, and saves the state for undo functionality.
|
|
70
|
+
* @param event Mouse or touch event that triggers the start of painting.
|
|
71
|
+
*/
|
|
72
|
+
private startPaint = (event: MouseEvent | TouchEvent) => {
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
this.painting = true;
|
|
75
|
+
const pos = this.getEventPosition(event);
|
|
76
|
+
this.context.moveTo(pos.x, pos.y);
|
|
77
|
+
this.context.beginPath();
|
|
78
|
+
this.saveState();
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Stops the painting process on the canvas.
|
|
83
|
+
*/
|
|
84
|
+
private endPaint = () => {
|
|
85
|
+
this.painting = false;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Continues the painting process, drawing lines based on mouse or touch movements.
|
|
90
|
+
* @param event Mouse or touch event containing the current position for painting.
|
|
91
|
+
*/
|
|
92
|
+
private paint = (event: MouseEvent | TouchEvent) => {
|
|
93
|
+
if (!this.painting) return;
|
|
94
|
+
const pos = this.getEventPosition(event);
|
|
95
|
+
this.context.lineTo(pos.x, pos.y);
|
|
96
|
+
this.context.stroke();
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Calculates the precise position of the mouse or touch event relative to the canvas.
|
|
101
|
+
* @param event Mouse or touch event.
|
|
102
|
+
* @returns The calculated position as an object with x and y coordinates.
|
|
103
|
+
*/
|
|
104
|
+
private getEventPosition(event: MouseEvent | TouchEvent) {
|
|
105
|
+
if (event instanceof TouchEvent) {
|
|
106
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
107
|
+
const touch = event.touches[0];
|
|
108
|
+
return { x: touch.clientX - rect.left, y: touch.clientY - rect.top };
|
|
109
|
+
} else {
|
|
110
|
+
return { x: event.clientX - this.canvas.offsetLeft, y: event.clientY - this.canvas.offsetTop };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Sets the brush size for painting.
|
|
116
|
+
* @param size New brush size.
|
|
117
|
+
*/
|
|
118
|
+
public setBrushSize(size: number) {
|
|
119
|
+
this.brushSize = size;
|
|
120
|
+
this.context.lineWidth = size;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Sets the color of the brush.
|
|
125
|
+
* @param color New brush color in CSS format.
|
|
126
|
+
*/
|
|
127
|
+
public setBrushColor(color: string) {
|
|
128
|
+
this.brushColor = color;
|
|
129
|
+
this.context.strokeStyle = color;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Sets the opacity of the brush strokes.
|
|
134
|
+
* @param opacity A value between 0.0 (fully transparent) and 1.0 (fully opaque).
|
|
135
|
+
*/
|
|
136
|
+
public setOpacity(opacity: number) {
|
|
137
|
+
this.lineOpacity = opacity;
|
|
138
|
+
this.context.globalAlpha = opacity;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Undoes the last action taken on the canvas, reverting to the previous state.
|
|
143
|
+
*/
|
|
144
|
+
public undo() {
|
|
145
|
+
if (this.historyStep > 0) {
|
|
146
|
+
this.historyStep--;
|
|
147
|
+
this.context.putImageData(this.history[this.historyStep], 0, 0);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Redoes an action that was previously undone on the canvas, if possible.
|
|
153
|
+
*/
|
|
154
|
+
public redo() {
|
|
155
|
+
if (this.historyStep < this.history.length - 1) {
|
|
156
|
+
this.historyStep++;
|
|
157
|
+
this.context.putImageData(this.history[this.historyStep], 0, 0);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Saves the current state of the canvas for future undo operations.
|
|
163
|
+
*/
|
|
164
|
+
private saveState() {
|
|
165
|
+
if (this.historyStep < this.history.length) this.history.splice(this.historyStep);
|
|
166
|
+
this.history.push(this.context.getImageData(0, 0, this.canvas.width, this.canvas.height));
|
|
167
|
+
this.historyStep = this.history.length;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Clears the entire canvas and saves the state for undo functionality.
|
|
172
|
+
*/
|
|
173
|
+
public clearCanvas() {
|
|
174
|
+
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
175
|
+
this.saveState();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title Interactive Video Playback Handler
|
|
3
|
+
* @notice Manages complex interactive video elements within web applications.
|
|
4
|
+
*/
|
|
5
|
+
class InteractiveVideoHandler {
|
|
6
|
+
private videoElement: HTMLVideoElement;
|
|
7
|
+
|
|
8
|
+
constructor(videoId: string) {
|
|
9
|
+
this.videoElement = document.getElementById(videoId) as HTMLVideoElement;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public addHotspot(x: number, y: number, callback: () => void) {
|
|
13
|
+
const hotspot = document.createElement("button");
|
|
14
|
+
hotspot.style.position = "absolute";
|
|
15
|
+
hotspot.style.left = `${x}px`;
|
|
16
|
+
hotspot.style.top = `${y}px`;
|
|
17
|
+
hotspot.innerText = "Click me!";
|
|
18
|
+
hotspot.addEventListener("click", callback);
|
|
19
|
+
this.videoElement.parentElement!.appendChild(hotspot);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public play() {
|
|
23
|
+
this.videoElement.play();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public pause() {
|
|
27
|
+
this.videoElement.pause();
|
|
28
|
+
}
|
|
29
|
+
}
|