Creating Gradient Brush along a Circular Path

前端 未结 3 468
-上瘾入骨i
-上瘾入骨i 2020-12-05 01:15

I need to create a multi-step gradient along a circular path, as demonstrated in the following image:

\"Wheel

相关标签:
3条回答
  • 2020-12-05 01:51

    You can get a cross-radial effect by using a non-affine transformation such as a perspective transform. I used the ideas in this article by Charles Petzold:

    • Non-Affine Transforms in 2D?

    to create a XAML-only annular region with a cross-radial gradient. Here is the markup:

    <Canvas x:Name="LayoutRoot">
        <Canvas.Resources>
            <x:Array x:Key="sampleData" Type="sys:Object">
                <x:Array Type="sys:Object">
                    <sys:Double>0</sys:Double>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                        <GradientStop Color="Red" Offset="0"/>
                        <GradientStop Color="Yellow" Offset="0.5"/>
                        <GradientStop Color="Blue" Offset="1"/>
                    </LinearGradientBrush>
                </x:Array>
                <x:Array Type="sys:Object">
                    <sys:Double>90</sys:Double>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                        <GradientStop Color="Blue" Offset="0"/>
                        <GradientStop Color="Green" Offset="0.5"/>
                        <GradientStop Color="Red" Offset="1"/>
                    </LinearGradientBrush>
                </x:Array>
                <x:Array Type="sys:Object">
                    <sys:Double>180</sys:Double>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                        <GradientStop Color="Red" Offset="0"/>
                        <GradientStop Color="Yellow" Offset="0.5"/>
                        <GradientStop Color="Blue" Offset="1"/>
                    </LinearGradientBrush>
                </x:Array>
                <x:Array Type="sys:Object">
                    <sys:Double>270</sys:Double>
                    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                        <GradientStop Color="Blue" Offset="0"/>
                        <GradientStop Color="Green" Offset="0.5"/>
                        <GradientStop Color="Red" Offset="1"/>
                    </LinearGradientBrush>
                </x:Array>
            </x:Array>
        </Canvas.Resources>
        <ItemsControl ItemsSource="{StaticResource sampleData}">
            <ItemsControl.OpacityMask>
                <RadialGradientBrush>
                    <GradientStop Color="Transparent" Offset="0.95"/>
                    <GradientStop Color="White" Offset="0.949"/>
                    <GradientStop Color="White" Offset="0.501"/>
                    <GradientStop Color="Transparent" Offset="0.5"/>
                </RadialGradientBrush>
            </ItemsControl.OpacityMask>
            <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                    <ItemsPresenter/>
                </ControlTemplate>
            </ItemsControl.Template>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Canvas Width="1" Height="1">
                        <Canvas.RenderTransform>
                            <RotateTransform Angle="{Binding [0]}" CenterX="124" CenterY="124"/>
                        </Canvas.RenderTransform>
                        <Viewport3D Width="250" Height="250">
                            <ModelVisual3D>
                                <ModelVisual3D.Content>
                                    <Model3DGroup>
                                        <GeometryModel3D>
                                            <GeometryModel3D.Geometry>
                                                <MeshGeometry3D Positions="0 0 0, 0 1 0, 1 0 0, 1 1 0" TextureCoordinates="0 1, 0 0, 1 1, 1 0" TriangleIndices="0 2 1, 2 3 1"/>
                                            </GeometryModel3D.Geometry>
                                            <GeometryModel3D.Material>
                                                <DiffuseMaterial Brush="{Binding [1]}"/>
                                            </GeometryModel3D.Material>
                                            <GeometryModel3D.Transform>
                                                <MatrixTransform3D Matrix="0.002,0,0,0,-0.499,-0.498,0,-0.998,0,0,1,0,0.499,0.5,0,1"/>
                                            </GeometryModel3D.Transform>
                                        </GeometryModel3D>
                                        <AmbientLight Color="White" />
                                    </Model3DGroup>
                                </ModelVisual3D.Content>
                            </ModelVisual3D>
                            <Viewport3D.Camera>
                                <OrthographicCamera Position="0.5 0.5 1" LookDirection="0 0 -1" UpDirection="0 1 0" Width="1"/>
                            </Viewport3D.Camera>
                        </Viewport3D>
                    </Canvas>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Canvas>
    

    and here is the visual result:

    enter image description here

    The effect uses a data source collection with items that have two properties, an angle and a brush. It draw four quadrants (up, right, down and left) using a different brush for each quadrant. Then the whole thing is clipped to the annular region with an opacity mask.

    0 讨论(0)
  • 2020-12-05 02:11

    Take a look at Shazzam You could write a pixelshader that renders this gradient.

    I think that in the long run this will be easier than combining linear gradients. An other option is to simply draw a bitmap and use it.

    0 讨论(0)
  • 2020-12-05 02:13

    In GDI+/Winforms you can use the PathGradientBrush to do this:

    http://www.bobpowell.net/pgb.htm

    http://msdn.microsoft.com/en-us/library/system.drawing.drawing2d.pathgradientbrush.aspx

    Unfortunately there is no support for a PathGradientBrush in WPF but a few people have asked for it here:

    http://dotnet.uservoice.com/forums/40583-wpf-feature-suggestions/suggestions/480949-add-a-pathgradientbrush-like-in-winforms-

    (might be worth casting your vote too!)

    Because of the lack of support you cannot do it directly in XAML, you could however use GDI+ code to create an image and then use the image in your XAML. This might give you better performance than using a non-affine transformation.

    0 讨论(0)
提交回复
热议问题