Web TypeScript 移动端功能示例
Web TypeScript 移动端功能示例,包括设备信息、网络状态和振动提示
💻 设备信息 typescript
🟢 simple
⭐⭐⭐
获取设备信息,包括类型、操作系统、浏览器、屏幕和硬件功能
⏱️ 20 min
🏷️ typescript, web, mobile features
Prerequisites:
Basic TypeScript, Navigator API, Screen API
// Web TypeScript Device Information Examples
// Using Navigator API and Screen API for device detection
// 1. Device Info Manager
class DeviceInfoManager {
// Get basic device info
getDeviceInfo(): {
userAgent: string;
platform: string;
vendor: string;
language: string;
cookiesEnabled: boolean;
onLine: boolean;
hardwareConcurrency: number;
deviceMemory: number;
maxTouchPoints: number;
} {
const nav = navigator as any;
return {
userAgent: navigator.userAgent,
platform: navigator.platform,
vendor: navigator.vendor,
language: navigator.language,
cookiesEnabled: navigator.cookieEnabled,
onLine: navigator.onLine,
hardwareConcurrency: navigator.hardwareConcurrency || 0,
deviceMemory: nav.deviceMemory || 0,
maxTouchPoints: navigator.maxTouchPoints || 0
};
}
// Get device type
getDeviceType(): 'desktop' | 'mobile' | 'tablet' {
const userAgent = navigator.userAgent.toLowerCase();
const maxTouchPoints = navigator.maxTouchPoints || 0;
// Check for mobile
const isMobile = /android|iphone|ipod|blackberry|iemobile|opera mini/i.test(userAgent);
// Check for tablet
const isTablet = /ipad|android(?!.*mobile)|tablet/i.test(userAgent) ||
(maxTouchPoints > 0 && /macintosh/i.test(userAgent));
if (isTablet) return 'tablet';
if (isMobile) return 'mobile';
return 'desktop';
}
// Get OS information
getOSInfo(): {
name: string;
version: string;
} {
const userAgent = navigator.userAgent;
let name = 'Unknown';
let version = 'Unknown';
if (/windows/i.test(userAgent)) {
name = 'Windows';
const match = userAgent.match(/Windows NT (\d+\.\d+)/);
if (match) version = match[1];
} else if (/macintosh|mac os x/i.test(userAgent)) {
name = 'macOS';
const match = userAgent.match(/Mac OS X (\d+[._]\d+)/);
if (match) version = match[1].replace(/_/g, '.');
} else if (/android/i.test(userAgent)) {
name = 'Android';
const match = userAgent.match(/Android (\d+\.\d+)/);
if (match) version = match[1];
} else if (/iphone|ipad|ipod/i.test(userAgent)) {
name = 'iOS';
const match = userAgent.match(/OS (\d+_\d+)/);
if (match) version = match[1].replace(/_/g, '.');
} else if (/linux/i.test(userAgent)) {
name = 'Linux';
}
return { name, version };
}
// Get browser info
getBrowserInfo(): {
name: string;
version: string;
} {
const userAgent = navigator.userAgent;
let name = 'Unknown';
let version = 'Unknown';
if (/chrome/i.test(userAgent) && !/edge|opr/i.test(userAgent)) {
name = 'Chrome';
const match = userAgent.match(/Chrome\/(\d+\.\d+\.\d+\.\d+)/);
if (match) version = match[1];
} else if (/safari/i.test(userAgent) && !/chrome/i.test(userAgent)) {
name = 'Safari';
const match = userAgent.match(/Version\/(\d+\.\d+)/);
if (match) version = match[1];
} else if (/firefox/i.test(userAgent)) {
name = 'Firefox';
const match = userAgent.match(/Firefox\/(\d+\.\d+)/);
if (match) version = match[1];
} else if (/edge/i.test(userAgent)) {
name = 'Edge';
const match = userAgent.match(/Edge\/(\d+\.\d+)/);
if (match) version = match[1];
} else if (/opr/i.test(userAgent)) {
name = 'Opera';
const match = userAgent.match(/OPR\/(\d+\.\d+)/);
if (match) version = match[1];
}
return { name, version };
}
// Get screen info
getScreenInfo(): {
width: number;
height: number;
availWidth: number;
availHeight: number;
colorDepth: number;
pixelDepth: number;
orientation: string;
devicePixelRatio: number;
} {
const screen = window.screen;
const orientation = (screen.orientation?.type || 'unknown');
return {
width: screen.width,
height: screen.height,
availWidth: screen.availWidth,
availHeight: screen.availHeight,
colorDepth: screen.colorDepth,
pixelDepth: screen.pixelDepth,
orientation,
devicePixelRatio: window.devicePixelRatio
};
}
// Get viewport info
getViewportInfo(): {
width: number;
height: number;
scrollX: number;
scrollY: number;
} {
return {
width: window.innerWidth,
height: window.innerHeight,
scrollX: window.scrollX,
scrollY: window.scrollY
};
}
// Check if touch device
isTouchDevice(): boolean {
return 'ontouchstart' in window ||
navigator.maxTouchPoints > 0 ||
(navigator as any).msMaxTouchPoints > 0;
}
// Check if retina display
isRetinaDisplay(): boolean {
return window.devicePixelRatio > 1;
}
// Get complete device report
getCompleteReport(): {
device: any;
os: any;
browser: any;
screen: any;
viewport: any;
capabilities: any;
} {
return {
device: {
type: this.getDeviceType(),
info: this.getDeviceInfo()
},
os: this.getOSInfo(),
browser: this.getBrowserInfo(),
screen: this.getScreenInfo(),
viewport: this.getViewportInfo(),
capabilities: {
touch: this.isTouchDevice(),
retina: this.isRetinaDisplay(),
webGL: this.checkWebGL(),
webWorker: 'Worker' in window,
serviceWorker: 'serviceWorker' in navigator,
localStorage: this.checkLocalStorage(),
sessionStorage: this.checkSessionStorage()
}
};
}
private checkWebGL(): boolean {
try {
const canvas = document.createElement('canvas');
return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
} catch {
return false;
}
}
private checkLocalStorage(): boolean {
try {
localStorage.setItem('test', 'test');
localStorage.removeItem('test');
return true;
} catch {
return false;
}
}
private checkSessionStorage(): boolean {
try {
sessionStorage.setItem('test', 'test');
sessionStorage.removeItem('test');
return true;
} catch {
return false;
}
}
}
// 2. Battery Manager
class BatteryManager {
private battery: any = null;
// Initialize battery API
async initialize(): Promise<void> {
if ('getBattery' in navigator) {
this.battery = await (navigator as any).getBattery();
}
}
// Check if battery API is supported
isSupported(): boolean {
return 'getBattery' in navigator;
}
// Get battery info
getBatteryInfo(): {
charging: boolean;
level: number;
chargingTime: number;
dischargingTime: number;
} | null {
if (!this.battery) {
return null;
}
return {
charging: this.battery.charging,
level: this.battery.level,
chargingTime: this.battery.chargingTime,
dischargingTime: this.battery.dischargingTime
};
}
// Add battery change listener
addChangeListener(callback: (info: any) => void): void {
if (this.battery) {
this.battery.addEventListener('levelchange', () => callback(this.getBatteryInfo()));
this.battery.addEventListener('chargingchange', () => callback(this.getBatteryInfo()));
this.battery.addEventListener('chargingtimechange', () => callback(this.getBatteryInfo()));
this.battery.addEventListener('dischargingtimechange', () => callback(this.getBatteryInfo()));
}
}
}
// 3. Memory Manager
class MemoryManager {
// Get memory info (Chrome only)
getMemoryInfo(): {
jsHeapSizeLimit: number;
totalJSHeapSize: number;
usedJSHeapSize: number;
} | null {
const performance = (window as any).performance;
if (performance && performance.memory) {
return {
jsHeapSizeLimit: performance.memory.jsHeapSizeLimit,
totalJSHeapSize: performance.memory.totalJSHeapSize,
usedJSHeapSize: performance.memory.usedJSHeapSize
};
}
return null;
}
// Get memory usage percentage
getMemoryUsage(): number | null {
const memory = this.getMemoryInfo();
if (!memory) return null;
return (memory.usedJSHeapSize / memory.jsHeapSizeLimit) * 100;
}
// Format bytes to readable string
formatBytes(bytes: number): string {
const mb = bytes / (1024 * 1024);
return mb.toFixed(2) + ' MB';
}
}
// 4. Connection Manager
class ConnectionManager {
// Get connection info
getConnectionInfo(): {
effectiveType: string;
downlink: number;
rtt: number;
saveData: boolean;
} | null {
const connection = (navigator as any).connection || (navigator as any).mozConnection || (navigator as any).webkitConnection;
if (!connection) {
return null;
}
return {
effectiveType: connection.effectiveType || 'unknown',
downlink: connection.downlink || 0,
rtt: connection.rtt || 0,
saveData: connection.saveData || false
};
}
// Check if slow connection
isSlowConnection(): boolean {
const info = this.getConnectionInfo();
if (!info) return false;
return info.effectiveType === 'slow-2g' || info.effectiveType === '2g';
}
// Check if fast connection
isFastConnection(): boolean {
const info = this.getConnectionInfo();
if (!info) return false;
return info.effectiveType === '4g';
}
}
// 5. Orientation Manager
class OrientationManager {
// Get current orientation
getOrientation(): 'portrait' | 'landscape' {
return window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
}
// Lock orientation (experimental)
async lockOrientation(orientation: 'portrait' | 'landscape'): Promise<boolean> {
try {
if ((screen.orientation as any).lock) {
await screen.orientation.lock(orientation);
return true;
}
return false;
} catch {
return false;
}
}
// Unlock orientation
unlockOrientation(): void {
if ((screen.orientation as any).unlock) {
screen.orientation.unlock();
}
}
// Add orientation change listener
addChangeListener(callback: (orientation: 'portrait' | 'landscape') => void): void {
window.addEventListener('orientationchange', () => {
callback(this.getOrientation());
});
window.addEventListener('resize', () => {
callback(this.getOrientation());
});
}
}
// 6. Device Capability Detector
class DeviceCapabilityDetector {
// Check for camera support
async hasCamera(): Promise<boolean> {
try {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.some(device => device.kind === 'videoinput');
} catch {
return false;
}
}
// Check for microphone support
async hasMicrophone(): Promise<boolean> {
try {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.some(device => device.kind === 'audioinput');
} catch {
return false;
}
}
// Check for geolocation support
hasGeolocation(): boolean {
return 'geolocation' in navigator;
}
// Check for vibration support
hasVibration(): boolean {
return 'vibrate' in navigator;
}
// Check for Bluetooth support
hasBluetooth(): boolean {
return 'bluetooth' in navigator;
}
// Check for USB support
hasUSB(): boolean {
return 'usb' in navigator;
}
// Get all capabilities
async getAllCapabilities(): Promise<{
camera: boolean;
microphone: boolean;
geolocation: boolean;
vibration: boolean;
bluetooth: boolean;
usb: boolean;
touch: boolean;
webGL: boolean;
}> {
return {
camera: await this.hasCamera(),
microphone: await this.hasMicrophone(),
geolocation: this.hasGeolocation(),
vibration: this.hasVibration(),
bluetooth: this.hasBluetooth(),
usb: this.hasUSB(),
touch: 'ontouchstart' in window,
webGL: this.checkWebGL()
};
}
private checkWebGL(): boolean {
try {
const canvas = document.createElement('canvas');
return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
} catch {
return false;
}
}
}
// Usage Examples
async function demonstrateDeviceInfo() {
console.log('=== Web TypeScript Device Information Examples ===\n');
const deviceManager = new DeviceInfoManager();
const batteryManager = new BatteryManager();
const memoryManager = new MemoryManager();
const connectionManager = new ConnectionManager();
const orientationManager = new OrientationManager();
const capabilityDetector = new DeviceCapabilityDetector();
// 1. Basic device info
console.log('--- 1. Device Info ---');
const deviceInfo = deviceManager.getDeviceInfo();
console.log('User Agent:', deviceInfo.userAgent);
console.log('Platform:', deviceInfo.platform);
console.log('Device Type:', deviceManager.getDeviceType());
// 2. OS and browser
console.log('\n--- 2. OS & Browser ---');
const osInfo = deviceManager.getOSInfo();
console.log('OS:', `${osInfo.name} ${osInfo.version}`);
const browserInfo = deviceManager.getBrowserInfo();
console.log('Browser:', `${browserInfo.name} ${browserInfo.version}`);
// 3. Screen info
console.log('\n--- 3. Screen Info ---');
const screenInfo = deviceManager.getScreenInfo();
console.log(`Screen: ${screenInfo.width}x${screenInfo.height}`);
console.log(`Available: ${screenInfo.availWidth}x${screenInfo.availHeight}`);
console.log(`Device Pixel Ratio: ${screenInfo.devicePixelRatio}`);
// 4. Capabilities
console.log('\n--- 4. Capabilities ---');
console.log('Touch Device:', deviceManager.isTouchDevice());
console.log('Retina Display:', deviceManager.isRetinaDisplay());
// 5. Battery
console.log('\n--- 5. Battery ---');
await batteryManager.initialize();
const batteryInfo = batteryManager.getBatteryInfo();
if (batteryInfo) {
console.log(`Battery Level: ${Math.round(batteryInfo.level * 100)}%`);
console.log(`Charging: ${batteryInfo.charging}`);
} else {
console.log('Battery API not supported');
}
// 6. Memory
console.log('\n--- 6. Memory ---');
const memoryInfo = memoryManager.getMemoryInfo();
if (memoryInfo) {
console.log(`Used Memory: ${memoryManager.formatBytes(memoryInfo.usedJSHeapSize)}`);
console.log(`Memory Limit: ${memoryManager.formatBytes(memoryInfo.jsHeapSizeLimit)}`);
console.log(`Memory Usage: ${memoryManager.getMemoryUsage()?.toFixed(2)}%`);
}
// 7. Connection
console.log('\n--- 7. Connection ---');
const connInfo = connectionManager.getConnectionInfo();
if (connInfo) {
console.log(`Connection Type: ${connInfo.effectiveType}`);
console.log(`Downlink: ${connInfo.downlink} Mbps`);
console.log(`RTT: ${connInfo.rtt} ms`);
}
// 8. Capabilities detection
console.log('\n--- 8. Device Capabilities ---');
const capabilities = await capabilityDetector.getAllCapabilities();
console.log('Camera:', capabilities.camera);
console.log('Microphone:', capabilities.microphone);
console.log('Geolocation:', capabilities.geolocation);
console.log('Vibration:', capabilities.vibration);
console.log('Bluetooth:', capabilities.bluetooth);
// 9. Complete report
console.log('\n--- 9. Complete Report ---');
const report = deviceManager.getCompleteReport();
console.log(JSON.stringify(report, null, 2));
console.log('\n=== All Device Information Examples Completed ===');
}
// Export functions
export { DeviceInfoManager, BatteryManager, MemoryManager, ConnectionManager, OrientationManager, DeviceCapabilityDetector };
export { demonstrateDeviceInfo };
💻 网络状态 typescript
🟢 simple
⭐⭐⭐
使用在线/离线事件和连接质量监控网络连接状态
⏱️ 20 min
🏷️ typescript, web, mobile features
Prerequisites:
Basic TypeScript, Network API, Navigator API
// Web TypeScript Network Status Examples
// Monitoring network connectivity and connection quality
// 1. Network Status Monitor
class NetworkStatusMonitor {
private isOnline: boolean = navigator.onLine;
private listeners: Array<(online: boolean) => void> = [];
constructor() {
this.initialize();
}
// Initialize event listeners
private initialize(): void {
window.addEventListener('online', this.handleOnline);
window.addEventListener('offline', this.handleOffline);
}
// Handle online event
private handleOnline = (): void => {
this.isOnline = true;
this.notifyListeners(true);
console.log('Network status: Online');
};
// Handle offline event
private handleOffline = (): void => {
this.isOnline = false;
this.notifyListeners(false);
console.log('Network status: Offline');
};
// Notify all listeners
private notifyListeners(online: boolean): void {
this.listeners.forEach(listener => {
try {
listener(online);
} catch (error) {
console.error('Error in network status listener:', error);
}
});
}
// Get current status
isCurrentlyOnline(): boolean {
return this.isOnline;
}
// Add status change listener
addListener(listener: (online: boolean) => void): void {
this.listeners.push(listener);
}
// Remove status change listener
removeListener(listener: (online: boolean) => void): void {
const index = this.listeners.indexOf(listener);
if (index > -1) {
this.listeners.splice(index, 1);
}
}
// Cleanup
destroy(): void {
window.removeEventListener('online', this.handleOnline);
window.removeEventListener('offline', this.handleOffline);
this.listeners = [];
}
}
// 2. Connection Quality Monitor
class ConnectionQualityMonitor {
private connection: any = null;
private listeners: Array<(info: any) => void> = [];
constructor() {
this.initialize();
}
// Initialize connection monitoring
private initialize(): void {
this.connection = (navigator as any).connection ||
(navigator as any).mozConnection ||
(navigator as any).webkitConnection;
if (this.connection) {
this.connection.addEventListener('change', this.handleChange);
}
}
// Handle connection change
private handleChange = (): void => {
const info = this.getConnectionInfo();
this.notifyListeners(info);
console.log('Connection quality changed:', info);
};
// Notify all listeners
private notifyListeners(info: any): void {
this.listeners.forEach(listener => {
try {
listener(info);
} catch (error) {
console.error('Error in connection quality listener:', error);
}
});
}
// Get connection info
getConnectionInfo(): {
effectiveType: string;
downlink: number;
rtt: number;
saveData: boolean;
} | null {
if (!this.connection) {
return null;
}
return {
effectiveType: this.connection.effectiveType || 'unknown',
downlink: this.connection.downlink || 0,
rtt: this.connection.rtt || 0,
saveData: this.connection.saveData || false
};
}
// Check if slow connection
isSlowConnection(): boolean {
const info = this.getConnectionInfo();
if (!info) return false;
const slowTypes = ['slow-2g', '2g', '3g'];
return slowTypes.includes(info.effectiveType);
}
// Check if fast connection
isFastConnection(): boolean {
const info = this.getConnectionInfo();
if (!info) return false;
return info.effectiveType === '4g';
}
// Get connection quality description
getQualityDescription(): string {
const info = this.getConnectionInfo();
if (!info) return 'Unknown';
const descriptions: Record<string, string> = {
'slow-2g': 'Very Slow (2G)',
'2g': 'Slow (2G)',
'3g': 'Moderate (3G)',
'4g': 'Fast (4G)'
};
return descriptions[info.effectiveType] || 'Unknown';
}
// Add change listener
addChangeListener(listener: (info: any) => void): void {
this.listeners.push(listener);
}
// Remove change listener
removeChangeListener(listener: (info: any) => void): void {
const index = this.listeners.indexOf(listener);
if (index > -1) {
this.listeners.splice(index, 1);
}
}
// Cleanup
destroy(): void {
if (this.connection) {
this.connection.removeEventListener('change', this.handleChange);
}
this.listeners = [];
}
}
// 3. Network Speed Tester
class NetworkSpeedTester {
private testUrl: string;
constructor(testUrl: string = 'https://www.google.com/favicon.ico') {
this.testUrl = testUrl;
}
// Test download speed
async testDownloadSpeed(): Promise<{
speedKbps: number;
latency: number;
}> {
const startTime = performance.now();
let downloadSize = 0;
try {
const response = await fetch(this.testUrl + '?t=' + Date.now());
const blob = await response.blob();
downloadSize = blob.size;
const endTime = performance.now();
const duration = (endTime - startTime) / 1000; // Convert to seconds
const speedKbps = ((downloadSize * 8) / duration) / 1000; // Convert to kbps
const latency = endTime - startTime;
return { speedKbps, latency };
} catch (error) {
console.error('Speed test failed:', error);
return { speedKbps: 0, latency: 0 };
}
}
// Test latency (ping)
async testLatency(): Promise<number> {
const start = performance.now();
try {
await fetch(this.testUrl + '?t=' + Date.now(), { method: 'HEAD' });
return performance.now() - start;
} catch {
return -1;
}
}
// Test multiple times and get average
async testAverage(iterations: number = 3): Promise<{
avgSpeedKbps: number;
avgLatency: number;
}> {
const speeds: number[] = [];
const latencies: number[] = [];
for (let i = 0; i < iterations; i++) {
const result = await this.testDownloadSpeed();
speeds.push(result.speedKbps);
latencies.push(result.latency);
// Wait a bit between tests
await new Promise(resolve => setTimeout(resolve, 500));
}
const avgSpeedKbps = speeds.reduce((a, b) => a + b, 0) / speeds.length;
const avgLatency = latencies.reduce((a, b) => a + b, 0) / latencies.length;
return { avgSpeedKbps, avgLatency };
}
}
// 4. Offline Manager
class OfflineManager {
private networkMonitor: NetworkStatusMonitor;
private offlineQueue: Array<{ url: string; options: RequestInit }> = [];
private isOfflineMode: boolean = false;
constructor() {
this.networkMonitor = new NetworkStatusMonitor();
this.initialize();
}
// Initialize offline manager
private initialize(): void {
this.networkMonitor.addListener((online) => {
this.isOfflineMode = !online;
if (online) {
this.syncOfflineRequests();
}
});
}
// Add request to offline queue
queueRequest(url: string, options: RequestInit = {}): void {
this.offlineQueue.push({ url, options });
console.log(`Request queued: ${url}`);
}
// Sync offline requests when back online
private async syncOfflineRequests(): Promise<void> {
if (this.offlineQueue.length === 0) {
return;
}
console.log(`Syncing ${this.offlineQueue.length} offline requests...`);
const queue = [...this.offlineQueue];
this.offlineQueue = [];
for (const request of queue) {
try {
await fetch(request.url, request.options);
console.log(`Synced: ${request.url}`);
} catch (error) {
console.error(`Failed to sync ${request.url}:`, error);
// Re-queue failed requests
this.queueRequest(request.url, request.options);
}
}
}
// Check if currently in offline mode
isOffline(): boolean {
return this.isOfflineMode;
}
// Get offline queue size
getQueueSize(): number {
return this.offlineQueue.length;
}
// Clear offline queue
clearQueue(): void {
this.offlineQueue = [];
}
}
// 5. Network Health Checker
class NetworkHealthChecker {
private connectionMonitor: ConnectionQualityMonitor;
private speedTester: NetworkSpeedTester;
constructor() {
this.connectionMonitor = new ConnectionQualityMonitor();
this.speedTester = new NetworkSpeedTester();
}
// Get comprehensive health report
async getHealthReport(): Promise<{
online: boolean;
connectionInfo: any;
speedTest: {
speedKbps: number;
latency: number;
} | null;
health: 'excellent' | 'good' | 'fair' | 'poor';
}> {
const online = navigator.onLine;
const connectionInfo = this.connectionMonitor.getConnectionInfo();
let speedTest = null;
let health: 'excellent' | 'good' | 'fair' | 'poor' = 'poor';
if (online) {
speedTest = await this.speedTester.testDownloadSpeed();
// Determine health based on speed and latency
if (speedTest.speedKbps > 5000 && speedTest.latency < 50) {
health = 'excellent';
} else if (speedTest.speedKbps > 1000 && speedTest.latency < 100) {
health = 'good';
} else if (speedTest.speedKbps > 500 && speedTest.latency < 200) {
health = 'fair';
} else {
health = 'poor';
}
}
return {
online,
connectionInfo,
speedTest,
health
};
}
// Simple health check (quick)
quickHealthCheck(): {
online: boolean;
connectionType: string;
estimatedQuality: 'good' | 'fair' | 'poor';
} {
const online = navigator.onLine;
const connInfo = this.connectionMonitor.getConnectionInfo();
let estimatedQuality: 'good' | 'fair' | 'poor' = 'poor';
if (connInfo) {
if (connInfo.effectiveType === '4g' && connInfo.downlink >= 10) {
estimatedQuality = 'good';
} else if (connInfo.effectiveType === '3g' || connInfo.effectiveType === '4g') {
estimatedQuality = 'fair';
}
}
return {
online,
connectionType: connInfo?.effectiveType || 'unknown',
estimatedQuality
};
}
}
// 6. Network Usage Tracker
class NetworkUsageTracker {
private requests: Map<string, number> = new Map();
// Track request
trackRequest(url: string, size: number): void {
const current = this.requests.get(url) || 0;
this.requests.set(url, current + size);
}
// Get total usage
getTotalUsage(): number {
let total = 0;
for (const size of this.requests.values()) {
total += size;
}
return total;
}
// Get usage by URL pattern
getUsageByPattern(pattern: RegExp): number {
let total = 0;
for (const [url, size] of this.requests) {
if (pattern.test(url)) {
total += size;
}
}
return total;
}
// Get top consumers
getTopConsumers(limit: number = 10): Array<{ url: string; size: number }> {
const consumers = Array.from(this.requests.entries())
.map(([url, size]) => ({ url, size }))
.sort((a, b) => b.size - a.size)
.slice(0, limit);
return consumers;
}
// Clear tracking data
clear(): void {
this.requests.clear();
}
// Get usage in readable format
getUsageReport(): {
totalBytes: number;
totalMB: number;
topConsumers: Array<{ url: string; size: number; sizeKB: number }>;
} {
const totalBytes = this.getTotalUsage();
const topConsumers = this.getTopConsumers(10);
return {
totalBytes,
totalMB: totalBytes / (1024 * 1024),
topConsumers: topConsumers.map(c => ({
...c,
sizeKB: c.size / 1024
}))
};
}
}
// Usage Examples
async function demonstrateNetworkStatus() {
console.log('=== Web TypeScript Network Status Examples ===\n');
const networkMonitor = new NetworkStatusMonitor();
const connectionMonitor = new ConnectionQualityMonitor();
const speedTester = new NetworkSpeedTester();
const offlineManager = new OfflineManager();
const healthChecker = new NetworkHealthChecker();
// 1. Network status
console.log('--- 1. Network Status ---');
console.log('Currently Online:', networkMonitor.isCurrentlyOnline());
// Add listener
networkMonitor.addListener((online) => {
console.log(`Status changed: ${online ? 'Online' : 'Offline'}`);
});
// 2. Connection quality
console.log('\n--- 2. Connection Quality ---');
const connInfo = connectionMonitor.getConnectionInfo();
if (connInfo) {
console.log('Effective Type:', connInfo.effectiveType);
console.log('Downlink:', connInfo.downlink, 'Mbps');
console.log('RTT:', connInfo.rtt, 'ms');
console.log('Quality Description:', connectionMonitor.getQualityDescription());
console.log('Slow Connection:', connectionMonitor.isSlowConnection());
console.log('Fast Connection:', connectionMonitor.isFastConnection());
}
// 3. Speed test
console.log('\n--- 3. Speed Test ---');
const speedResult = await speedTester.testDownloadSpeed();
console.log(`Speed: ${speedResult.speedKbps.toFixed(2)} kbps`);
console.log(`Latency: ${speedResult.latency.toFixed(2)} ms`);
// 4. Average speed test
console.log('\n--- 4. Average Speed Test ---');
const avgResult = await speedTester.testAverage(2);
console.log(`Average Speed: ${avgResult.avgSpeedKbps.toFixed(2)} kbps`);
console.log(`Average Latency: ${avgResult.avgLatency.toFixed(2)} ms`);
// 5. Health check
console.log('\n--- 5. Health Check ---');
const healthReport = await healthChecker.getHealthReport();
console.log('Health:', healthReport.health);
console.log('Online:', healthReport.online);
// 6. Quick health check
console.log('\n--- 6. Quick Health Check ---');
const quickHealth = healthChecker.quickHealthCheck();
console.log('Quick Health:', quickHealth);
// 7. Offline manager
console.log('\n--- 7. Offline Manager ---');
console.log('Is Offline:', offlineManager.isOffline());
console.log('Queue Size:', offlineManager.getQueueSize());
console.log('\n=== All Network Status Examples Completed ===');
}
// Export functions
export { NetworkStatusMonitor, ConnectionQualityMonitor, NetworkSpeedTester, OfflineManager, NetworkHealthChecker, NetworkUsageTracker };
export { demonstrateNetworkStatus };
💻 振动提示 typescript
🟢 simple
⭐⭐
控制设备振动以实现触觉反馈,支持模式和时序
⏱️ 15 min
🏷️ typescript, web, mobile features
Prerequisites:
Basic TypeScript, Vibration API
// Web TypeScript Vibration API Examples
// Using Vibration API for haptic feedback
// 1. Vibration Manager
class VibrationManager {
// Check if vibration is supported
isSupported(): boolean {
return 'vibrate' in navigator;
}
// Vibrate for specified duration
vibrate(duration: number): boolean {
if (!this.isSupported()) {
console.warn('Vibration API not supported');
return false;
}
return navigator.vibrate(duration);
}
// Vibrate with pattern
vibratePattern(pattern: number[]): boolean {
if (!this.isSupported()) {
console.warn('Vibration API not supported');
return false;
}
return navigator.vibrate(pattern);
}
// Stop vibration
stop(): boolean {
if (!this.isSupported()) {
return false;
}
return navigator.vibrate(0);
}
}
// 2. Haptic Feedback Patterns
class HapticFeedbackPatterns {
private vibrate: VibrationManager;
constructor() {
this.vibrate = new VibrationManager();
}
// Short tap feedback
tap(): void {
this.vibrate.vibrate(10);
}
// Medium tap feedback
mediumTap(): void {
this.vibrate.vibrate(25);
}
// Strong tap feedback
strongTap(): void {
this.vibrate.vibrate(50);
}
// Success feedback
success(): void {
this.vibrate.vibratePattern([50, 50, 50]);
}
// Error feedback
error(): void {
this.vibrate.vibratePattern([100, 50, 100, 50, 100]);
}
// Warning feedback
warning(): void {
this.vibrate.vibratePattern([50, 100, 50]);
}
// Notification feedback
notification(): void {
this.vibrate.vibratePattern([100, 50, 100]);
}
// Confirmation feedback (ask)
confirmation(): void {
this.vibrate.vibratePattern([30, 50, 30]);
}
// Heartbeat pattern
heartbeat(): void {
this.vibrate.vibratePattern([50, 50, 50, 200, 50, 50, 50, 200]);
}
// SOS pattern
sos(): void {
this.vibrate.vibratePattern([
100, 50, 100, 50, 100, 200,
200, 50, 200, 50, 200, 200,
100, 50, 100, 50, 100, 200
]);
}
// Ring pattern
ring(repeat: boolean = false): void {
const pattern = [1000, 500];
if (repeat && this.vibrate.isSupported()) {
// Note: Continuous vibration needs to be handled carefully
this.vibrate.vibratePattern(pattern);
} else {
this.vibrate.vibratePattern(pattern);
}
}
// Typing feedback
typing(): void {
this.vibrate.vibrate(15);
}
// Delete feedback
delete(): void {
this.vibrate.vibratePattern([50, 30, 50]);
}
// Scroll boundary feedback
scrollBoundary(): void {
this.vibrate.vibrate(25);
}
// Snap feedback
snap(): void {
this.vibrate.vibratePattern([20, 30, 40]);
}
// Brush feedback
brush(): void {
this.vibrate.vibratePattern([10, 20, 10, 20, 10]);
}
}
// 3. Vibration Sequencer
class VibrationSequencer {
private vibrate: VibrationManager;
private sequences: Map<string, number[]> = new Map();
constructor() {
this.vibrate = new VibrationManager();
this.initializeDefaultSequences();
}
// Initialize default sequences
private initializeDefaultSequences(): void {
this.sequences.set('dot', [30]);
this.sequences.set('dash', [100]);
this.sequences.set('dot-dot-dot', [30, 50, 30, 50, 30]);
this.sequences.set('dash-dash-dash', [100, 50, 100, 50, 100]);
this.sequences.set('dot-dash', [30, 50, 100]);
this.sequences.set('dash-dot', [100, 50, 30]);
}
// Play sequence by name
play(name: string): boolean {
const pattern = this.sequences.get(name);
if (pattern) {
return this.vibrate.vibratePattern(pattern);
}
return false;
}
// Register custom sequence
registerSequence(name: string, pattern: number[]): void {
this.sequences.set(name, pattern);
}
// Play sequence with delay
playDelayed(name: string, delay: number): void {
setTimeout(() => {
this.play(name);
}, delay);
}
// Play sequences in sequence
playSequence(names: string[], delay: number = 500): void {
names.forEach((name, index) => {
this.playDelayed(name, index * delay);
});
}
// Create rhythm pattern
createRhythm(beats: string): number[] {
const pattern: number[] = [];
for (const char of beats) {
if (char === '.') {
pattern.push(30, 50);
} else if (char === '-') {
pattern.push(100, 50);
} else if (char === ' ') {
pattern.push(0, 200);
}
}
// Remove trailing pause
if (pattern.length > 0 && pattern[pattern.length - 1] === 0) {
pattern.pop();
pattern.pop();
}
return pattern;
}
// Play rhythm
playRhythm(beats: string): boolean {
const pattern = this.createRhythm(beats);
return this.vibrate.vibratePattern(pattern);
}
}
// 4. Notification Vibrations
class NotificationVibrations {
private haptic: HapticFeedbackPatterns;
constructor() {
this.haptic = new HapticFeedbackPatterns();
}
// New message vibration
newMessage(): void {
this.haptic.notification();
}
// New email vibration
newEmail(): void {
this.haptic.vibratePattern([50, 100, 50, 100, 100, 100, 50, 200]);
}
// Calendar reminder
calendarReminder(): void {
this.haptic.vibratePattern([100, 50, 100, 50, 100, 200, 200]);
}
// Alarm vibration
alarm(): void {
// Repeating pattern - would need interval in real implementation
this.haptic.vibratePattern([500, 200, 500, 200]);
}
// Phone call
phoneCall(): void {
this.haptic.ring(true);
}
// Missed call
missedCall(): void {
this.haptic.vibratePattern([100, 100, 100, 100, 100]);
}
}
// 5. Game Feedback Vibrations
class GameFeedbackVibrations {
private haptic: HapticFeedbackPatterns;
constructor() {
this.haptic = new HapticFeedbackPatterns();
}
// Button press
buttonPress(): void {
this.haptic.tap();
}
// Button hold
buttonHold(): void {
this.haptic.vibratePattern([20, 10, 20]);
}
// Hit feedback
hit(light: boolean = false): void {
if (light) {
this.haptic.tap();
} else {
this.haptic.mediumTap();
}
}
// Critical hit
criticalHit(): void {
this.haptic.vibratePattern([50, 30, 100]);
}
// Miss feedback
miss(): void {
this.haptic.vibrate(15);
}
// Explosion
explosion(): void {
this.haptic.vibratePattern([200, 50, 100, 50, 50]);
}
// Power-up
powerUp(): void {
this.haptic.vibratePattern([30, 30, 50, 30, 70, 30, 100, 30, 150]);
}
// Level complete
levelComplete(): void {
this.haptic.success();
}
// Game over
gameOver(): void {
this.haptic.error();
}
// Achievement unlocked
achievement(): void {
this.haptic.vibratePattern([
50, 50, 50, 50, 50, 50,
100, 50, 100, 50, 100, 50,
200
]);
}
}
// 6. Accessibility Vibrations
class AccessibilityVibrations {
private haptic: HapticFeedbackPatterns;
constructor() {
this.haptic = new HapticFeedbackPatterns();
}
// Tick sound (for clock, timer)
tick(): void {
this.haptic.vibrate(10);
}
// Tock sound
tock(): void {
this.haptic.vibrate(15);
}
// Hour chime
hourChime(): void {
this.haptic.vibratePattern([100, 200, 100]);
}
// Timer complete
timerComplete(): void {
this.haptic.notification();
}
// Boundary warning
boundaryWarning(): void {
this.haptic.warning();
}
// Focus reminder
focusReminder(): void {
this.haptic.vibratePattern([30, 100, 30]);
}
// Step counter (each step)
step(): void {
this.haptic.vibrate(20);
}
// Goal reached
goalReached(): void {
this.haptic.success();
}
// Distance warning (getting closer)
proximityAlert(level: 1 | 2 | 3): void {
switch (level) {
case 1:
this.haptic.vibrate(20);
break;
case 2:
this.haptic.vibratePattern([30, 100, 30]);
break;
case 3:
this.haptic.vibratePattern([50, 50, 50, 50]);
break;
}
}
}
// 7. Vibration Composer
class VibrationComposer {
private vibrate: VibrationManager;
constructor() {
this.vibrate = new VibrationManager();
}
// Compose custom vibration from notes
compose(notes: Array<{ duration: number; pause?: number }>): void {
const pattern: number[] = [];
for (let i = 0; i < notes.length; i++) {
const note = notes[i];
pattern.push(note.duration);
if (i < notes.length - 1) {
pattern.push(note.pause || 50);
}
}
this.vibrate.vibratePattern(pattern);
}
// Compose melody
composeMelody(notes: number[], tempo: number = 200): void {
const pattern: number[] = [];
for (let i = 0; i < notes.length; i++) {
pattern.push(notes[i]);
if (i < notes.length - 1) {
pattern.push(tempo);
}
}
this.vibrate.vibratePattern(pattern);
}
// Fade in/out
fadeIn(maxDuration: number, steps: number = 5): void {
const pattern: number[] = [];
const stepDuration = maxDuration / steps;
for (let i = 1; i <= steps; i++) {
pattern.push(stepDuration * i, 50);
}
this.vibrate.vibratePattern(pattern);
}
fadeOut(maxDuration: number, steps: number = 5): void {
const pattern: number[] = [];
const stepDuration = maxDuration / steps;
for (let i = steps; i >= 1; i--) {
pattern.push(stepDuration * i, 50);
}
this.vibrate.vibratePattern(pattern);
}
// Ramping vibration
ramp(startDuration: number, endDuration: number, steps: number = 5): void {
const pattern: number[] = [];
const increment = (endDuration - startDuration) / (steps - 1);
for (let i = 0; i < steps; i++) {
const duration = startDuration + (increment * i);
pattern.push(duration, 50);
}
this.vibrate.vibratePattern(pattern);
}
}
// Usage Examples
async function demonstrateVibration() {
console.log('=== Web TypeScript Vibration API Examples ===\n');
const vibrationManager = new VibrationManager();
const hapticPatterns = new HapticFeedbackPatterns();
const sequencer = new VibrationSequencer();
const gameFeedback = new GameFeedbackVibrations();
const composer = new VibrationComposer();
// 1. Check support
console.log('--- 1. Vibration Support ---');
console.log('Vibration Supported:', vibrationManager.isSupported());
if (!vibrationManager.isSupported()) {
console.log('Vibration API is not supported on this device');
return;
}
// 2. Basic vibration
console.log('\n--- 2. Basic Vibration ---');
console.log('Short vibration...');
vibrationManager.vibrate(100);
await new Promise(resolve => setTimeout(resolve, 500));
// 3. Haptic patterns
console.log('\n--- 3. Haptic Patterns ---');
console.log('Success pattern...');
hapticPatterns.success();
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('Error pattern...');
hapticPatterns.error();
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('Warning pattern...');
hapticPatterns.warning();
await new Promise(resolve => setTimeout(resolve, 1000));
// 4. Sequencer
console.log('\n--- 4. Sequencer ---');
console.log('SOS pattern...');
hapticPatterns.sos();
await new Promise(resolve => setTimeout(resolve, 2000));
// 5. Game feedback
console.log('\n--- 5. Game Feedback ---');
console.log('Hit...');
gameFeedback.hit();
await new Promise(resolve => setTimeout(resolve, 300));
console.log('Critical hit...');
gameFeedback.criticalHit();
await new Promise(resolve => setTimeout(resolve, 500));
console.log('Power up...');
gameFeedback.powerUp();
await new Promise(resolve => setTimeout(resolve, 1000));
// 6. Composer
console.log('\n--- 6. Vibration Composer ---');
console.log('Composed melody...');
composer.composeMelody([100, 150, 200, 150, 100], 150);
await new Promise(resolve => setTimeout(resolve, 1500));
console.log('\n=== All Vibration API Examples Completed ===');
}
// Export functions
export { VibrationManager, HapticFeedbackPatterns, VibrationSequencer, NotificationVibrations, GameFeedbackVibrations, AccessibilityVibrations, VibrationComposer };
export { demonstrateVibration };