134 lines
3.2 KiB
Markdown
134 lines
3.2 KiB
Markdown
# holo_shiny
|
|
|
|
`holo_shiny` is a Flutter package that renders shader-driven holographic shine.
|
|
|
|
It exposes two widget layers:
|
|
|
|
- `Shiny`: apply shine to any widget (no clipping and no rotation)
|
|
- `ShinyCard`: card-oriented convenience widget with shape clipping and tilt rotation
|
|
|
|
## Features
|
|
|
|
- GLSL shader-driven holographic effects
|
|
- Optional motion input via sensors or custom tilt stream
|
|
- Position-driven rendering: visuals respond to tilt/input position with no internal time animation
|
|
- Generic wrapper API for any widget via `Shiny(child: ...)`
|
|
- Card API with `background`, `foreground`, `shape`, and drag tilt via `ShinyCard`
|
|
- Four specialized material profiles backed by dedicated shader assets
|
|
- Global shader opacity control via `opacity`
|
|
- Cross-platform Flutter support (mobile, web, desktop)
|
|
|
|
## Installation
|
|
|
|
Add the package:
|
|
|
|
```yaml
|
|
dependencies:
|
|
holo_shiny: ^0.1.0
|
|
```
|
|
|
|
Then run:
|
|
|
|
```bash
|
|
flutter pub get
|
|
```
|
|
|
|
## Quick Start
|
|
|
|
```dart
|
|
import 'package:flutter/material.dart';
|
|
import 'package:holo_shiny/holo_shiny.dart';
|
|
|
|
class Demo extends StatelessWidget {
|
|
const Demo({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return const Shiny(
|
|
child: ColoredBox(
|
|
color: Color(0xFF202A3A),
|
|
child: SizedBox(width: 280, height: 80),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Card Usage
|
|
|
|
```dart
|
|
ShinyCard(
|
|
controller: controller,
|
|
background: Container(color: const Color(0xFF1B2D4B)),
|
|
foreground: const Center(child: Text('HOLO')),
|
|
profile: ShinyProfile.crackedIce,
|
|
opacity: 1.0,
|
|
)
|
|
```
|
|
|
|
## Motion with Controller
|
|
|
|
```dart
|
|
final ShinyController controller = ShinyController(useSensor: true);
|
|
|
|
Shiny(
|
|
controller: controller,
|
|
child: Container(color: const Color(0xFF1B2D4B)),
|
|
)
|
|
```
|
|
|
|
## Profiles
|
|
|
|
Choose a precompiled material profile:
|
|
|
|
```dart
|
|
ShinyCard(
|
|
profile: ShinyProfile.holographicSilver,
|
|
)
|
|
|
|
ShinyCard(
|
|
profile: ShinyProfile.superGoldVinyl,
|
|
)
|
|
```
|
|
|
|
You can also provide a custom stream:
|
|
|
|
```dart
|
|
final StreamController<Offset> input = StreamController<Offset>.broadcast();
|
|
final ShinyController controller = ShinyController(tiltStream: input.stream);
|
|
```
|
|
|
|
## API Summary
|
|
|
|
- `Shiny`: generic effect wrapper
|
|
- `ShinyCard`: shape + rotation + composition convenience widget
|
|
- `ShinyProfile`: specialized material presets mapped to dedicated shader assets
|
|
- `ShinyController`: optional source selection for tilt
|
|
- `SensorTiltController`: low-level sensor fusion stream utility
|
|
|
|
Important defaults:
|
|
|
|
- `profile` defaults to `ShinyProfile.crackedIce`
|
|
- `opacity` defaults to `1.0`
|
|
|
|
## Platform Notes
|
|
|
|
- Shader uses Flutter runtime effects and avoids derivative functions (`dFdx`, `dFdy`, `fwidth`) for web compatibility.
|
|
- Shader output is deterministic for a given input state and is driven by tilt/position values instead of a ticking time uniform.
|
|
- If a sensor is unavailable, motion input simply emits no events.
|
|
|
|
## Example
|
|
|
|
See the package example app in `example/` for:
|
|
|
|
- Basic usage
|
|
- Any-widget shiny wrapper usage
|
|
- Sensor-driven motion
|
|
- External stream override
|
|
- Custom card shape/background/foreground composition
|
|
- Profile switching in the demo UI
|
|
|
|
## Publishing Notes
|
|
|
|
Replace placeholder package metadata URLs in `pubspec.yaml` before publishing.
|