user3106516
user3106516

Reputation:

How to fill always from bottom to top in rotated svg rectange?

Currently I use linear gradient to fill rectangle in my html 5 project, svg code like this:

 <svg xmlns="http://www.w3.org/2000/svg" id="SvgjsSvg1352" version="1.1" width="100%" height="100%" xlink="http://www.w3.org/1999/xlink" style="position:relative;overflow:hidden;left:-0.4000244140625px;top:-0.399993896484375px;">
  <rect id="SvgjsRect6626" width="34" height="172" x="0.5" y="0.5" stroke="#000000" stroke-width="1" fill="url(#SvgjsLinearGradient6627)"/>
  <defs id="SvgjsDefs1353">
    <linearGradient id="SvgjsLinearGradient6627" x1="0" y1="1" x2="0" y2="0">
      <stop id="SvgjsStop6628" stop-opacity="1" stop-color="blue" offset="0.17221135029354206"/>
      <stop id="SvgjsStop6629" stop-opacity="1" stop-color="#cccccc" offset="0.17221135029354206"/>
      <stop id="SvgjsStop6630" stop-opacity="1" stop-color="#cccccc" offset="1"/>
    </linearGradient>
  </defs>
</svg>

As you can see, linear gradient fill the rectangle from bottom to top with start point (0, 1) and end point (0, 0). Problem is, sometimes the svg itself is rotated, and I still want to fill the rectangle from bottom to top and to keep the top in the same horizontal line.

Below is current what I have:

https://i.sstatic.net/8Jo9C.png

As you can see in the left side, rect is rotated, and linear gradient which fill the rect also rotated together with the rect, but what I expected is something below:

https://i.sstatic.net/CqHgu.png

So how can I get the correct fill start point and end point if svg is rotated?

Actually, I've tried gradient transform before, but it not works like I expected, for example, if rect rotate angle is 30, then linear gradient rotate angle should be similar to -10, please check svg code below:

<svg width="35" height="173" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
      <defs>
           <linearGradient gradientTransform="rotate(-10)" y2="0" x2="0" y1="1" x1="0" id="SvgjsLinearGradient6627">
                <stop offset="0.17221" stop-color="blue" id="SvgjsStop6628"/>
                <stop offset="0.17221" stop-color="#cccccc" id="SvgjsStop6629"/>
                <stop offset="1" stop-color="#cccccc" id="SvgjsStop6630"/>
           </linearGradient>
      </defs>
      <g>
          <title>Layer 1</title>
          <rect transform="rotate(30)" fill="url(#SvgjsLinearGradient6627)" stroke="#000000" y="0.5" x="0.5" height="172" width="34" id="SvgjsRect6626"/>
      </g>
 </svg>

Why this happen? or if I want to use gradient transform to resolve this problem, how could get the correct angle for linear gradient?

I also tried to calculate the correct start point and end point for the fill vector below:

        var a1 = Vector.create([0, 1]);
        var a2 = Vector.create([0, 0]);
        var b = Vector.create([0, 0.5]);
        var c1 = a1.rotate(-this.getRotation() * Math.PI / 180, b);
        var c2 = a2.rotate(-this.getRotation() * Math.PI / 180, b);
        this.__levelGradient.from(c1.elements[0], c2.elements[0]).to(c1.elements[1], c2.elements[1]);
        this._element.fill(this.__levelGradient);

The 'Vector' comes from library Sylvester(sylvester.jcoglan.com/api/vector.html), and library svg.js (www.svgjs.com/) also used here. I hope somebody can figure problems in my implementation or if you have any other ideas to implement this, show me the code how to calculate it.

@Michael Mullany, thanks for your help! I can not post images due to less reputation, this is really bad, otherwise I can show you some images.

Upvotes: 0

Views: 747

Answers (1)

Michael Mullany
Michael Mullany

Reputation: 31808

You can use a gradientTransform attribute on your gradient to undo the effects of the transform on the object. It's not particularly elegant, but it will work.

Upvotes: 0

Related Questions