Start by introducing a small ad:
Recently bought a millet box toss, found that the UI is quite beautiful, especially the homepage that reflection effect.
(the figure is casually looking at the bottom of the image above the reflection effect.) )
Well, the advertisement is over, return to the point, this reflection effect I personally think is very good, then there is no way to achieve in the WIN10?
A little analysis, the approximate level is this:
Simply put, the reflection is displayed in the same way as the control, then flipped down and panned. Finally, add a gradient to the reflection of transparency on the perfect.
It's easy to flip and pan, so you can use RenderTransform. Trouble is how to make the reflection display the same as the display of the control.
There is no such thing as VisualBrush in the WinRT, so we have to find another path. The saying goes: God closes a door and opens a window for you. Although Microsoft removed VisualBrush, but gave us rendertargetbitmap this to get the most control of the current appearance of the artifact. (MediaElement can not get, WebView need to use Webviewbrush to obtain, here we ignore these two are not common requirements of the guy. )
Then we can set the reflection to the Image control, then assign the value to RenderTargetBitmap on it. But the question comes again, when should we go to catch the appearance of the control? Check out MSDN to learn that the LayoutUpdated event can help us.
Wait for what, and immediately start writing our code.
Create our project with a new templated control named Reflectionpanel.
Then define our control template as follows:
<ResourceDictionaryxmlns= "Http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x= "Http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local= "Using:reflectionpaneldemo"Xmlns:controls= "Using:ReflectionPanelDemo.Controls"> <StyleTargetType= "Controls:reflectionpanel"> <Setter Property= "HorizontalAlignment"Value= "Center" /> <Setter Property= "VerticalAlignment"Value= "Center" /> <Setter Property= "Template"> <Setter.value> <ControlTemplateTargetType= "Controls:reflectionpanel"> <Gridx:name= "Rootlayout"Background="{TemplateBinding Background}"> <!--#region Reflection - <!--the center of the bottom of the control as the transform point - <Imagex:name= "Reflectionimage"Stretch= "None"Rendertransformorigin= "0.5,1"> <Image.rendertransform> <TransformGroup> <!--invert controls at the bottom of the control - <ScaleTransformScaleY= "-1" /> <!--the distance between the reflection and the actual content - <TranslateTransformx:name= "Spacingtransform"Y= "0" /> </TransformGroup> </Image.rendertransform> </Image> <!--#endregion - <!--#region Actual content - <ContentControlx:name= "Contentborder"Content="{TemplateBinding Content}" /> <!--#endregion - </Grid> </ControlTemplate> </Setter.value> </Setter> </Style></ResourceDictionary>
This corresponds to the previous analysis.
Next write the CS code.
protected Override voidOnApplyTemplate () {FrameworkElement rootlayout= (FrameworkElement) This. GetTemplateChild ("Rootlayout"); //The actual content container. This. _contentborder = (ContentControl) This. GetTemplateChild ("Contentborder"); //reflection image. This. _reflectionimage = (Image) This. GetTemplateChild ("Reflectionimage"); //reflection displacement. This. _spacingtransform = (TranslateTransform) This. GetTemplateChild ("Spacingtransform"); This. _spacingtransform.y = This. reflectionspacing; if(designmode.designmodeenabled = =false) {rootlayout.layoutupdated+= This. rootlayoutchanged; }}Private Async voidRootlayoutchanged (ObjectSenderObjecte) { Try { //renders the control to the image source. RenderTargetBitmap Contentrender =NewRenderTargetBitmap (); awaitContentrender.renderasync ( This. _contentborder); //set the reflection image. This. _reflectionimage.source =Contentrender; } Catch { }}
Here is the most critical code. See the demo at the end of the article for details.
Let's try it next.
It feels good to say.
Finally, let's do a gradual translucent effect.
In WinRT, because there is no opacitymask attribute, so we still start with the picture.
RenderTargetBitmap has a method called Getpixelsasync, you can get to the image of the data, the format is in the form of BGRA8, here linkage of the old Week blog Good (http://www.cnblogs.com/tcjiaan /p/4231886.html).
To put it simply, every 4 bytes represents a pixel. We simply analyze the requirements, then we can conclude that the top of the picture is the most transparent, the bottom is the most opaque.
After a simple mathematical calculation, we can write the following code:
//gets the image data. byte[] Bgra8 = (awaitContentrender.getpixelsasync ()). ToArray ();//Gets the height and width of the image. intwidth =Contentrender.pixelwidth;intHeight =Contentrender.pixelheight; for(inti =0; I < Bgra8. Length; i + =4){ //gets the original channel A of the pixel. byteA = Bgra8[i +3]; //calculates the Y-axis coordinates of the pixel. inty = (I/4) /width; //calculates the new A-channel value. Bgra8[i +3] = (byte) (A * Y/height);}
Finally we get the modified data to the Image control to go up OK. Here we use WriteableBitmap.
New writeablebitmap (width, height); bgra8. CopyTo (outputbitmap.pixelbuffer); // set the reflection image. this. _reflectionimage.source = Outputbitmap;
You are done, look at the Demo effect.
Finally comes with full Demo download: reflectionpaneldemo.zip
Finally, the ice and snow naked 360 degrees knelt to beg a job uwp/wp8.1 related . (Toss Winform quickly spit blood) (long-term effective)
"Win10" implements the control reflection effect