Создание градиентной кисти вдоль круговой траектории - PullRequest
14 голосов
/ 30 января 2011

Мне нужно создать многошаговый градиент вдоль круговой траектории, как показано на следующем рисунке:

Wheel Gradient

Есть ли у кого-нибудь какие-либо идеи о том, как это можно сделатьв XAML, а не код?Можно ли использовать существующие градиентные кисти или как-то их комбинировать для достижения этого эффекта?

Ответы [ 3 ]

16 голосов
/ 30 января 2011

Вы можете получить перекрестный радиальный эффект, используя неаффинное преобразование, такое как перспективное преобразование.Я использовал идеи этой статьи Чарльза Петцольда:

для создания кольцевой области только для XAMLс поперечным радиальным градиентом.Вот разметка:

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

, а вот визуальный результат:

enter image description here

Эффект использует коллекцию источника данных с элементами, имеющими два свойства,угол и кисть.Он рисует четыре квадранта (вверх, вправо, вниз и влево), используя разные кисти для каждого квадранта.Затем все это обрезается до кольцевой области с маской непрозрачности.

1 голос
/ 31 января 2011

В GDI + / Winforms вы можете использовать PathGradientBrush для этого:

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

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

К сожалению, нет поддержки PathGradientBrush в WPF, но несколько человек просили об этом здесь:

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

(возможно, стоит отдать свой голос тоже!)

Из-за отсутствия поддержки вы не можете сделать это напрямую в XAML, однако вы можете использовать код GDI + для создания изображения, а затем использовать изображение в вашем XAML. Это может дать вам лучшую производительность, чем использование неаффинного преобразования.

0 голосов
/ 30 января 2011

Взгляните на Shazzam Вы можете написать пиксельный шейдер, который отображает этот градиент.

Я думаю, что в долгосрочной перспективе это будет проще, чем объединение линейных градиентов.Другой вариант - просто нарисовать растровое изображение и использовать его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...