2015-08-13 3 views
4

Итак, как сделать такой эффект, используя C# & XAML?
Как сделать эффект матового стекла в Windows 10 Universal App?

http://i.stack.imgur.com/L2Zhc.gif

+0

Вы уже пробовали? Какой-то код или что-то, что вы пытались сделать, но не сработали? – Mickey

+0

Я искал что-то подобное в Интернете, но есть примеры, которые размывают изображение, но не перекрываются, но они не имеют отношения к Windows 10, поэтому я даже не знаю с чего начать. И знать, что люди помогают мне, я написал здесь, но не для вас, чтобы написать ответ на презрение. – SnakeAce

+0

Возможный дубликат [Размытие за прозрачным окном WPF] (http: // stackoverflow.com/questions/31778017/blur-behind-transparent-wpf-window) – IInspectable

ответ

9

Я пытался создать что-то вроде этого с тех пор, iOS 7 представила матовое стекло. Теперь благодаря Win2D гораздо проще создать аналогичные эффекты в WinRT.

Во-первых, вам необходимо получить пакет Win2D.uwp от NuGet.

Идея заключается в том, чтобы создать GaussianBlurEffect на основе исходного изображения и поместить его поверх другого белого цветной маски, чтобы имитировать внешний вид матированного стекла.

Чтобы подготовить GaussianBlurEffect, вам необходимо создать элемент управления xaml CanvasControl из библиотеки Win2D. Таким образом, структура пользовательского интерфейса является то, как это -

<Grid x:Name="ImagePanel2" Width="356" Height="200" Margin="0,0,0,40" VerticalAlignment="Bottom"> 
    <Image x:Name="Image2" Source="Assets/Food.jpg" Stretch="UniformToFill" /> 
    <Grid x:Name="Overlay" ManipulationMode="TranslateX" ManipulationStarted="Overlay_ManipulationStarted" ManipulationDelta="Overlay_ManipulationDelta" ManipulationCompleted="Overlay_ManipulationCompleted" RenderTransformOrigin="0.5,0.5"> 
     <Grid.Clip> 
      <RectangleGeometry x:Name="Clip" Rect="0, 0, 356, 200" /> 
     </Grid.Clip> 
     <Rectangle x:Name="WhiteMask" Fill="White" /> 
     <Xaml:CanvasControl x:Name="Canvas" CreateResources="Canvas_CreateResources" Draw="Canvas_Draw" /> 
    </Grid> 
    <TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Frosted Glass" VerticalAlignment="Top" Foreground="#FF595959" Margin="12,12,0,0" FontWeight="Light" FontSize="26.667" FontStyle="Italic" TextLineBounds="Tight" /> 
</Grid> 

Примечание Я создал Clip для Overlay элемента, потому что мне нужно, чтобы уменьшить Rect 'третьего параметра s (т.е. Ширина) в то время как я панорамируя его влево, чтобы сделать иллюзию, что Overlay скользит вместе с моим пальцем.

код позади довольно прямо вперед -

void Canvas_CreateResources(CanvasControl sender, CanvasCreateResourcesEventArgs args) 
{ 
    args.TrackAsyncAction(CreateResourcesAsync(sender).AsAsyncAction()); 
} 

async Task CreateResourcesAsync(CanvasControl sender) 
{ 
    // give it a little bit delay to ensure the image is load, ideally you want to Image.ImageOpened event instead 
    await Task.Delay(200); 

    using (var stream = new InMemoryRandomAccessStream()) 
    { 
     // get the stream from the background image 
     var target = new RenderTargetBitmap(); 
     await target.RenderAsync(this.Image2); 

     var pixelBuffer = await target.GetPixelsAsync(); 
     var pixels = pixelBuffer.ToArray(); 

     var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream); 
     encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)target.PixelWidth, (uint)target.PixelHeight, 96, 96, pixels); 

     await encoder.FlushAsync(); 
     stream.Seek(0); 

     // load the stream into our bitmap 
     _bitmap = await CanvasBitmap.LoadAsync(sender, stream); 
    } 
} 

void Canvas_Draw(CanvasControl sender, CanvasDrawEventArgs args) 
{ 
    using (var session = args.DrawingSession) 
    { 
     var blur = new GaussianBlurEffect 
     { 
      BlurAmount = 50.0f, // increase this to make it more blurry or vise versa. 
      //Optimization = EffectOptimization.Balanced, // default value 
      //BorderMode = EffectBorderMode.Soft // default value 
      Source = _bitmap 
     }; 

     session.DrawImage(blur, new Rect(0, 0, sender.ActualWidth, sender.ActualHeight), 
      new Rect(0, 0, _bitmap.SizeInPixels.Width, _bitmap.SizeInPixels.Height), 0.9f); 
    } 
} 

void Overlay_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e) 
{ 
    // reset the inital with of the Rect 
    _x = (float)this.ImagePanel2.ActualWidth; 
} 

void Overlay_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) 
{ 
    // get the movement on X axis 
    _x += (float)e.Delta.Translation.X; 

    // keep the pan within the bountry 
    if (_x > this.ImagePanel2.ActualWidth || _x < 0) return; 

    // we clip the overlay to reveal the actual image underneath 
    this.Clip.Rect = new Rect(0, 0, _x, this.ImagePanel2.ActualHeight); 
} 

void Overlay_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) 
{ 
    // reset the clip to show the full overlay 
    this.Clip.Rect = new Rect(0, 0, this.ImagePanel2.ActualWidth, this.ImagePanel2.ActualHeight); 
} 

Вы можете дополнительно настроить BlurAmount свойства, а также непрозрачности фигуру (0.9f), чтобы получить ОТСИДЕТЬ точный эффект, который вы хотите.

Также следует отметить, что может быть другой (лучше?) способ сделать это в будущем. Если new Composition API поддерживает GaussianBlurEffect в будущей версии, я обновлю ответ.

Вы можете найти текущий рабочий образец этого GitHub repo. И я добавил изображение здесь, чтобы продемонстрировать, как это выглядит. :)

enter image description here

+0

О, милое решение, спасибо, но это половина того, что мне нужно. Так может ли быть какой-либо вариант с динамическим контентом? Итак, у нас есть основные и динамические рамки, например: ' код наложения, содержимое' Просто сейчас работает для фонового изображения. – SnakeAce

+0

Как я понял, все зависит от образа, а именно: '_bitmap = await CanvasBitmap.LoadAsync (sender,« here »);« Итак, можем ли мы отправить экран текущего кадра? Или есть другой метод? – SnakeAce

+0

@SnakeAce, 'LoadAsync' также принимает' IRandomAccessStream'. Таким образом, вы можете использовать 'RenderTargetBitmap' для получения растрового изображения из любого' UIElement' в пользовательском интерфейсе, а затем преобразовать его в 'InMemoryRandomAccessStream'. См. Мой обновленный ответ. –

2

Вы должны смотреть на классы Win2D и там для Canvas Effects - есть GaussianBlurEffect, которые могут быть полезны. Вот ссылка: http://microsoft.github.io/Win2D/html/N_Microsoft_Graphics_Canvas_Effects.htm и для GaussianBlurEffect: http://microsoft.github.io/Win2D/html/T_Microsoft_Graphics_Canvas_Effects_GaussianBlurEffect.htm включая некоторые образцы кода C#.

Дополнение: если вы хотите знать, как использовать win2D, я нашел удобный учебник (который я следующий себя прямо сейчас :)) http://blogs.msdn.com/b/uk_faculty_connection/archive/2014/09/05/win2d.aspx

+0

Не использовали классы Win2D, поэтому не могу сказать напрямую. Но интересно ли погода или нет метод использования SetWindowCompositionAttribute может быть лучше или хуже с точки зрения производительности? Я знаю, что он использует Interop, который может быть голосованием по отношению к Win2D, но также кажется очень ... Родным, так сказать :) (как вы могли бы услышать, я сам не тестировал его, просто знаю об этом, я сам проверил его, я буду экспериментировать с ним завтра и опубликую мои результаты здесь). Пример: http://withinrafael.com/adding-the-aero-glass-blur-to-your-windows-10-apps/ (извините «В твоем лице» -флаг) – ILOABN

Смежные вопросы