개발/WPF2018. 4. 3. 17:31

WPF에서 점1에서 점2까지 그라데이션으로 선을 그리는 방법은 간단하다.

문제는 이 두 점이 계속 바뀌거나 움직이는 경우, 그라데이션이 제대로 먹지 않는다는 점이다. 그라데이션 방향이 뒤집히거나 시작과 끝 색이 같아져버리는 경우도 있다.

말 그대로 StartPoint에서 EndPoint방향으로 선형적으로 그라데이션을 주기 때문에 이 두 포인트가 어긋나면 이상한 그라데이션이 생긴다.


잘못된 예제:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<Grid>
    <Canvas>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="500" Y2="500">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="CYan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="250" Y2="500">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="CYan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="0" Y2="500">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="CYan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="0" Y2="250">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="CYan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="0" Y2="0">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="CYan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="250" Y2="0">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="CYan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="500" Y2="0">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="CYan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="500" Y2="250">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="CYan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
    </Canvas>
</Grid>

결과:

* 실제 이동시키지는 않고 가운데부터 팔방으로 선을 그려보았다.


알고보면 LinearGradientBrush는 선이 아니라 영역(예를 들어 Rectangle)을 그리는데 쓰는거라 선 그리는데 사용하기 애매하다. 어쨌건 다른 좋은 방법이 없기 때문에 만약 이런 식으로 선을 그리고 싶다면 StartPoint, EndPoint도 같이 바꿔줘야 한다.


올바른 예제:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<Grid>
    <Canvas>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="500" Y2="500">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="Cyan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="250" Y2="500">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="Cyan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="0" Y2="500">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="1,0" EndPoint="0,1">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="Cyan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="0" Y2="250">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="1,0.5" EndPoint="0,0.5">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="Cyan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="0" Y2="0">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="1,1" EndPoint="0,0">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="Cyan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="250" Y2="0">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0.5,1" EndPoint="0.5,0">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="Cyan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="500" Y2="0">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,1" EndPoint="1,0">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="Cyan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
        <Line StrokeThickness="20" X1="250" Y1="250" X2="500" Y2="250">
            <Line.Stroke>
                <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
                    <GradientStop Color="Red" Offset="0"/>
                    <GradientStop Color="Cyan" Offset="1"/>
                </LinearGradientBrush>
            </Line.Stroke>
        </Line>
    </Canvas>
</Grid>

결과:

* 이것이 원하던 형태의 결과이다. 가운데부터 팔방으로 그라데이션이 생긴다.


만약 Line의 X1, Y1, X2, Y2를 바인딩 했다면 StartPoint, EndPoint도 바인딩하는 것이 좋다.

예제:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public Point LineGradientStartPoint
{
    get
    {
        Point p = new Point();
        if(srcNode != null && dstNode != null)
        {
            if (srcNode.X < dstNode.X)
                p.X = 0;
            else if (srcNode.X > dstNode.X)
                p.X = 1;
            else
                p.X = 0.5;
 
            if (srcNode.Y < dstNode.Y)
                p.Y = 0;
            else if (srcNode.Y > dstNode.Y)
                p.Y = 1;
            else
                p.Y = 0.5;
        }
        return p;
    }
}
 
public Point LineGradientEndPoint
{
    get
    {
        Point p = new Point();
        if (srcNode != null && dstNode != null)
        {
            if (srcNode.X < dstNode.X)
                p.X = 1;
            else if (srcNode.X > dstNode.X)
                p.X = 0;
            else
                p.X = 0.5;
 
            if (srcNode.Y < dstNode.Y)
                p.Y = 1;
            else if (srcNode.Y > dstNode.Y)
                p.Y = 0;
            else
                p.Y = 0.5;
        }
        return p;
    }
}

X1와 X2, Y1과 Y2를 비교해 작은 쪽을 0, 큰 쪽을 1로 놓으면 그라데이션이 그에 맞춰 그려진다.

Posted by Maverick Unlimited