WPF开发:如何实现Polyline折线仅填充下方区域的效果
问题描述
我正在使用C#/WPF做形状绘制相关测试,在窗口中创建了绑定Points坐标集的Polyline控件,代码如下:
<Window x:Class="PolylineTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Window.Resources> <Style TargetType="Polyline"> <Setter Property="SnapsToDevicePixels" Value="True"/> <Setter Property="Margin" Value="20"/> </Style> </Window.Resources> <Grid> <Polyline Fill="Red" Stroke="Black" StrokeThickness="2" FillRule="Nonzero" Points="1, 99 2, 99 3, 99 4, 99 5, 99 6, 99 7, 99 8, 99 9, 98 10, 98 11, 98 12, 98 13, 98 14, 98 15, 98 16, 98 17, 98 18, 98 19, 98 20, 97 21, 96 22, 96 23, 96 24, 96 25, 96 26, 96 27, 96 28, 96 29, 96 30, 96 31, 96 32, 95 33, 96 34, 94 35, 94 36, 94 37, 93 38, 93 39, 94 40, 93 41, 92 42, 93 43, 92 44, 91 45, 91 46, 91 47, 90 48, 89 49, 88 50, 87 51, 86 52, 85 53, 85 54, 83 55, 83 56, 84 57, 86 58, 86 59, 85 60, 85 61, 83 62, 81 63, 77 64, 80 65, 83 66, 78 67, 80 68, 77 69, 72 70, 78 71, 74 72, 76 73, 80 74, 78 75, 81 76, 78 77, 74 78, 73 79, 71 80, 73 81, 67 82, 74 83, 77 84, 73 85, 71 86, 74 87, 74 88, 71 89, 72 90, 72 91, 76 92, 72 93, 67 94, 68 95, 71 96, 72 97, 73 98, 73 99, 74 100, 76 101, 76 102, 77 103, 74 104, 78 105, 77 106, 69 107, 68 108, 68 109, 65 110, 73 111, 71 112, 73 113, 76 114, 66 115, 66 116, 72 117, 73 118, 73 119, 77 120, 73 121, 73 122, 75 123, 77 124, 73 125, 76 126, 79 127, 74 128, 72 129, 74 130, 76 131, 73 132, 76 133, 76 134, 70 "/> </Grid> </Window>
运行后当前输出效果:
期望实现仅填充折线下方区域的效果:
尝试调整FillRule属性无法达到预期,请问是否可以通过Polyline实现该需求?
解决方案
无法直接通过原生Polyline的自带属性实现该效果,原因如下:
Polyline的Fill逻辑是自动将折线的起点和终点直接连线,形成闭合多边形后再填充,你当前的场景下起点坐标为(1,99),终点坐标为(134,70),两点直接连线后闭合区域会包含折线以上的部分,调整FillRule不会改变这个闭合逻辑,因此无效。
你可以通过追加边界点的方式实现需求,操作非常简单:
在你现有Points集合的末尾追加两个点即可:134,99(折线终点的X坐标+下边界Y值)、1,99(折线起点的X坐标+下边界Y值),修改后闭合的区域就刚好是折线到下边界之间的部分,填充后就是你要的效果。
修改后的Polyline代码示例:
<Polyline Fill="Red" Stroke="Black" StrokeThickness="2" FillRule="Nonzero" Points="1, 99 2, 99 3, 99 4, 99 5, 99 6, 99 7, 99 8, 99 9, 98 10, 98 11, 98 12, 98 13, 98 14, 98 15, 98 16, 98 17, 98 18, 98 19, 98 20, 97 21, 96 22, 96 23, 96 24, 96 25, 96 26, 96 27, 96 28, 96 29, 96 30, 96 31, 96 32, 95 33, 96 34, 94 35, 94 36, 94 37, 93 38, 93 39, 94 40, 93 41, 92 42, 93 43, 92 44, 91 45, 91 46, 91 47, 90 48, 89 49, 88 50, 87 51, 86 52, 85 53, 85 54, 83 55, 83 56, 84 57, 86 58, 86 59, 85 60, 85 61, 83 62, 81 63, 77 64, 80 65, 83 66, 78 67, 80 68, 77 69, 72 70, 78 71, 74 72, 76 73, 80 74, 78 75, 81 76, 78 77, 74 78, 73 79, 71 80, 73 81, 67 82, 74 83, 77 84, 73 85, 71 86, 74 87, 74 88, 71 89, 72 90, 72 91, 76 92, 72 93, 67 94, 68 95, 71 96, 72 97, 73 98, 73 99, 74 100, 76 101, 76 102, 77 103, 74 104, 78 105, 77 106, 69 107, 68 108, 68 109, 65 110, 73 111, 71 112, 73 113, 76 114, 66 115, 66 116, 72 117, 73 118, 73 119, 77 120, 73 121, 73 122, 75 123, 77 124, 73 125, 76 126, 79 127, 74 128, 72 129, 74 130, 76 131, 73 132, 76 133, 76 134, 70 134,99 1,99"/>
如果你的Points是动态绑定的数据源,不想修改原始坐标,可以额外实现一个IValueConverter,在绑定时自动计算并追加对应边界点,无需改动业务代码。
内容的提问来源于stack exchange,提问作者phibel
相关产品推荐
相关产品推荐

