[UWP]使用Win2D的BorderEffect實現圖片的平鋪功能
1. WPF有,而UWP沒有的圖片平鋪功能
在WPF中只要將ImageSource的TileMode
屬性設置為Tile
即可實現圖片的平鋪,具體可見WPF的這些文檔:
WPF圖片平鋪功能我幾乎沒用過,只是作為基礎中的基礎知識記住了用法。我以為那麼基礎的功能在UWP肯定有,根本不用懷疑,所以當我在UWP中發現這麼基礎的東西居然沒有時真的嚇了一跳。
上圖左面是WPF版本的TileBrush
,右邊是UWP版本,可以看到UWP版本功能少了一大半。
這麼小的一個類,我覺得沒必要在這裏做簡化吧。幸好圖片平鋪可以使用Win2D里的實現。
2. UWP中的圖片平鋪功能
<Grid>
<Rectangle x:Name="Background" />
</Grid>
假設有以上的XAML,要在名為Background
的元素上應用合成畫筆,首先引用 nuget包,然後參考官方文檔中 的部分使用圖片創建一個合成畫筆:
var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
var imageBrush = compositor.CreateSurfaceBrush();
var loadedSurface = LoadedImageSurface.StartLoadFromUri(new Uri("ms-appx:///110Strawberry.png"));
imageBrush.Surface = loadedSurface;
imageBrush.Stretch = CompositionStretch.None;
現在就差創建一個SpriteVisual
並把它應用到Background的VisualTree上了,順便一提,是這張圖片:
不過要實現平鋪功能還需要創建一個BorderEffect:
var borderEffect = new BorderEffect
{
Source = new CompositionEffectSourceParameter("source")
};
var effectFactory = compositor.CreateEffectFactory(borderEffect);
var effectBrush = effectFactory.CreateBrush();
effectBrush.SetSourceParameter("source", imageBrush);
var sprite = compositor.CreateSpriteVisual();
sprite.Brush = effectBrush;
var backgroundVisual = ElementCompositionPreview.GetElementVisual(Background);
var bindSizeAnimation = compositor.CreateExpressionAnimation("backgroundVisual.Size");
bindSizeAnimation.SetReferenceParameter("backgroundVisual", backgroundVisual);
sprite.StartAnimation("Size", bindSizeAnimation);
ElementCompositionPreview.SetElementChildVisual(Background, sprite);
總之BorderEffect
以imageBrush為Source,其它都保留默認值,將它它應用到Background的VisualTree上後效果如下:
這還不是我想要的平鋪效果。這是因為這時候ExtendX
和ExtendY
保持默認值的Clamp
,這個類型會讓BorderEffect重複圖像邊緣的屬性。如果要實現我想要的平鋪需要將這兩個屬性設置為Wrap
:
borderEffect.ExtendX = CanvasEdgeBehavior.Wrap;
borderEffect.ExtendY = CanvasEdgeBehavior.Wrap;
居然不是從左上角開始平鋪的,和我的想法還是有出入,不過這種細節就算了。順便一提ExtendX
和ExtendY
還可以設置為Mirror
,效果如下:
3. 綁定Size
var backgroundVisual = ElementCompositionPreview.GetElementVisual(Background);
var bindSizeAnimation = compositor.CreateExpressionAnimation("backgroundVisual.Size");
bindSizeAnimation.SetReferenceParameter("backgroundVisual", backgroundVisual);
sprite.StartAnimation("Size", bindSizeAnimation);
最後順便提一下,上面的代碼中有這麼一段代碼沒介紹到,這是用來動態地設置SpriteVisual
的尺寸。ExpressionAnimation有一直運行和永不停止這兩個特性,創建ExpressionAnimation並在SpriteVisual
上運行動畫,實際上將SpriteVisual
的Size永遠地綁定為backgroundVisual 的Size的值。其實簡單地訂閱SizeChanged
事件也能達到這個效果,代碼好像還少些。
4. 結語
這麼簡單的功能居然都要這麼多代碼,或者有更簡單的實現?不過凡事都有要辯證地看,幸好它這麼複雜,又讓我水了一篇博客。
有給出其它的方案,可以參考一下。
5. 參考
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】
※USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能
※評比前十大台北網頁設計、台北網站設計公司知名案例作品心得分享
※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選
※評比南投搬家公司費用收費行情懶人包大公開