首页 > 解决方案 > 在填充缺失角的同时保留线条的扁平 LineCap 属性

问题描述

我目前正在尝试使用给定的坐标模拟铁路的轨道。以前我一直在为 StrokeStart 和 StrokeEnd LineCap 属性使用“圆角”值,但是使用该值获得的附加半径在添加轨道接头时会导致问题。我切换到 LineCap 的“flat”值,除了我的轨道的“角落”没有填充这一事实之外,它的效果要好得多,如下所示:

缺角 https://imgur.com/a/EliIlzD

我试图通过首先使用“Round”值渲染我的所有轨道,然后使用“Flat”值再次在顶部渲染它们来抵消这种情况,这似乎填充了角落,但会导致其他问题,例如当轨道被占用时重叠的颜色,以及我首先渲染的圆形轨道在轨道末端出现:

重叠颜色 https://imgur.com/a/0XCVGv5

曲目结尾处的问题 https://imgur.com/a/fKju9uA

我的 XAML 只是一条简单的线,由具有来自我的视图模型的各种绑定的坐标列表形成,以及用于稍微缩小我的坐标的转换器。这显然是首先使用 Rounded EndCaps 渲染的轨道:


<Line  X1="{Binding X1, Converter={StaticResource ScaleXCoordConverter}}" Y1="{Binding Y1, Converter={StaticResource ScaleYCoordConverter}}"
                                                   X2="{Binding X2, Converter={StaticResource ScaleXCoordConverter}}" Y2="{Binding Y2, Converter={StaticResource ScaleYCoordConverter}}"
                                                   Stroke="{Binding DataContext.LineColor, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}}" 
                                                   StrokeThickness="2" StrokeEndLineCap="Round" StrokeStartLineCap="Round">
                                                <Line.InputBindings>
                                                    <MouseBinding Gesture="LeftClick" Command="{Binding DataContext.OccupyTrackCommand, RelativeSource={RelativeSource AncestorType=ContentPresenter, AncestorLevel=2}}"/>
                                                </Line.InputBindings>

                                            </Line>

有没有人幸运地创建了一条可以解决这些问题的自定义线,您可以在其中使用 LineCap 的“Flat”值,同时毫无问题地保留角落?编辑:只是为了澄清一下,我想我要求自定义实现线或线帽来解决所有这些问题,但是非常欢迎任何其他解决方案。

标签: wpflinecap

解决方案


我想出的解决方案是针对我的项目的,但我想无论如何我都会发布它,以防它帮助将来遇到此线程的任何人。

private void SetLineCaps() {

        if (LineCoords.Count == 1) {
            LineCoords[0].StartLineCap = "Flat";
            LineCoords[0].EndLineCap = "Flat";
            return;
        }
        foreach (var currentCoord in LineCoords) {
            foreach (var compareCoord in LineCoords) {


                if(currentCoord == compareCoord) continue;
                if ((compareCoord.X1 == currentCoord.X1 && compareCoord.Y1 == currentCoord.Y1)
                    || (compareCoord.X2 == currentCoord.X1 && compareCoord.Y2 == currentCoord.Y1)) {
                    currentCoord.StartLineCap = "Round";
                }
                if ((compareCoord.X1 == currentCoord.X2 && compareCoord.Y1 == currentCoord.Y2 )
                    || (compareCoord.X2 == currentCoord.X2 && compareCoord.Y2 == currentCoord.Y2)){ 

                    currentCoord.EndLineCap = "Round";
                }
            }
        }
    }

基本上我最终不得不做的是检查每条线的起点和终点,并检查起点或终点是否触及该特定线列表的任何其他点。例如,如果我有一条有 3 条线的轨道,它会检查是否有任何线端接触,如果是,它将特定的线帽设置为“圆形”,否则保持“平坦”。然后我将我的 StartLineCap 和 EndLineCap 限制在这些值上,一切都按预期工作。如果您想了解我如何处理出血颜色,请参阅我关于 z-index 的其他帖子。


推荐阅读