feat(accessibility): add reduceMotion scaling and minimize animations; apply RepaintBoundary to heavy widgets

This commit is contained in:
JiWoong Sul
2025-09-08 14:30:28 +09:00
parent 10491af55b
commit eb6691ce6a
11 changed files with 478 additions and 331 deletions

View File

@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'dart:math' as math;
import '../utils/reduce_motion.dart';
/// 웨이브 애니메이션 배경 효과를 제공하는 위젯
///
@@ -16,6 +17,8 @@ class AnimatedWaveBackground extends StatelessWidget {
@override
Widget build(BuildContext context) {
final reduce = ReduceMotion.isEnabled(context);
final amp = reduce ? 0.3 : 1.0; // 효과 강도 스케일
return Stack(
children: [
// 웨이브 애니메이션 배경 요소 - 사인/코사인 함수 대신 더 부드러운 곡선 사용
@@ -25,15 +28,15 @@ class AnimatedWaveBackground extends StatelessWidget {
// 0~1 사이의 값을 0~2π 사이의 값으로 변환하여 부드러운 주기 생성
final angle = controller.value * 2 * math.pi;
// 사인 함수를 사용하여 부드러운 움직임 생성
final xOffset = 20 * math.sin(angle);
final yOffset = 10 * math.cos(angle);
final xOffset = 20 * amp * math.sin(angle);
final yOffset = 10 * amp * math.cos(angle);
return Positioned(
right: -40 + xOffset,
top: -60 + yOffset,
child: Transform.rotate(
// 회전도 선형적으로 변화하도록 수정
angle: 0.2 * math.sin(angle * 0.5),
angle: 0.2 * amp * math.sin(angle * 0.5),
child: Container(
width: 200,
height: 200,
@@ -51,15 +54,15 @@ class AnimatedWaveBackground extends StatelessWidget {
builder: (context, child) {
// 첫 번째 원과 약간 다른 위상을 가지도록 설정
final angle = (controller.value * 2 * math.pi) + (math.pi / 3);
final xOffset = 20 * math.cos(angle);
final yOffset = 10 * math.sin(angle);
final xOffset = 20 * amp * math.cos(angle);
final yOffset = 10 * amp * math.sin(angle);
return Positioned(
left: -80 + xOffset,
bottom: -70 + yOffset,
child: Transform.rotate(
// 반대 방향으로 회전하도록 설정
angle: -0.3 * math.sin(angle * 0.5),
angle: -0.3 * amp * math.sin(angle * 0.5),
child: Container(
width: 220,
height: 220,
@@ -78,14 +81,14 @@ class AnimatedWaveBackground extends StatelessWidget {
builder: (context, child) {
// 세 번째 원은 다른 위상으로 움직이도록 설정
final angle = (controller.value * 2 * math.pi) + (math.pi * 2 / 3);
final xOffset = 15 * math.sin(angle * 0.7);
final yOffset = 8 * math.cos(angle * 0.7);
final xOffset = 15 * amp * math.sin(angle * 0.7);
final yOffset = 8 * amp * math.cos(angle * 0.7);
return Positioned(
right: 40 + xOffset,
bottom: -40 + yOffset,
child: Transform.rotate(
angle: 0.4 * math.cos(angle * 0.5),
angle: 0.4 * amp * math.cos(angle * 0.5),
child: Container(
width: 120,
height: 120,
@@ -110,8 +113,7 @@ class AnimatedWaveBackground extends StatelessWidget {
height: 30,
decoration: BoxDecoration(
color: Colors.white.withValues(
alpha: 0.1 + 0.1 * pulseController.value,
),
alpha: reduce ? 0.08 : 0.1 + 0.1 * pulseController.value),
borderRadius: BorderRadius.circular(15),
),
),