|
|
楼主 |
发表于 2026-8-4 20:29:54
|
显示全部楼层
perl+Tk模拟flash,按照时序显示隐藏图片
本帖最后由 zzz19760225 于 2026-8-21 09:03 编辑
5.pl
perl 5.pl
- #!/usr/bin/perl
- use utf8;
- use Tk;
- use strict;
- use warnings;
- # ============================================
- # 1. 定义图层数据结构(使用颜色和形状)
- # ============================================
- my @timeline = (
- # { time => 开始时间, layer => 图层, color => 颜色, shape => 形状, duration => 时长 }
- { time => 0, layer => 1, color => '#FF0000', shape => 'rectangle', duration => 3 },
- { time => 2, layer => 2, color => '#00FF00', shape => 'circle', duration => 3 },
- { time => 3, layer => 1, color => '#0000FF', shape => 'rectangle', duration => 4 },
- { time => 5, layer => 3, color => '#FFFF00', shape => 'oval', duration => 5 },
- { time => 6, layer => 2, color => '#FF00FF', shape => 'circle', duration => 2 },
- { time => 7, layer => 1, color => '#00FFFF', shape => 'rectangle', duration => 3 },
- { time => 10, layer => 3, color => '#FF8800', shape => 'oval', duration => 2 },
- );
- # ============================================
- # 2. 创建主窗口和画布
- # ============================================
- my $mw = MainWindow->new;
- $mw->title("Perl/Tk 时间轴动画 - 图形版本");
- $mw->geometry("800x600");
- my $canvas = $mw->Canvas(
- -width => 800,
- -height => 500,
- -bg => '#2c3e50',
- -relief => 'sunken',
- -bd => 3,
- )->pack(-expand => 1, -fill => 'both');
- # 信息显示
- my $info_frame = $mw->Frame->pack(-side => 'bottom', -fill => 'x');
- $info_frame->Label(
- -text => "时间轴动画 (图形版本) | ",
- -font => ['Arial', 10, 'bold']
- )->pack(-side => 'left', -padx => 10);
- my $time_label = $info_frame->Label(
- -text => "时间: 0.0s",
- -font => ['Arial', 10],
- -fg => '#3498db'
- )->pack(-side => 'left');
- my $layer_label = $info_frame->Label(
- -text => " | 活动图层: 无",
- -font => ['Arial', 10],
- -fg => '#e74c3c'
- )->pack(-side => 'left');
- # ============================================
- # 3. 图层存储
- # ============================================
- my %layers;
- my %layer_visible;
- foreach my $item (@timeline) {
- my $layer = $item->{layer};
- $layers{$layer} ||= { item_id => undef };
- $layer_visible{$layer} = 1;
- }
- # ============================================
- # 4. 绘图函数
- # ============================================
- sub draw_shape {
- my ($layer, $color, $shape) = @_;
-
- # 删除该图层旧的对象
- if (defined $layers{$layer}->{item_id}) {
- $canvas->delete($layers{$layer}->{item_id});
- $layers{$layer}->{item_id} = undef;
- }
-
- # 计算位置(不同图层偏移不同位置)
- my $x = 100 + ($layer - 1) * 200;
- my $y = 100 + ($layer - 1) * 50;
- my $size = 80;
-
- my $item_id;
-
- # 根据形状绘制
- if ($shape eq 'rectangle') {
- $item_id = $canvas->createRectangle(
- $x, $y, $x + $size, $y + $size,
- -fill => $color,
- -outline => 'white',
- -width => 2
- );
- } elsif ($shape eq 'circle') {
- $item_id = $canvas->createOval(
- $x, $y, $x + $size, $y + $size,
- -fill => $color,
- -outline => 'white',
- -width => 2
- );
- } elsif ($shape eq 'oval') {
- $item_id = $canvas->createOval(
- $x, $y, $x + $size * 1.5, $y + $size * 0.8,
- -fill => $color,
- -outline => 'white',
- -width => 2
- );
- } else {
- # 默认画矩形
- $item_id = $canvas->createRectangle(
- $x, $y, $x + $size, $y + $size,
- -fill => $color,
- -outline => 'white',
- -width => 2
- );
- }
-
- # 添加文字标签
- $canvas->createText(
- $x + $size/2, $y + $size/2,
- -text => "图层 $layer",
- -fill => 'white',
- -font => ['Arial', 12, 'bold']
- );
-
- $layers{$layer}->{item_id} = $item_id;
- $canvas->itemconfigure($item_id, -state => $layer_visible{$layer} ? 'normal' : 'hidden');
- }
- # ============================================
- # 5. 动画引擎
- # ============================================
- my $animation_running = 0;
- my $current_time = 0;
- my $start_time = 0;
- my $after_id = undef;
- my $loop_count = 0;
- sub update_animation {
- my ($time) = @_;
-
- $current_time = $time;
- $time_label->configure(-text => sprintf("时间: %.1fs", $time));
-
- # 找到当前时间活动的图层
- my @active_items;
- foreach my $item (@timeline) {
- my $start = $item->{time};
- my $end = $start + $item->{duration};
-
- if ($time >= $start && $time < $end) {
- push @active_items, $item;
- }
- }
-
- # 先隐藏所有图层
- foreach my $layer (keys %layers) {
- if (defined $layers{$layer}->{item_id}) {
- $canvas->itemconfigure($layers{$layer}->{item_id}, -state => 'hidden');
- }
- }
-
- # 显示当前活动的图层
- foreach my $item (@active_items) {
- my $layer = $item->{layer};
- draw_shape($layer, $item->{color}, $item->{shape});
- $canvas->itemconfigure($layers{$layer}->{item_id}, -state => 'normal');
- $layer_visible{$layer} = 1;
- }
-
- # 更新信息
- my $layer_info = @active_items > 0 ?
- "图层: " . join(', ', map { $_->{layer} } @active_items) :
- "无活动图层";
- $layer_label->configure(-text => " | $layer_info");
- }
- sub animate_loop {
- return unless $animation_running;
-
- my $elapsed = time() - $start_time;
- my $total_duration = get_total_duration();
-
- if ($elapsed > $total_duration) {
- $loop_count++;
- $start_time = time();
- $elapsed = 0;
- $mw->title("Perl/Tk 时间轴动画 - 循环播放 $loop_count");
- }
-
- update_animation($elapsed);
- $after_id = $mw->after(100 => \&animate_loop);
- }
- sub get_total_duration {
- my $max_time = 0;
- foreach my $item (@timeline) {
- my $end = $item->{time} + $item->{duration};
- $max_time = $end if $end > $max_time;
- }
- return $max_time;
- }
- # ============================================
- # 6. 控制按钮
- # ============================================
- my $control_frame = $mw->Frame(-bg => '#ecf0f1')->pack(-side => 'bottom', -fill => 'x');
- my $play_btn;
- $play_btn = $control_frame->Button(
- -text => "▶ 播放",
- -font => ['Arial', 10, 'bold'],
- -bg => '#2ecc71',
- -fg => 'white',
- -command => sub {
- if ($animation_running) {
- $animation_running = 0;
- $play_btn->configure(-text => "▶ 播放", -bg => '#2ecc71');
- $mw->afterCancel($after_id) if $after_id;
- } else {
- $animation_running = 1;
- $start_time = time();
- $play_btn->configure(-text => "⏸ 暂停", -bg => '#e74c3c');
- animate_loop();
- }
- }
- );
- $play_btn->pack(-side => 'left', -padx => 10, -pady => 5);
- $control_frame->Button(
- -text => "⟲ 重置",
- -font => ['Arial', 10],
- -command => sub {
- $animation_running = 0;
- $play_btn->configure(-text => "▶ 播放", -bg => '#2ecc71');
- $mw->afterCancel($after_id) if $after_id;
- $current_time = 0;
- $loop_count = 0;
- update_animation(0);
- $mw->title("Perl/Tk 时间轴动画");
- }
- )->pack(-side => 'left', -padx => 10, -pady => 5);
- $control_frame->Button(
- -text => "显示所有图层",
- -font => ['Arial', 9],
- -command => sub {
- foreach my $layer (keys %layers) {
- $layer_visible{$layer} = 1;
- if (defined $layers{$layer}->{item_id}) {
- $canvas->itemconfigure($layers{$layer}->{item_id}, -state => 'normal');
- }
- }
- }
- )->pack(-side => 'right', -padx => 10, -pady => 5);
- $control_frame->Button(
- -text => "隐藏所有图层",
- -font => ['Arial', 9],
- -command => sub {
- foreach my $layer (keys %layers) {
- $layer_visible{$layer} = 0;
- if (defined $layers{$layer}->{item_id}) {
- $canvas->itemconfigure($layers{$layer}->{item_id}, -state => 'hidden');
- }
- }
- }
- )->pack(-side => 'right', -padx => 10, -pady => 5);
- # ============================================
- # 7. 启动
- # ============================================
- update_animation(0);
- my $help_label = $mw->Label(
- -text => "提示: 使用不同颜色和形状模拟图层动画,无需外部图片",
- -font => ['Arial', 9],
- -fg => '#7f8c8d'
- )->pack(-side => 'bottom', -pady => 2);
- MainLoop;
复制代码
舞台人物的先后出场,延续图层图片。pl改成py好像也能运行。 |
|