NVI
NVI

Reputation: 15045

SVG: make a gradient to fill the whole shape for every angle given

Trigonometry problem

Given an angle between 0° and 90°, generate a SVG gradient that fills entire rectangle.

SVG gradients accept two control points rather than angle. Here is the code of the first square on the picture above:

<linearGradient x1="0" y1="0" x2="1" y2="0.5">

The problem is that the gradient doesn’t cover the entire square. I want to extend the gradient just enough to fill the shape entirely so the red triangle would be not visible. Here is an interactive demo (tested in Chrome, Firefox and Safari) to give you a better idea.


Solution in JavaScript:

function angleToVector(angle) {
    var od = Math.sqrt(2);
    var op = Math.cos(Math.abs(Math.PI/4 - angle)) * od;
    var x = op * Math.cos(angle);
    var y = op * Math.sin(angle);
    return {x: x, y: y};
}

For angle between -180° and 180°:

function angleToPoints(angle) {
    var segment = Math.floor(angle / Math.PI * 2) + 2;
    var diagonal = (1/2 * segment + 1/4) * Math.PI;
    var op = Math.cos(Math.abs(diagonal - angle)) * Math.sqrt(2);
    var x = op * Math.cos(angle);
    var y = op * Math.sin(angle);

    return {
        x1: x < 0 ? 1 : 0,
        y1: y < 0 ? 1 : 0,
        x2: x >= 0 ? x : x + 1,
        y2: y >= 0 ? y : y + 1
    };
}

There might be a simpler solution for this.

Upvotes: 3

Views: 453

Answers (1)

wdebeaum
wdebeaum

Reputation: 4211

So your question as I understand it is this: given a rectangle (whose top left corner is the origin O = (0, 0) and whose bottom right corner is D = (w, h)) and a line l through point O at angle a (with 0° <= a <= 90°), find the point P = (x2, y2) on l such that line DP makes a right angle with l.

If you draw the diagonal of the rectangle, OD, it completes a right triangle with the right angle at P. The angle of that diagonal is atan(h/w), and if you take the absolute difference of that from a (i.e. |atan(h/w) - a|), you'll get the angle in that right triangle at point O. Then you can take the cosine of that angle to get the distance between O and P along l as a proportion of the length of OD (the hypotenuse). You can multiply out the hypotenuse, and then just multiply that by cos(a) and sin(a) to get x2 and y2, respectively.

To summarize:

|OD| = sqrt(w*w + h*h)
|OP| = cos(|atan(h/w) - a|) * |OD|
x2 = |OP| * cos(a)
y2 = |OP| * sin(a)

Upvotes: 4

Related Questions