It is currently March 28th, 2024, 12:40 pm

Creating a bar shape with rounded ends...

Tips and Tricks from the Rainmeter Community
Post Reply
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Creating a bar shape with rounded ends...

Post by jsmorley »

This was discussed in another thread, but I thought it might be of enough general interest to placehold it here.

If you want to have a Bar meter with rounded ends, That isn't too hard. You can simply create an external BarImage of the bar you want, with rounded ends, and use BarBorder to force some number of left and right pixels of the image to always be displayed.

The disadvantage to this approach is that if the bar image is not a solid color, if for instance you want to have a gradient from green to red as the value grows, it won't work right. The "rounded" end that you define in BarBorder is simply cropped off and used, and you just won't get the effect you are looking for.

There is a way to emulate the Bar meter using the new Shape meter however, and to be honest it has some real advantages, some additional flexibility, that are worth exploring.

So first, let's look at an example skin:

Code: Select all

[Rainmeter]
Update=100
DynamicWindowSize=1
AccurateText=1

[Variables]
BarW=300

[MeasureLoop]
Measure=Loop
StartValue=0
EndValue=100

[MeterBar]
Meter=Shape
X=0
Y=0
Shape=Rectangle 0,0,#BarW#,20,10 |  Fill LinearGradient MyGradient1 | StrokeWidth 0
MyGradient1=90 | 225,225,225 ; 0.0 | 32,32,32 ; 1.0
Shape2=Rectangle 0,0,([MeasureLoop]*#BarW#/100),20,10 | Fill LinearGradient1 MyGradient2 | StrokeWidth 0
MyGradient2=180 | 50,184,50,255 ; 0.0 | 50,184,50,255 ; (0.5 + (100-[MeasureLoop])/100) | 219,213,42,255 ; (0.9 + (100-[MeasureLoop])/100) | 199,36,36,255 ; (1.0 + (100-[MeasureLoop])/100)
Shape3=Rectangle 0,0,([MeasureLoop]*#BarW#/100),20,10 | Fill LinearGradient MyGradient3 | StrokeWidth 0
MyGradient3=90 | 32,32,32,190 ; 0.0 | 225,225,225,1 ; 1.0
DynamicVariables=1
GIF.gif
So what is going on here... First, we are creating our bar shape using a simple rounded Rectangle in a Shape meter:

Rectangle 0,0,([MeasureLoop]*#BarW#/100),20,10

The "width" of the shape is based on the percentage that the current [MeasureLoop] measure's value is, related to the overall width we want, defined in #BarW# (300 pixels in this case). So as the measure value changes the rectangle shape will shrink and grow accordingly.

That gives us our bar shape with rounded ends. Much easier than using BarImage and BarBorder in this case.

Now the clever bit...

We are defining a horizontal gradient for the rectangle:

Code: Select all

MyGradient2=180 | 50,184,50,255 ; 0.0 | 50,184,50,255 ; (0.5 + (100-[MeasureLoop])/100) | 219,213,42,255 ; (0.9 + (100-[MeasureLoop])/100) | 199,36,36,255 ; (1.0 + (100-[MeasureLoop])/100)
Let's tear that apart and see what we are doing...

First we are defining a starting color of green at a shape percentage of 0.0. Then we want it to start transitioning to yellow, but not until we have hit at least 0.5, or 50%. We want entirely solid green until 50%. Now let's look at why we are using a formula in all of our "percentage" settings from here out.

The issue is that gradients are based on a percentage of the size of the shape. 0.25 would be 25% of the shape's width, and 1.0 would be 100% of the shape's width.

In this case we don't want that. We don't want the entire gradient effect, from green to red, when the shape is smaller, only when it is at 100%. So to get around that, we need to define the gradient so it is based on the "final" width, the width when the measure's value and thus the size of the shape is at 100%.

So that means that the percentages we use are going to be more than 100% most of the time, changing as the size of the shape changes. We need a calculation that allows us to add the desired percentage (0.5 for the end of green, 0.9 for the midpoint of yellow, and 1.0 for the end of red) to how much is "left over" to get the measure value to 100%. So if you think about it we want the gradient to be "static" at 100% of the final shape width, while the shape itself changes based on the measure value.

So when we want our second green definition to end at 0.5 or 50%, we can't just use 0.5. That is 50% of the current shape's width, which is constantly changing. We need to add that to what is left over when we subtract the measure's percentage from 100%. (0.5 + (100-[MeasureLoop])/100) will get that difference, divide by 100 to turn it into an actual percentage, and add it to 0.5.

So what this does is create a "static" gradient (t's actually not static at all, but simulates being static) that will have 0.5 or 50% always exactly in the middle of the overall size the shape "can be", rather than what it "is". That is how you achieve the effect of "revealing" the gradient as the shape's size changes, which is the effect you are going for.
Post Reply