| 
					
				 | 
			
			
				@@ -0,0 +1,274 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//import { Component, OnInit } from '@angular/core'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Component, ElementRef, ViewChild, OnInit } from '@angular/core'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Capacitor } from '@capacitor/core'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Filesystem, Directory } from '@capacitor/filesystem'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//import { AudioService } from '../../services/audio.service'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Share } from '@capacitor/share'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { AlertController } from '@ionic/angular'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { AudioService } from 'src/app/services/audio.service'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Component({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  selector: 'app-scream-room', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  templateUrl: './scream-room.page.html', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  styleUrls: ['./scream-room.page.scss'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  standalone:false, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+export class ScreamRoomPage implements OnInit { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  @ViewChild('visualizerCanvas') visualizerCanvas!: ElementRef<HTMLCanvasElement>; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  isRecording = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  volumeLevel = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  volumePercentage = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  waveformImage: string | null = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private canvasCtx!: CanvasRenderingContext2D; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private animationId!: number; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private audioChunks: Blob[] = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  constructor( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private audioService: AudioService, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private alertController: AlertController 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ) {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ngOnInit() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.audioService.initAudioContext(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ngAfterViewInit() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.setupVisualizer(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private setupVisualizer() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const canvas = this.visualizerCanvas.nativeElement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.canvasCtx = canvas.getContext('2d')!; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    canvas.width = canvas.offsetWidth; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    canvas.height = 200; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.drawInitialVisualizer(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private drawInitialVisualizer() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const { width, height } = this.visualizerCanvas.nativeElement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.canvasCtx.clearRect(0, 0, width, height); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 绘制初始平静的波浪线 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.canvasCtx.lineWidth = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.canvasCtx.strokeStyle = '#3880ff'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.canvasCtx.beginPath(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let x = 0; x < width; x++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const y = height / 2 + Math.sin(x * 0.05) * 20; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (x === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.canvasCtx.moveTo(x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.canvasCtx.lineTo(x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.canvasCtx.stroke(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  async startRecording() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.isRecording = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.audioChunks = []; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      await this.audioService.startRecording((volume) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.volumeLevel = volume / 100; // 转换为0-1范围 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.volumePercentage = Math.round(volume); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.updateVisualizer(volume); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.startVisualizerAnimation(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      console.error('录音失败:', error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.presentAlert('录音失败', '无法访问麦克风,请检查权限设置'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.isRecording = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  async stopRecording() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.isRecording = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cancelAnimationFrame(this.animationId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const audioBlob = await this.audioService.stopRecording(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.audioChunks = this.audioService.getRecordedChunks(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 生成声波图 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.generateWaveformArt(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      console.error('停止录音失败:', error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private startVisualizerAnimation() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const canvas = this.visualizerCanvas.nativeElement; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const { width, height } = canvas; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const draw = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (!this.isRecording) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.canvasCtx.clearRect(0, 0, width, height); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 根据音量动态绘制 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.canvasCtx.lineWidth = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.canvasCtx.strokeStyle = '#ff3860'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.canvasCtx.beginPath(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const amplitude = this.volumePercentage / 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for (let x = 0; x < width; x++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const y = height / 2 +  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 Math.sin(x * 0.05 + Date.now() * 0.005) * (20 + amplitude) + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                 Math.sin(x * 0.1) * (10 + amplitude/2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (x === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          this.canvasCtx.moveTo(x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          this.canvasCtx.lineTo(x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.canvasCtx.stroke(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.animationId = requestAnimationFrame(draw); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.animationId = requestAnimationFrame(draw); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private updateVisualizer(volume: number) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 实时更新可视化效果 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 动画循环中已经处理,这里可以留空或添加额外效果 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private generateWaveformArt() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const canvas = document.createElement('canvas'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    canvas.width = 800; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    canvas.height = 400; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const ctx = canvas.getContext('2d')!; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 创建渐变背景 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gradient.addColorStop(0, '#ff758c'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gradient.addColorStop(1, '#ff7eb3'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ctx.fillStyle = gradient; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ctx.fillRect(0, 0, canvas.width, canvas.height); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 分析音频数据生成波形 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    this.audioService.analyzeAudio(this.audioChunks, (dataArray) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.lineWidth = 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.strokeStyle = '#ffffff'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.globalCompositeOperation = 'overlay'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.beginPath(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const sliceWidth = canvas.width / dataArray.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      let x = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      for (let i = 0; i < dataArray.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const v = dataArray[i] / 255.0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const y = v * canvas.height; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (i === 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          ctx.moveTo(x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          ctx.lineTo(x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        x += sliceWidth; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.stroke(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 添加一些艺术效果 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.addArtisticEffects(ctx, canvas.width, canvas.height, dataArray); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 转换为图像URL 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.waveformImage = canvas.toDataURL('image/png'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  private addArtisticEffects(ctx: CanvasRenderingContext2D, width: number, height: number, dataArray: Uint8Array) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 添加粒子效果 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ctx.fillStyle = 'rgba(255, 255, 255, 0.7)'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let i = 0; i < dataArray.length; i += 10) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const x = (i / dataArray.length) * width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const y = (dataArray[i] / 255.0) * height; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const size = (dataArray[i] / 255.0) * 10 + 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.beginPath(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.arc(x, y, size, 0, Math.PI * 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.fill(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 添加一些随机线条增加艺术感 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ctx.strokeStyle = 'rgba(255, 255, 255, 0.3)'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ctx.lineWidth = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    for (let i = 0; i < 20; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.beginPath(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.moveTo(Math.random() * width, Math.random() * height); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.lineTo(Math.random() * width, Math.random() * height); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ctx.stroke(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  async saveArtwork() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!this.waveformImage) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 保存到相册 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const base64Data = this.waveformImage.split(',')[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      const fileName = `scream-art-${new Date().getTime()}.png`; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      await Filesystem.writeFile({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        path: fileName, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        data: base64Data, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        directory: Directory.Documents, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        recursive: true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      // 在Android上需要特殊处理才能显示在相册中 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (Capacitor.getPlatform() === 'android') { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        await Filesystem.getUri({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          directory: Directory.Documents, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          path: fileName 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.presentAlert('保存成功', '你的声波艺术画已保存到相册'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        console.error('保存失败:', error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.presentAlert('保存失败', '无法保存图片,请重试'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  async shareArtwork() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!this.waveformImage) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      await Share.share({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        title: '我的声波艺术画', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        text: '看看我用情绪发泄室创作的声波艺术!', 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        url: this.waveformImage, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        dialogTitle: '分享我的艺术创作' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } catch (error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      console.error('分享失败:', error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  async presentAlert(header: string, message: string) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const alert = await this.alertController.create({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      header, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      message, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      buttons: ['OK'] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    await alert.present(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  ngOnDestroy() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (this.isRecording) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      this.audioService.stopRecording(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cancelAnimationFrame(this.animationId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |