在圆值附近添加标签

时间:2017-07-14 03:09:11

标签: wpf geometry

所以我有Circular Progress-Bar,我希望Label围绕圈Value定位。

这就是我的尝试:

<Grid x:Name="LayoutRoot" VerticalAlignment="Center" HorizontalAlignment="Center">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <DesignInControl:CircularProgressBar HorizontalAlignment="Center" VerticalAlignment="Center" SegmentColor="#FF878889" StrokeThickness="25" Percentage="100" Radius="100"/>
            <DesignInControl:CircularProgressBar x:Name="circle" HorizontalAlignment="Center" VerticalAlignment="Center" Percentage="0" SegmentColor="Red" StrokeThickness="25" Radius="100"/>
        </Grid>
    </StackPanel>
    <Label x:Name="vlb" Content="{Binding ElementName=circle, Path=Percentage}" Margin="-50,-50,-50,-50" RenderTransformOrigin="0.5,0.5" Grid.RowSpan="2">
        <Label.RenderTransform>
        <TransformGroup>
                <ScaleTransform/>
                <SkewTransform/>
                <RotateTransform Angle="3600.12"/>
                <TranslateTransform/>
            </TransformGroup>
    </Label.RenderTransform>                                                  
    </Label>
</Grid>

现在在我的Timer里面,我每秒将Circelr百分比提高1:

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    double d = circle.Percentage += 1;
    var radius = 100;
    var sangle = (d * 360) / 100;
    double angleRad = (Math.PI / 180.0) * (sangle - 90);
    double x = radius * Math.Cos(angleRad);
    double y = radius * Math.Sin(angleRad);
    vlb.RenderTransform = new RotateTransform { Angle = sangle, CenterX = 0, CenterY = 0 };
}

结果是我的Label现在是直的:

enter image description here

更新

<Grid x:Name="LayoutRoot" VerticalAlignment="Center" HorizontalAlignment="Center">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
            <DesignInControl:CircularProgressBar HorizontalAlignment="Center" VerticalAlignment="Center" SegmentColor="#FF878889" StrokeThickness="25" Percentage="100" Radius="100"/>
            <DesignInControl:CircularProgressBar x:Name="circle" HorizontalAlignment="Center" VerticalAlignment="Center" Percentage="0" SegmentColor="SeaGreen" StrokeThickness="25" Radius="100"/>
        </Grid>
    </StackPanel>
    <Label x:Name="vlb_outer" Margin="-50,-50,-50,-50" RenderTransformOrigin="0.5,0.5" Grid.RowSpan="2">
        <Label.RenderTransform>
            <TransformGroup>
                <ScaleTransform/>
                <SkewTransform/>
                <RotateTransform Angle="50"/>
                <TranslateTransform/>
            </TransformGroup>
        </Label.RenderTransform>
        <Label Content="{Binding ElementName=circle, Path=Percentage}" FontSize="20" x:Name="vlb_inner">
            <Label.RenderTransform>
                <TransformGroup>
                    <RotateTransform Angle="-50"/>
                </TransformGroup>
            </Label.RenderTransform>
        </Label>
    </Label>
</Grid>

结果

enter image description here

Update

开始位置:

enter image description here

Value之后1加注:

enter image description here

Label左侧尺寸很小。

2 个答案:

答案 0 :(得分:0)

之前我从未在wpf中使用过变换,但由于我有游戏开发背景,这对我来说很容易处理:

我创建了一个孩子 - Label,它具有绑定和自己的TransformGroup,如下所示:

<Label x:Name="vlb_outer" Margin="-50,-50,-50,-50" RenderTransformOrigin="0.5,0.5" Grid.RowSpan="2">
    <Label.RenderTransform>
        <TransformGroup>
            <ScaleTransform/>
            <SkewTransform/>
            <RotateTransform Angle="50"/>
            <TranslateTransform/>
        </TransformGroup>
    </Label.RenderTransform>
    <Label Content="{Binding Value}" x:Name="vlb_inner">
        <Label.RenderTransform>
            <TransformGroup>
                <RotateTransform Angle="-50"/>
            </TransformGroup>
        </Label.RenderTransform>
    </Label>
</Label>

现在我在代码中所做的很简单,我只是将rotationvalue分配给vlb_outer元素,将负旋转值分配给vlb_inner元素。通过这种方式,它将围绕其自身的中心向相反方向旋转相同的角度。

vlb_outer.RenderTransform = new RotateTransform() { Angle = value };
vlb_inner.RenderTransform = new RotateTransform() { Angle = -value };

我为我简化了所有内容,因为我没有您的代码,但它似乎有效。我尝试使用0到360之间的滑块,并将值绑定到Content和旋转。

希望它有所帮助。

修改

好吧,因为你不喜欢这个位置(显然),我玩弄了我的计算并信任我,我讨厌硬编码的值,但在这种情况下,他们帮了我很多。

我目前的代码如下:

private void Rotate(double value)
{
    double sangle = value * 360 + 42;
    vlb_outer.RenderTransform = new RotateTransform() { Angle = sangle, CenterX = 0, CenterY = 0 };
    vlb_inner.RenderTransform = new RotateTransform() { Angle = -sangle, CenterX = 0, CenterY = 0 };
    Value = (int)(value*360);
}

它获取值(从0到1)并将其乘以360(用于旋转)和一个用于修复起始位置的幻数。我不认为42是完美的,但周围的东西对我有用。

修改

此代码应该适合您

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    double sangle = circle.Percentage * 3.6 + 42;
    vlb_outer.RenderTransform = new RotateTransform() { Angle = sangle, CenterX = 0, CenterY = 0 };
    vlb_inner.RenderTransform = new RotateTransform() { Angle = -sangle, CenterX = 0, CenterY = 0 };
}

答案 1 :(得分:0)

我认为你只是搞砸了你的定位和利润。我没有你的圆圈控件,所以我只是使用一个静态的黄色圆圈来移动标签,并带有一个滑块用于演示:

<Grid>
    <Slider x:Name="angleProvider" Minimum="0" Maximum="360" VerticalAlignment="Top" HorizontalAlignment="Center" MinWidth="100" Margin="10"/>
    <Ellipse
        Width="50" Height="50"
        VerticalAlignment="Center" HorizontalAlignment="Center"
        Fill="Yellow"/>
    <Label
        Content="{Binding ElementName=angleProvider,Path=Value}" ContentStringFormat="{}{0:##0'°'}"
        RenderTransformOrigin="0.5,0.5"
        Width="80" Height="80"
        Padding="0"
        VerticalAlignment="Center" HorizontalAlignment="Center"
        VerticalContentAlignment="Top" HorizontalContentAlignment="Center">
        <Label.RenderTransform>
            <TransformGroup>
                <ScaleTransform/>
                <SkewTransform/>
                <RotateTransform Angle="{Binding ElementName=angleProvider,Path=Value}"/>
                <TranslateTransform/>
            </TransformGroup>
        </Label.RenderTransform>
    </Label>
</Grid>

所以基本上,将标签的中心放在与圆圈中心相同的位置,将标签内容放在中心位置,设置宽度和高度大于圆圈,使文字显示在外面,旋转标签它的中心。

注意我没有检查您实际需要的RotateTransform以外的哪些变换。我认为可以从TransformGroup删除所有其他内容。