page-dynamic.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // page-dynamic.component.ts
  2. import { Component, AfterViewInit } from '@angular/core';
  3. import { FormsModule } from '@angular/forms';
  4. @Component({
  5. selector: 'app-page-dynamic',
  6. standalone: true,
  7. templateUrl: './page-dynamic.html',
  8. styleUrls: ['./page-dynamic.scss'],
  9. imports: [FormsModule]
  10. })
  11. export class PageDynamic implements AfterViewInit {
  12. isOcrSuccess: boolean | null = null;
  13. activeLanterns = false;
  14. isProcessing = false;
  15. formData = {
  16. awardName: '',
  17. applicant: '',
  18. description: '',
  19. document: null as File | null
  20. };
  21. ngAfterViewInit() {
  22. this.initCraneInteraction();
  23. this.initPavilionInteraction();
  24. }
  25. onOcrClick() {
  26. this.isProcessing = true;
  27. this.activeLanterns = false;
  28. this.isOcrSuccess = null;
  29. // 模拟OCR处理过程
  30. setTimeout(() => {
  31. this.isProcessing = false;
  32. const isSuccess = Math.random() > 0.3;
  33. this.isOcrSuccess = isSuccess;
  34. this.activeLanterns = isSuccess;
  35. if (!isSuccess) {
  36. this.createCeramicShards();
  37. }
  38. }, 1500);
  39. }
  40. createCeramicShards() {
  41. const gate = document.querySelector('.ocr-gate');
  42. if (!gate) return;
  43. for (let i = 0; i < 8; i++) {
  44. const shard = document.createElement('div');
  45. shard.classList.add('ceramic-shard');
  46. shard.style.setProperty('--angle', `${Math.random() * 360}deg`);
  47. shard.style.setProperty('--distance', `${50 + Math.random() * 100}px`);
  48. gate.appendChild(shard);
  49. setTimeout(() => {
  50. shard.style.opacity = '1';
  51. shard.style.transform = `translate(
  52. calc(var(--distance) * cos(var(--angle))),
  53. calc(var(--distance) * sin(var(--angle)))
  54. ) rotate(var(--angle))`;
  55. }, 10);
  56. setTimeout(() => {
  57. shard.remove();
  58. }, 1000);
  59. }
  60. }
  61. initCraneInteraction() {
  62. const cranes = document.querySelectorAll('.crane');
  63. cranes.forEach(crane => {
  64. crane.addEventListener('mouseenter', () => {
  65. if (!crane.classList.contains('main-crane')) {
  66. crane.classList.add('hovered');
  67. }
  68. });
  69. crane.addEventListener('mouseleave', () => {
  70. crane.classList.remove('hovered');
  71. });
  72. });
  73. }
  74. initPavilionInteraction() {
  75. const pavilion = document.querySelector('.pavilion-model');
  76. if (!pavilion) return;
  77. // 使用类型断言明确指定事件类型
  78. pavilion.addEventListener('mousemove', (e: Event) => {
  79. const mouseEvent = e as MouseEvent; // 类型断言
  80. const rect = pavilion.getBoundingClientRect();
  81. const centerX = rect.left + rect.width / 2;
  82. const centerY = rect.top + rect.height / 2;
  83. const rotateY = (mouseEvent.clientX - centerX) / 20;
  84. const rotateX = (centerY - mouseEvent.clientY) / 20;
  85. (pavilion as HTMLElement).style.transform =
  86. `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
  87. });
  88. pavilion.addEventListener('mouseleave', () => {
  89. (pavilion as HTMLElement).style.transform =
  90. 'perspective(1000px) rotateX(0) rotateY(0)';
  91. });
  92. }
  93. onFileSelected(event: Event) {
  94. const input = event.target as HTMLInputElement;
  95. if (input.files && input.files.length > 0) {
  96. this.formData.document = input.files[0];
  97. }
  98. }
  99. submitForm() {
  100. console.log('Form submitted:', this.formData);
  101. // 实际应用中这里会发送数据到服务器
  102. alert('奖项申报已提交!');
  103. this.formData = {
  104. awardName: '',
  105. applicant: '',
  106. description: '',
  107. document: null
  108. };
  109. }
  110. }