2

Adobe Premiere のようなタイム スケールを次のように作成しようとしています。 ここに画像の説明を入力 しかし、0.01 秒単位まで下げる必要があります。

私のタイムライン コントロールは次のようになります。 ここに画像の説明を入力

更新: @Sten Petrov の提案を使用し、VisualBrush.

しかし今、私はLabel秒の実装方法にこだわっています。

私の新しいコード(コントロールが変更される可能性があります):

<Window x:Class="WpfApplication3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="680.839">
<Grid Background="Black">

    <ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Visible" >
        <ScrollViewer.ContentTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="30"/>
                        <RowDefinition Height="1*"/>
                    </Grid.RowDefinitions>

                    <Grid SnapsToDevicePixels="False" UseLayoutRounding="True">
                        <Grid.Background>
                            <VisualBrush TileMode="Tile" Viewport="0,0,5,30" ViewportUnits="Absolute" Viewbox="0,0,5,30" ViewboxUnits="Absolute">
                                <VisualBrush.Visual>
                                    <Line Stroke="Coral" StrokeThickness="2" X1="0" X2="0" Y1="25" Y2="30" UseLayoutRounding="True" />
                                </VisualBrush.Visual>
                            </VisualBrush>
                        </Grid.Background>
                    </Grid>

                    <Grid Margin="50,0,0,0" SnapsToDevicePixels="False" UseLayoutRounding="True">
                        <Grid.Background>
                            <VisualBrush TileMode="Tile" Viewport="0,0,50,30" ViewportUnits="Absolute" Viewbox="0,0,50,30" ViewboxUnits="Absolute">
                                <VisualBrush.Visual>
                                    <Line Stroke="Red" StrokeThickness="2" X1="0" X2="0" Y1="20" Y2="30" UseLayoutRounding="True" />
                                </VisualBrush.Visual>
                            </VisualBrush>
                        </Grid.Background>
                    </Grid>

                    <Grid SnapsToDevicePixels="False" Height="30" UseLayoutRounding="True" >
                        <Grid.Background>
                            <VisualBrush TileMode="Tile" Viewport="0,0,500,30" ViewportUnits="Absolute" Viewbox="0,0,500,30" ViewboxUnits="Absolute">
                                <VisualBrush.Visual>
                                    <Grid HorizontalAlignment="Left" Width="500" UseLayoutRounding="True">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="21*"/>
                                            <ColumnDefinition Width="25*"/>
                                            <ColumnDefinition Width="25*"/>
                                            <ColumnDefinition Width="25*"/>
                                            <ColumnDefinition Width="25*"/>
                                            <ColumnDefinition Width="25*"/>
                                            <ColumnDefinition Width="25*"/>
                                            <ColumnDefinition Width="25*"/>
                                            <ColumnDefinition Width="25*"/>
                                            <ColumnDefinition Width="20*"/>
                                            <ColumnDefinition Width="9*"/>
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="15"/>
                                            <RowDefinition Height="1*"/>
                                        </Grid.RowDefinitions>
                                        <Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="1" Height="9" Content=".100" Foreground="White"/>
                                        <Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="2" Height="9" Content=".200" Foreground="White"/>
                                        <Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="3" Height="9" Content=".300" Foreground="White"/>
                                        <Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="4" Height="9" Content=".400" Foreground="White"/>
                                        <Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="5" Height="9" Content=".500" Foreground="White"/>
                                        <Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="6" Height="9" Content=".600" Foreground="White"/>
                                        <Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="7" Height="9" Content=".700" Foreground="White"/>
                                        <Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="8" Height="9" Content=".800" Foreground="White"/>
                                        <Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="9" Height="9" Content=".900" Foreground="White"/>
                                    </Grid>
                                </VisualBrush.Visual>
                            </VisualBrush>
                        </Grid.Background>
                    </Grid>

                    <Grid SnapsToDevicePixels="False" Height="30" UseLayoutRounding="True" Margin="500,0,0,0" >
                        <Grid.Background>
                            <VisualBrush TileMode="Tile" Viewport="0,0,500,30" ViewportUnits="Absolute" Viewbox="0,0,500,30" ViewboxUnits="Absolute">
                                <VisualBrush.Visual>
                                    <Line Stroke="Blue" StrokeThickness="2" X1="0" X2="0" Y1="10" Y2="30" UseLayoutRounding="True" />
                                </VisualBrush.Visual>
                            </VisualBrush>
                        </Grid.Background>
                    </Grid>

                    <Grid SnapsToDevicePixels="False" Height="30" UseLayoutRounding="True" Margin="491,0,0,0" >
                        <Grid.RowDefinitions>
                            <RowDefinition Height="7"/>
                            <RowDefinition Height="23"/>
                        </Grid.RowDefinitions>
                        <!--Need something here-->
                        <Label Grid.Row="0" FontFamily="Tahoma" FontSize="8" Padding="0" VerticalAlignment="Bottom" Grid.Column="0" Height="9" Content="00:00" Foreground="White"/>
                    </Grid>

                </Grid>
            </DataTemplate>
        </ScrollViewer.ContentTemplate>
    </ScrollViewer>

</Grid>

/アップデート

1 行あたり 0.01 秒なので、10 分間のタイムラインで 60000 行 + 6000 ラベルの描画を検討しています。

以前にこれについて質問しました: 10000 以上の UI 要素、バインドまたは描画?

もともとは、直接線を引いていましたCanvas。それから私はVisualHostより軽いと思われるので、私はaを使用するようになりました.

うーん、軽さが足りない。

ビデオをMediaElement再生する があり、タイムラインはビデオの位置と同期してスクロールします。AScrollViewerはタイムラインをラップし、.ScrollToHorizontalOffset約 10 ミリ秒ごとに実行します。

タイムラインが 3 分程度を超えると、ビデオがシャッターを切ります。これは、VisualHostまだすべてのフレームワーク要素が含まれており、スクロールによってそれらが再検証されるためだと思います。

だから今、私は表示するものを生成しようとしてImageいますが、それはもっと軽いはずです。

この仮定は間違っていますか?

現在、タイムラインを .xml にする際の問題に直面していますImage

タイムライン全体をイメージにレンダリングできなかったため、「チャンク」しています。Exceptions私は画像サイズが大きすぎることについて打っていました。

私のコードについて: これは私のメインのエントリ ポイントです。

public void RenderHeaderPicture()
{
    const int ChunkSize = 5000;
    var bitmapFrames = new List<BitmapFrame>();

    // generates X number of DrawingVisual's based on ChunkSize
    List<DrawingVisual> visuals = generateHeaderVisualChunks(
        AppViewModel.TimelineViewModel.HeaderWidth, ChunkSize, TimelineViewModel.ViewLevel.Level1);

    for (var i = 0; i < visuals.Count; i++)
    {
        var renderTargetBitmap = new RenderTargetBitmap(ChunkSize, 30, 96, 96, PixelFormats.Pbgra32);
        renderTargetBitmap.Render(visuals[i]);

        //test to make sure image good
        saveHeaderSegmentAsPng(string.Format("headerSeg{0}.png", i), renderTargetBitmap);

        bitmapFrames.Add(BitmapFrame.Create(renderTargetBitmap));
    }

    // put the frames back together now
    var drawingVisual = new DrawingVisual();
    using (var drawingContext = drawingVisual.RenderOpen())
    {
        for (int i = 0; i < bitmapFrames.Count; i++)
        {
            drawingContext.DrawImage(bitmapFrames[i], new Rect(i * ChunkSize, 0, bitmapFrames[i].PixelWidth, 30));
        }
        drawingContext.Close();
    }

    var newBmp = new RenderTargetBitmap(AppViewModel.TimelineViewModel.HeaderWidth, 30, 96, 96, PixelFormats.Pbgra32);
    newBmp.Render(drawingVisual);

    AppViewModel.TimelineViewModel.HeaderImageSource = newBmp;
}

を作成するコードは次のとおりです。DrawingVisual's

private List<DrawingVisual> generateHeaderVisualChunks(int width, int chunkSize, TimelineViewModel.ViewLevel level) 
{ 
    var ret = new List<DrawingVisual>();

    var currentTime = new TimeSpan(0, 0, 0, 0, 0);
    var timeStep = new TimeSpan(0, 0, 0, 0, (int)level);
    var currentLine = 0;

    const double DistanceBetweenLines = 5;
    const int TenthOfSecondLine = 10;
    const int SecondLine = 100;

    int iterations = (width / chunkSize);
    int remainder = width % chunkSize; //not doing anything with yet

    var grayBrush = new SolidColorBrush(Color.FromRgb(192, 192, 192));
    var grayPen = new Pen(grayBrush, 2);
    var whitePen = new Pen(Brushes.Purple, 2);

    grayBrush.Freeze();
    grayPen.Freeze();
    whitePen.Freeze();

    for (int i = 0; i < iterations; i++)
    {
        var visual = new DrawingVisual();
        using (var dc = visual.RenderOpen())
        {
            double currentX = 0;

            if (i > 0)
            {
                currentLine--;
                currentTime -= timeStep;
            }

            while (currentX <= chunkSize)
            {
                if (((currentLine % SecondLine) == 0) && currentLine != 0)
                {
                    dc.DrawLine(whitePen, new Point(currentX, 30), new Point(currentX, 15));
                    FormattedText text = null;
                    double tempX = currentX;
                    switch (level)
                    {
                        case TimelineViewModel.ViewLevel.Level1:
                            text = new FormattedText(
                                    currentTime.ToString(@"hh\:mm\:ss\.fff"),
                                    CultureInfo.CurrentCulture,
                                    FlowDirection.LeftToRight,
                                    new Typeface("Tahoma"),
                                    8,
                                    grayBrush);
                            break;
                    }

                    dc.DrawText(text, new Point((tempX - 22), 0));
                }
                else if ((((currentLine % TenthOfSecondLine) == 0) && currentLine != 0)
                            && (currentLine % SecondLine) != 0)
                {
                    dc.DrawLine(grayPen, new Point(currentX, 30), new Point(currentX, 20));

                    FormattedText text = null;
                    switch (level)
                    {
                        case TimelineViewModel.ViewLevel.Level1:
                            text = new FormattedText(
                                    string.Format(".{0}", currentTime.Milliseconds),
                                    CultureInfo.CurrentCulture,
                                    FlowDirection.LeftToRight,
                                    new Typeface("Tahoma"),
                                    8,
                                    grayBrush);
                            break;
                    }

                    dc.DrawText(text, new Point((currentX - 8), 8));
                }
                else
                {
                    dc.DrawLine(grayPen, new Point(currentX, 30), new Point(currentX, 25));
                }

                currentX += DistanceBetweenLines;
                currentLine++;
                currentTime += timeStep;
            }
        }
        ret.Add(visual);
    }
    return ret;
}

PNG セグメントを保存します。

private static void saveHeaderSegmentAsPng(string fileName, RenderTargetBitmap renderTargetBitmap)
{
    var pngBitmapEncoder = new PngBitmapEncoder();

    pngBitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
    using (var fileStream = new FileStream(fileName, FileMode.Create))
    {
        pngBitmapEncoder.Save(fileStream);
        fileStream.Flush();
        fileStream.Close();
    }
}

すべての png セグメントは、個別のファイルで正しくレンダリングされます。そして、タイムラインは 1:20 を超えるまで正しくレンダリングされ、その後問題が発生します。

見る: ここに画像の説明を入力

画像がぼやけているようなものです。これで何が起こっているか知っている人はいますか?

ありがとう

4

1 に答える 1

3

私のリビングルームにあなたのアプローチのようなものが必要な水平解像度のテレビがある日を待っています.

ここでデモを行ったばかりのこのコード全体を破棄してください。使用可能保守可能になることは決してありません。そのうちの 1 つをなんとか絞り出すことしかできませんでした。

次に、VisualBrushについて学習します。そこにはたくさんのチュートリアルがあります。ビジュアル テンプレートを繰り返すことができ、PNG は必要ありません。また、画面の解像度が変更された場合 (最大 40001px 幅) にスケーリングされます。

マークの上に表示される数字には、100 万通りの異なるアプローチがあります。そのうちのいくつかは、タイムライン ユニット (2 つの大きなマークの間のスペース) を表すユーザー コントロールなど、上記のビジュアル ブラシと組み合わせることができます。それらのいくつかをグリッド (必要に応じてスタックパネル、キャンバスなど) に配置し、それらのオフセットとラベルを (動的に) 調整します。突然、画面上に 10 個のコントロールを持つ無限のタイムラインを表すことができます。

于 2013-03-20T23:26:05.760 に答える