使用silverlight中的图像的离散颜色填充显示进度

时间:2012-01-12 00:10:18

标签: .net silverlight animation controls progress

在Silverlight中,我想显示上传过程的进度,作为图像上的一系列增量颜色填充。

例如,

这是进度为0时:enter image description here

这是30%:enter image description here

和100%是完全彩色的图像:enter image description here

如何控制颜色填充(我知道这将借助于技巧,如覆盖原始图像的最终图像)来显示进度?

我的任务可能很棘手,因为该图像是Windows Phone项目中按钮的OpacityMask。

P.S。只是为了避免混淆,因为我担心问题的设计方面。通过某些操作挂钩进度的逻辑已经到位。我只需要列出一个进展的介绍。

2 个答案:

答案 0 :(得分:2)

修改

我做了一个实现。 A more thorough explanation and download of the code can be found on my blog

C#:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace CustomControls
{
    [TemplatePart(Name="CLIPRECTANGLE", Type=typeof(RectangleGeometry))]
    public class ImageProgressBar : ProgressBar
    {
        public ImageProgressBar()
        {
            this.DefaultStyleKey = typeof(ImageProgressBar);
        }

        public ImageSource Source
        {
            get { return (ImageSource)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(ImageSource), typeof(ImageProgressBar), new PropertyMetadata(null));

        public Brush Fill
        {
            get { return (Brush)GetValue(FillProperty); }
            set { SetValue(FillProperty, value); }
        }

        public static readonly DependencyProperty FillProperty =
            DependencyProperty.Register("Fill", typeof(Brush), typeof(ImageProgressBar), new PropertyMetadata(null));

        private RectangleGeometry _clip;

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            _clip = this.GetTemplateChild("CLIPRECTANGLE") as RectangleGeometry;
            this.ValueChanged += ImageProgressBar_ValueChanged;
            this.SizeChanged += ImageProgressBar_SizeChanged;
        }

        void ImageProgressBar_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            UpdateClip();
        }

        void ImageProgressBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            UpdateClip();
        }

        private void UpdateClip()
        {
            if (_clip != null)
            {
                _clip.Rect = new Rect(0, 0, this.ActualWidth, this.ActualHeight * ((this.Value - this.Minimum) / (this.Maximum - this.Minimum)));
            }
        }
    }
}

模板:generic.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:CustomControls">
    <Style TargetType="local:ImageProgressBar">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:ImageProgressBar">
                    <Border BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Margin="{TemplateBinding Margin}"
                            Background="{TemplateBinding Background}"
                            Width="{TemplateBinding Width}"
                            Height="{TemplateBinding Height}">
                        <Grid>
                            <Image Source="{TemplateBinding Source}"
                                   Stretch="Fill" />
                            <Rectangle Fill="{TemplateBinding Fill}">
                                <Rectangle.OpacityMask>
                                    <ImageBrush ImageSource="{Binding Path=Source, RelativeSource={RelativeSource TemplatedParent}}"
                                                Stretch="Fill" />
                                </Rectangle.OpacityMask>
                                <Rectangle.Clip>
                                    <RectangleGeometry x:Name="CLIPRECTANGLE" />
                                </Rectangle.Clip>
                            </Rectangle>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

</ResourceDictionary>

使用方法:

<my:ImageProgressBar Width="100"
                        Height="100"
                        Fill="Red"
                        Source="ProgressBar.png"
                        Minimum="100"
                        Maximum="200"
                        Value="{Binding ElementName=slider1, Path=Value, Mode=TwoWay}" />
<Slider Margin="0"
        Name="slider1"
        VerticalAlignment="Top"
        Minimum="100"
        Maximum="200"
        Value="125" />

像魅力一样:

Example

原始答案

你可以像这样创建一个线性渐变画笔:

<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
    <GradientStop Color="Black" Offset="0"/>
    <GradientStop Color="Black" Offset="1"/>
    <GradientStop Color="Lime" Offset="1"/>
    <GradientStop Color="Lime" Offset="1"/>
</LinearGradientBrush>

使用此画笔绘制形状/字符/文本/任何内容。

要显示进度,只需更新中间两个渐变停止的偏移。您可以绑定这些以使其更容易。

创建一个真正的进度条:为ProgressBar创建一个模板,并(多个)将偏移量绑定到进度条的值,最小值和最大值,并按(Value - Minimum)/(Maximum - Minimum)计算偏移量

使用位图(PNG):

<Grid HorizontalAlignment="Center"
        VerticalAlignment="Center">
    <Image Source="ProgressBar.png"
            Width="100"
            Height="100" />
    <Rectangle Fill="Lime">
        <Rectangle.OpacityMask>
            <ImageBrush ImageSource="ProgressBar.png" />
        </Rectangle.OpacityMask>
        <Rectangle.Clip>
            <RectangleGeometry Rect="0,25,100,75"/>
        </Rectangle.Clip>
    </Rectangle>
</Grid>

进度更改时替换Rect。切断正确的金额。

请注意,相同的图像用于蒙版。

答案 1 :(得分:0)

我前几天制作了自定义ProgressBar。我不打算告诉你如何做你的(因为我不是设计师),但它并不困难。

创建模板

<ControlTemplate x:Key="CustomProgressBarTemplate" TargetType="ProgressBar">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CommonStates">
                <VisualState x:Name="Determinate"/>
                <VisualState x:Name="Indeterminate">
                    <!--Modyify your Storyboard-->
                    <Storyboard RepeatBehavior="Forever">
                        <DoubleAnimation Storyboard.TargetName="IndeterminateGradientFill"
                            Storyboard.TargetProperty="(Shape.Fill).(LinearGradientBrush.Transform).(TransformGroup.Children)[0].X"
                            Duration="00:00:.5" From="0" To="20" />
                        <ObjectAnimationUsingKeyFrames Duration="00:00:00" Storyboard.TargetName="IndeterminateRoot" Storyboard.TargetProperty="(UIElement.Visibility)">
                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Visible</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                        <ObjectAnimationUsingKeyFrames Duration="00:00:00" Storyboard.TargetName="DeterminateRoot" Storyboard.TargetProperty="(UIElement.Visibility)">
                            <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                <DiscreteObjectKeyFrame.Value>
                                    <Visibility>Collapsed</Visibility>
                                </DiscreteObjectKeyFrame.Value>
                            </DiscreteObjectKeyFrame>
                        </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
        <!--Default Root Visuals for either type of ProgressBar-->
        <Border x:Name="ProgressBarTrack" CornerRadius="3" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" />
        <Grid x:Name="ProgressBarRootGrid" >
            <Grid Margin="1">
            </Grid>
            <!-- Beginning of Indeterminate Progress Bar Visuals-->
            <Grid x:Name="IndeterminateRoot" Opacity="0.88" Visibility="Collapsed">
            </Grid>
            <!-- Beginning of Determinate Progress Bar Visuals-->
            <Grid x:Name="DeterminateRoot" Margin="1" >   
            </Grid>
        </Grid>
    </Grid>
</ControlTemplate>

在行列式和不确定网格中,只需使用路径和形状绘制图像 (Storyboard.TargetProperty =“(Shape.Fill)。(LinearGradientBrush.Transform)。(TransformGroup.Children)[0] .X”LinearGradientBrush是我用来填充网格中的对象的画笔。)

应用模板

 <ProgressBar Template="{StaticResource CustomProgressBarTemplate}"/>

您必须使用设计,确保您只需填写正确的UIElement。我希望这对你来说是一个好的开始