Яндекс.Метрика

    Песочница

    Полу-Prezi за 10 минут в .NET и WPF

    Речь пойдёт о создании программы для воспроизведения презентации по типу веб-сервиса Prezi, хотя подобную концепцию можно было видеть ранее в PowerPoint 2010 в одном из стандартных темплейтов.

    Отличие от обычной презентации в виде слайдов — наличие сплошного фона, как-бы полотна для контента, где перемещение от одной области с содержанием к другой происходит посредством перемещения, приближения и поворота.




    Итак, делаем что-то похожее в .NET и WPF. Лично мне нравится VB.NET (наверное из-за отсутствия {...}, которые занимают целую строку в C#).

    Необходимо: VisualStudio, Framework 4 и здоровая картинка, например 4800x3800, нарисованная в Фотошопе с каким-то контентом (можно налепить пару слайдов экспортом из PowerPoint):

    image

    В VisualStudio создаём пустой WPF проект и на «форму» добавляем следующие дела:
    фоновую картинку ImageBg с растяжкой под форму, компонент ScrollViewer со скрытыми барами и в него ещё одну картинку Image1 без растяжения.

    [Grid Name="Grid1"]
    [Image Name="ImageBg" Stretch="Fill"/]
    [ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"]
    [Image Name="Image1" Stretch="None"/]
    [/ScrollViewer]
    [/Grid]

    (<> заменено на [])

    Задаём переменные:

    'базовый путь к файлам
    Dim base_dir As String = System.AppDomain.CurrentDomain.BaseDirectory()
    'трансформация перемещением
    Dim trTranslate As New TranslateTransform
    'трансформация поворотом
    Dim trRotate As New RotateTransform
    'трансформация масштабированием
    Dim trScale As New ScaleTransform
    'шаг (как-бы слайд)
    Dim stp As Integer = 0
    'кол-во шагов
    Dim stp_count As Integer = 0
    'функция нелинейности для анимации перемещения
    Dim ease As New PowerEase
    'параметры изначального положения (масштаб, угол, координаты)
    Dim init_s, init_a As Double
    Dim init_x, init_y As Integer
    'параметры нового шага (масштаб, угол, координаты и время перемещения)
    Dim new_z(99) As Double
    Dim new_a(99) As Double
    Dim new_x(99) As Double
    Dim new_y(99) As Double
    Dim new_t(99) As Double


    Делаем предзагрузку изображений в Window_Loaded:

    ImageBg.Source = New BitmapImage(New Uri(base_dir + "bg.jpg"))
    Image1.Source = New BitmapImage(New Uri(base_dir + "content.jpg"))


    Файлы bg.jpg с каким-то фоном (например чёрным цветом) и content.jpg нужно положить в папку Debug.
    К контенту можно также добавить маску прозрачности .png, но пока это лишнее.

    Там же после загрузки изображение прописываем параметры трансформации:

    Dim transf_grp As New TransformGroup
    transf_grp.Children.Add(trTranslate)
    transf_grp.Children.Add(trRotate)
    transf_grp.Children.Add(trScale)
    Image1.RenderTransform = transf_grp


    Т.е. создаётся группа трансформации, в которую входят три отдельных типа трансформации.

    Задаём изначальное состояние контента, чтобы большая картинка вписывалась в экран с небольшим зазором (по-человечески это делается свойствами Stretch и Margin, но в данном случае нужно через трансформацию):


    init_s = Math.Round(Grid1.ActualWidth / (Image1.Source.Width + 50), 2)
    init_a = 0
    init_x = 50
    init_y = (Grid1.ActualHeight - (Image1.Source.Height) * init_s) * 2
    trScale.ScaleX = init_s
    trScale.ScaleY = init_s
    trRotate.Angle = init_a
    trTranslate.X = init_x
    trTranslate.Y = init_y


    Загрузка списков шагов из файла:

    If File.Exists(base_dir + "loc.ini") Then
    Dim oRead As System.IO.StreamReader = File.OpenText(base_dir + "loc.ini")
    Dim data(99) As String
    Dim i As Integer = 0
    Do While oRead.Peek >= 0
    i += 1
    data(i) = oRead.ReadLine()
    Dim param() As String = data(i).Split(",")
    new_z(i) = CDbl(param(0))
    new_a(i) = CDbl(param(1))
    new_x(i) = CDbl(param(2))
    new_y(i) = CDbl(param(3))
    new_t(i) = CDbl(param(4))
    If new_z(i) <> 0 Then stp_count += 1
    Loop
    oRead.Close()
    End If


    Структура файла: каждая строка — это новый шаг, а в строке через запятую 5 параметров (масштаб, угол, координаты x и y, время перемещения)

    Добавляем обработку перемещения между шагами:

    Private Sub NavigationStep()
    Dim Z_anim As New DoubleAnimation(trScale.ScaleX, new_z(stp), TimeSpan.FromSeconds(new_t(stp)))
    Dim A_anim As New DoubleAnimation(trRotate.Angle, new_a(stp), TimeSpan.FromSeconds(new_t(stp) / 2))
    Dim X_anim As New DoubleAnimation(trTranslate.X, new_x(stp), TimeSpan.FromSeconds(new_t(stp)))
    Dim Y_anim As New DoubleAnimation(trTranslate.Y, new_y(stp), TimeSpan.FromSeconds(new_t(stp)))
    ease.EasingMode = EasingMode.EaseInOut
    Z_anim.EasingFunction = ease
    A_anim.EasingFunction = ease
    X_anim.EasingFunction = ease
    Y_anim.EasingFunction = ease
    trScale.BeginAnimation(ScaleTransform.ScaleXProperty, Z_anim)
    trScale.BeginAnimation(ScaleTransform.ScaleYProperty, Z_anim)
    trRotate.BeginAnimation(RotateTransform.AngleProperty, A_anim)
    trTranslate.BeginAnimation(TranslateTransform.XProperty, X_anim)
    trTranslate.BeginAnimation(TranslateTransform.YProperty, Y_anim)
    End Sub


    Тут просто 4 анимации для масштаба, угла и координат (конечно переменные можно было задать заранее для чистоты кода, но так тоже почти компактно).

    Собственно вот и всё по сути.
    Осталось записать набор шагов в текстовый файл loc.ini, например:
    1.5,0,-70,-40,1.5
    2,-100,-1200,-100,2
    3,85,110,-640,1
    4,35,-735,-1800,0.5

    И активировать переключение между шагами в коде:

    Private Sub Image1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles Image1.MouseUp
    If Not setup_mode And Not sel_mode Then
    If e.GetPosition(Grid1).X < Grid1.ActualWidth / 2 Then
    stp -= 1
    If stp <= 0 Then stp = stp_count
    NavigationStep()
    End If
    If e.GetPosition(Grid1).X >= Grid1.ActualWidth / 2 Then
    stp += 1
    If stp = stp_count + 1 Then stp = 1
    NavigationStep()
    End If
    End If
    End Sub


    Если нажали на левую часть изображения контента — на шаг назад, на правую — вперёд.

    Для нормальной работы конечно нужен режим настройки с последующим сохранением новых параметров. Но тут его описывать не буду, а рабочую бета-версию можно скачать тут. Для запуска нужен Framework 4.

    Также можно совершенствовать программу по многим направлениям — добавить поддержку векторного контента (что более приблизит к Prezi), сделать сохранение проекта, добавить мульти-тач для настройки, быструю навигацию, смену полотна контента и прочее.