沿着圆形路径创建渐变画笔。

时间:2023-01-04 21:27:55

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

我需要沿着圆形路径创建一个多步梯度,如下图所示:

沿着圆形路径创建渐变画笔。

Does anyone have any ideas on how this could be accomplished in XAML rather than code? Would it be possible to use the existing gradient brushes or composite them somehow to achieve this effect?

有人知道如何在XAML而不是代码中实现这一点吗?是否可以使用现有的梯度刷或复合材料来达到这种效果?

3 个解决方案

#1


15  

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:

您可以通过使用非仿射变换(如透视变换)获得交叉径向效应。我引用了查尔斯·佩佐德在这篇文章中的观点:

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

创建一个只有xml的、具有交叉径向梯度的环形区域。这是标记:

<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:

这是视觉结果:

沿着圆形路径创建渐变画笔。

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.

该效果使用具有两个属性、一个角度和一个笔刷的项的数据源集合。它用不同的笔刷绘制四个象限(上、右、下、左)。然后用一个不透明的蒙版将整个物体裁剪到环形区域。

#2


1  

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

在GDI+/Winforms中,您可以使用PathGradientBrush来完成以下操作:

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

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

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

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:

不幸的是,在WPF中没有对PathGradientBrush的支持,但是有一些人在这里要求它:

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

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.

由于缺少对XAML的支持,所以不能直接在XAML中执行,因此可以使用GDI+代码创建映像,然后在XAML中使用映像。这可能比使用非仿射变换有更好的性能。

#3


0  

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

看看Shazzam,你可以写一个像素着色器来渲染这个渐变。

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.

我认为从长远来看,这比合并线性梯度要容易。另一种选择是简单地绘制位图并使用它。

#1


15  

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:

您可以通过使用非仿射变换(如透视变换)获得交叉径向效应。我引用了查尔斯·佩佐德在这篇文章中的观点:

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

创建一个只有xml的、具有交叉径向梯度的环形区域。这是标记:

<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:

这是视觉结果:

沿着圆形路径创建渐变画笔。

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.

该效果使用具有两个属性、一个角度和一个笔刷的项的数据源集合。它用不同的笔刷绘制四个象限(上、右、下、左)。然后用一个不透明的蒙版将整个物体裁剪到环形区域。

#2


1  

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

在GDI+/Winforms中,您可以使用PathGradientBrush来完成以下操作:

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

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

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

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:

不幸的是,在WPF中没有对PathGradientBrush的支持,但是有一些人在这里要求它:

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

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.

由于缺少对XAML的支持,所以不能直接在XAML中执行,因此可以使用GDI+代码创建映像,然后在XAML中使用映像。这可能比使用非仿射变换有更好的性能。

#3


0  

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

看看Shazzam,你可以写一个像素着色器来渲染这个渐变。

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.

我认为从长远来看,这比合并线性梯度要容易。另一种选择是简单地绘制位图并使用它。