Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How can I rotate a gradientrect diagonally properly?

I have a gradientRect as the back of my clockface svg. I want it to be rotated 45 degrees diagonally so the gradient goes from the top left to the bottom right not side to side. I've tried wrapping it in a g container

 

  <g transform="rotate(45)">
    <gradientRect id="bg" width="100%" height="100%" />
  </g>



#bg {
  gradient-type: "linear";
  gradient-x1: "0";
  gradient-y1: "50";
  gradient-x2: "0";
  gradient-y2: "100%-50";
  gradient-color1: "magenta";
  gradient-color2: "red";
}

 

It rotates the gradientrect but moves it out of place. I also need it to cover the whole screen. Any idea the best approach to have a diagonal linear gradient? Thanks!

Best Answer
0 Votes
26 REPLIES 26

I think a rect that size is too big to rotate. You may need to investigate BarbWire's suggestion of assembling smaller rects.

If you only want angles that are multiples of 45 deg, you can do it using a 336x336.

Peter McLennan
Gondwana Software
Best Answer
0 Votes

Bildschirmfoto.pngIt's definitely a matter of size!
I just ran a little test with rotating on tap. The big gradientRect got ugly cropped, while a 336x336 can even be rotated with smoothSecond angle without any problems.
So you might test out where the size-limit is or go with a combination of small rects rotated together in one group

Best Answer
0 Votes

If you really need to cover all the secreen:
I now tested with 4 gradientRects (width: 210, height: 210) in the rotated group
1 set at (0,0)
2 set at (0,-h)

3 set at (-w,0)

4 set at (-w,-h)
This rotates without getting smashed, but can show 1px gaps depending on rotation angle, so you'd need to overlap them.
Making the gradient-quartett looking like one gradient would be another challenge.

Best Answer

@SunsetRunner and @Gondwana Tnx for help me! Finally I used a "merge" between real rotation and collision points to set x1, y1, x2, y2 and rotation angle and it's working!

 

Here's the code:

 

common/utils.js

function degreesToRadians(degrees){
  var pi = Math.PI;
  return degrees * (pi/180);
}

function opossiteAngle(angle){
  var opposite;
  if (angle == 0) {
    opposite = 180; // or -180 as you wish
  } else {
    if (angle > 0) {
      opposite = angle - 180;
    } else {
      opposite = angle + 180;
    }
  }
  return opposite;
}

function calculateCoords(width, height, degrees){
  let x0 = width / 2;
  let y0 = height / 2;

  let vx = Math.cos(degreesToRadians(degrees - 90));
  let vy = Math.sin(degreesToRadians(degrees - 90));

  //potential border positions
  let ex = vx > 0 ? width : 0;
  let ey = vy > 0 ? height : 0;

  //check for horizontal/vertical directions
  if (vx == 0) {
      return [x0, ey];
  }

  if (vy == 0) {
      return [ex, y0];
  }

  // in general case find times of intersections with horizontal and vertical edge line
  let tx = (ex - x0) / vx;
  let ty = (ey - y0) / vy;

  // and get intersection for smaller parameter value
  if (tx <= ty) {
      return [ex, y0 + tx * vy];
  }

  return [x0 + ty * vx, ey];
}

export function calcColPts(width, height, degrees){
  let pointOne = calculateCoords(width, height, degrees);
  pointOne = [Math.ceil(pointOne[0]), Math.ceil(pointOne[1])];
  let pointTwo = calculateCoords(width, height, opossiteAngle(degrees));
  pointTwo = [Math.ceil(pointTwo[0]), Math.ceil(pointTwo[1])];
  return [pointOne, pointTwo];
}

 

app/index.js

messaging.peerSocket.onmessage = evt => {
  if (evt.data.key === "degreeGradient" && evt.data.newValue) {
    let degrees = JSON.parse(evt.data.newValue);
    document.getElementById("gGradRectangle").groupTransform.rotate.angle = (degrees <= 90) ? 90 : (degrees <= 180) ? 180 : (degrees <= 270) ? 270 : 359;
    degrees = (degrees <= 90) ? degrees : (degrees <= 180) ? degrees - 90 : (degrees <= 270) ? degrees - 180 : degrees - 270;   
    let points = util.calcColPts(336, 336, 90 - degrees);
    let x1 = Math.min(points[0][0], points[1][0]);
    let y1 = Math.min(points[0][1], points[1][1]);
    let x2 = Math.max(points[0][0], points[1][0]);
    let y2 = Math.max(points[0][1], points[1][1]);
    document.getElementById("gradRectangle").gradient.x1 = x1;
    document.getElementById("gradRectangle").gradient.y1 = y1;
    document.getElementById("gradRectangle").gradient.x2 = x2;
    document.getElementById("gradRectangle").gradient.y2 = y2;
  }
}

 

resources/index.view

<svg id="rectangleRoot">
    <g id="gGradRectangle" transform="translate(50%, 50%)">
      <gradientRect id="gradRectangle" x="-168" y="-168" width="336" height="336"
        gradient-type="linear"
        gradient-x1="168" gradient-y1="0"
        gradient-x2="168" gradient-y2="336"
        gradient-color1="white"
        gradient-color2="black"/>
    </g>
  </svg>

 

Best Answer

Ah... interesting to see your use-case!

I hadn't fully understood before.

Nice, that you got it working 👍

Best Answer

I actually never would have thought of calculating the gradients coords (I#m so used to using groups for every transform).
That is an interesting approach. I like!

Best Answer
0 Votes

I wouldn't have thought of that either. That's great!

Peter McLennan
Gondwana Software
Best Answer