Flutter弹幕显示插件canvas_danmaku的使用
Flutter弹幕显示插件canvas_danmaku的使用
概述
canvas_danmaku
是一个使用 CustomPainter
进行直接绘制的简易高性能 Flutter 弹幕组件。它通过底层的 CustomPainter
直接绘制弹幕,减少了 Flutter 框架中组件的数量,降低了组件树的复杂度,从而提高性能。
示例
依赖添加
在你的 pubspec.yaml
文件中添加以下依赖:
dependencies:
canvas_danmaku: ^0.2.6
基本使用示例
下面是一个简单的示例,展示了如何在 Flutter 应用中集成 canvas_danmaku
插件:
import 'package:canvas_danmaku/canvas_danmaku.dart';
class _DanmakuPageState extends State<DanmakuPage> {
late DanmakuController _controller;
[@override](/user/override)
Widget build(BuildContext context) {
return Stack(
children: [
// 你的自定义组件,例如一个播放器
Container(),
// 弹幕组件
DanmakuScreen(
createdController: (e) {
_controller = e;
},
option: DanmakuOption(),
),
],
);
}
}
完整示例 Demo
下面是一个更完整的示例,包含了控制面板和各种交互功能:
import 'dart:io';
import 'dart:async';
import 'dart:convert';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:canvas_danmaku/canvas_danmaku.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'CanvasDanmaku Demo',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
HomePage({Key? key}) : super(key: key);
[@override](/user/override)
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late DanmakuController _controller;
final _danmuKey = GlobalKey();
bool _running = true;
bool _showStroke = true;
bool _massiveMode = false;
double _opacity = 1.0;
int _duration = 8;
double _fontSize = Platform.isIOS || Platform.isAndroid ? 16 : 25;
int _fontWeight = 4;
bool _hideScroll = false;
bool _hideTop = false;
bool _hideBottom = false;
bool _safeArea = true;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('CanvasDanmaku Demo'),
),
body: Column(
children: [
Wrap(
children: [
IconButton(
icon: Icon(Icons.add),
tooltip: 'Add Scroll',
onPressed: () {
_controller.addDanmaku(
DanmakuContentItem(
"这是一条超长弹幕ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789这是一条超长的弹幕,这条弹幕会超出屏幕宽度",
color: getRandomColor(),
),
);
},
),
IconButton(
icon: Icon(Icons.add),
tooltip: 'Add Top',
onPressed: () {
_controller.addDanmaku(
DanmakuContentItem("这是一条顶部弹幕", color: getRandomColor(), type: DanmakuItemType.top),
);
},
),
IconButton(
icon: Icon(Icons.add),
tooltip: 'Add Bottom',
onPressed: () {
_controller.addDanmaku(
DanmakuContentItem("这是一条底部弹幕", color: getRandomColor(), type: DanmakuItemType.bottom),
);
},
),
IconButton(
icon: Icon(Icons.play_circle_outline_outlined),
onPressed: startPlay,
tooltip: 'Start Player',
),
IconButton(
icon: Icon(_running ? Icons.pause : Icons.play_arrow),
onPressed: () {
if (_running) {
_controller.pause();
} else {
_controller.resume();
}
setState(() {
_running = !_running;
});
},
tooltip: 'Play Resume',
),
IconButton(
icon: Icon(_showStroke ? Icons.font_download : Icons.font_download_rounded),
onPressed: () {
_controller.updateOption(_controller.option.copyWith(showStroke: !_showStroke));
setState(() {
_showStroke = !_showStroke;
});
},
tooltip: 'Stroke',
),
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
_controller.clear();
},
tooltip: 'Clear',
),
],
),
Expanded(
child: Container(
color: Colors.grey,
child: DanmakuScreen(
key: _danmuKey,
createdController: (DanmakuController e) {
_controller = e;
},
option: DanmakuOption(
opacity: _opacity,
fontSize: _fontSize,
fontWeight: _fontWeight,
duration: _duration,
showStroke: _showStroke,
massiveMode: _massiveMode,
hideScroll: _hideScroll,
hideTop: _hideTop,
hideBottom: _hideBottom,
safeArea: _safeArea,
),
),
),
),
],
),
endDrawer: Drawer(
child: SafeArea(
child: ListView(
padding: EdgeInsets.all(8),
children: [
Text("Opacity : $_opacity"),
Slider(
value: _opacity,
max: 1.0,
min: 0.1,
divisions: 9,
onChanged: (e) {
setState(() {
_opacity = e;
});
_controller.updateOption(_controller.option.copyWith(opacity: e));
},
),
Text("FontSize : $_fontSize"),
Slider(
value: _fontSize,
min: 8,
max: 36,
divisions: 14,
onChanged: (e) {
setState(() {
_fontSize = e;
});
_controller.updateOption(_controller.option.copyWith(fontSize: e));
},
),
Text("Duration : $_duration"),
Slider(
value: _duration.toDouble(),
min: 4,
max: 20,
divisions: 16,
onChanged: (e) {
setState(() {
_duration = e.toInt();
});
_controller.updateOption(_controller.option.copyWith(duration: e.toInt()));
},
),
SwitchListTile(
title: const Text('MassiveMode'),
value: _massiveMode,
onChanged: (e) {
setState(() {
_massiveMode = e;
});
_controller.updateOption(_controller.option.copyWith(massiveMode: e));
},
),
SwitchListTile(
title: const Text('SafeArea'),
value: _safeArea,
onChanged: (e) {
setState(() {
_safeArea = e;
});
_controller.updateOption(_controller.option.copyWith(safeArea: e));
},
),
],
),
),
),
);
}
Timer? timer;
int sec = 0;
void startPlay() async {
String data = await DefaultAssetBundle.of(context).loadString('assets/132590001.json');
List<DanmakuContentItem> _items = [];
var jsonMap = json.decode(data);
for (var item in jsonMap['comments']) {
_items.add(DanmakuContentItem(item['m'], color: Colors.white));
}
if (timer == null) {
timer = Timer.periodic(Duration(seconds: 1), (timer) {
if (!_controller.running) return;
_controller.addDanmaku(_items[sec]);
sec++;
});
}
}
Color getRandomColor() {
final Random random = Random();
return Color.fromARGB(
255, // 固定 alpha 为 255(完全不透明)
random.nextInt(256),
random.nextInt(256),
random.nextInt(256),
);
}
[@override](/user/override)
void dispose() {
timer?.cancel();
super.dispose();
}
}
更多关于Flutter弹幕显示插件canvas_danmaku的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter弹幕显示插件canvas_danmaku的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter中使用canvas_danmaku
插件来显示弹幕的示例代码。这个插件允许你在Flutter应用中实现类似于视频网站的弹幕效果。
首先,确保你已经在pubspec.yaml
文件中添加了canvas_danmaku
依赖:
dependencies:
flutter:
sdk: flutter
canvas_danmaku: ^最新版本号 # 请替换为实际发布的最新版本号
然后运行flutter pub get
来安装依赖。
接下来是一个简单的示例代码,展示了如何使用canvas_danmaku
插件来显示弹幕:
import 'package:flutter/material.dart';
import 'package:canvas_danmaku/canvas_danmaku.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Danmaku Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: DanmakuPage(),
);
}
}
class DanmakuPage extends StatefulWidget {
@override
_DanmakuPageState createState() => _DanmakuPageState();
}
class _DanmakuPageState extends State<DanmakuPage> {
DanmakuController? _controller;
@override
void initState() {
super.initState();
_initDanmakuController();
}
void _initDanmakuController() {
_controller = DanmakuController(
viewportWidth: 375, // 设置视口宽度
viewportHeight: 667, // 设置视口高度
danmakuCount: 100, // 设置弹幕数量
danmakuConfig: DanmakuConfig(
fontSize: 24,
speed: 300, // 弹幕速度(毫秒)
lifeTime: 5000, // 弹幕生命周期(毫秒)
direction: DanmakuDirection.rtl, // 从右到左
isLimitInScreen: true, // 是否限制在屏幕内
gravity: DanmakuGravity.bottom, // 底部显示
maxLines: 3, // 最大行数
),
);
// 添加一些示例弹幕
_addDanmakus();
}
void _addDanmakus() {
final List<String> messages = [
'Hello, Flutter!',
'This is a test message.',
'Canvas Danmaku is awesome!',
// 添加更多消息...
];
messages.forEach((message) {
_controller?.addDanmaku(DanmakuData(text: message));
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Danmaku Demo'),
),
body: Stack(
children: [
Positioned.fill(
child: DanmakuWidget(
controller: _controller!,
),
),
// 你可以在这里添加其他UI元素,比如视频播放器等
],
),
);
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
}
解释
- 依赖管理:在
pubspec.yaml
文件中添加canvas_danmaku
依赖。 - 初始化:在
_DanmakuPageState
的initState
方法中初始化DanmakuController
,并设置一些配置参数,如视口宽度、高度、弹幕数量、字体大小、速度等。 - 添加弹幕:通过
_addDanmakus
方法添加一些示例弹幕。 - UI构建:使用
DanmakuWidget
来显示弹幕,并将其放置在Stack
中,以便可以在其上添加其他UI元素(例如视频播放器)。 - 资源释放:在
dispose
方法中释放DanmakuController
资源。
这个示例提供了一个基本的框架,你可以根据需要进行进一步的自定义和扩展。