decrease a radius by 10% using Index - Jquery - javascript

I have 10 sets of data coming in, and I need to set a radius for the first one to be the largest and then decrease by 10%.
my index comes in like: 1, 2, 3, 4, 5....
I am taking the index and dividing it by 1
var radiusTest = 1 / (index);
circleRadius = radiusTest * 100
Then I am multiplying it by 100, it is close to what I need but it does not degrade as nicely as I would like. Having each radius decrease by 10% is what I am looking for, not sure the best way of setting it up?

I think you are going for something like this:
var radiusTest = 1 - index * .1;
circleRadius = radiusTest * 100

So you have a value starting at 100% and decreasing in equal amounts over 10 iterations, or by 10%. Here is a way to implement this in JavaScript.
var steps = 10,
step,
stepSize = 1/steps,
radii = [];
for(step = 0; step <= steps; step++) {
radii[step] = (1-(stepSize * step)) * 100;
}
The array radii should contain:
[100, 90, 80, 70, 60, 50, 40,30,20, 10, 0]
You can mess with the constants to see different steps and step sizes.

Related

Represent a number with a color, difference not enough for percentage based rgb

I have an array (1200 values) of numbers
[123, 145, 158, 133...]
I'd like to have a div for each value with a background color from red to green, red being the smallest number and green the largest.
The base setup looks like this: (templating with vuejs but unrelated to the problem)
const values = [123, 145, 158, 133...]; // 1200 values inside
const total = values.length;
<div
v-for="(val, i) in values"
:key="i"
:style="{backgroundColor: `rgb(${(100 - (val*100/total)) * 256}, ${(val*100/total) * 256}, 0)`}">
{{val}}
</div>
I'm not a maths specialist but since all my numbers are around 100, the rgb generated is the same. (around 12% yellowish color)
How can I give more weight to the difference between 137 and 147?
EDIT: final formula:
:style="{backgroundColor: `rgb(${(256/(maxValue-minValue) * (boule-maxValue) - 255)}, ${(256/20 * (boule-maxValue) + 255)}, 0)`}"
Checkout this post: https://stats.stackexchange.com/questions/70801/how-to-normalize-data-to-0-1-range.
Basically you want to linearly rescale your values to another interval. You need your current min and max values from the array. Then define the new min' and max' which are the limits of the new interval. This would be [0, 255] in your case.
To do the transformation use the formula:
newvalue= (max'-min')/(max-min)*(value-max)+max'
As an example:
If your min value is 127 and max is 147, and you want to map 137. Then:
256/20 * (137-147) + 255 which results in 127.
If you want to map 130. Then:
256/20 * (130-147) + 255 = 37.4.
It really depends on what meaning those values actually have
However, you can try this: if your values are always bigger than 100 and always less than 150 (you can choose these number of course) you can "stretch" your values using the values as minimum and maximum. Let's take 137 and 147 as examples:
(val-min) : (max-min) = x : 255
(137-100):(150-100) = x:255 -> 37:50 = x:255 -> 188
(147-100):(150-100) = x:255 -> 47:50 = x:255 -> 239
That is for the math. In the end, this is the calculation:
newValue = (val-min)*255/(max-min)
where min and max are your chosen values.
You could take a kind of magnifier for a range of data. In this example, the values between 20 and 30 are mapped to a two times greater range than the outside values inside of an interval of 0 ... 100.
function magnifier(value, start, end, factor) {
var middle = (start + end) / 2,
size = (end - start) * factor / 2,
left = middle - size,
right = middle + size;
if (value <= start) return value * left / start;
if (value <= end) return (value - start) * factor + left;
return (value - end) * (100 - right) / (100 - end) + right;
}
var i;
for (i = 0; i <= 100; i += 5) {
console.log(i, magnifier(i, 20, 30, 2));
}
.as-console-wrapper { max-height: 100% !important; top: 0; }

Javascript: Set variable to either 1 or -1

I'm trying to get an object that moves in a different direction when you click on it, and each time you click on it it goes faster. I have it almost functioning, but I can't get the program to exclude 0 or do only -1 or 1; I can only do a random number between -1 and 1. This means that if it hits zero, it can't progress.
(The following code is built with a Javascript engine called "Crafty". Non-javascript parts are commented as best as I can.)
Crafty.init(400,320, document.getElementById('game')); // Creates canvas
// Create variables
var speed = 10;
var min = -1;
var max = 1;
// Create a 32px by 32px red box
var square = Crafty.e('2D, Canvas, Color, Mouse, Motion')
.attr({x: 50, y: 50, w: 32, h: 32})
.color('red')
// When the red box is clicked, move it in a random direction. Make it go faster each time.
.bind('Click', function(MouseEvent){
speed *= 2;
var vel = square.velocity();
var direction = ((Math.random() * (max - min)) + min);
vel.x;
vel.y;
vel.x = (speed *= direction);
vel.y = (speed *= direction);
});
Change to this line
var direction = (Math.random()) > .5 ? 1 : -1;
It really comes down to this line:
var direction = ((Math.random() * (max - min)) + min);
If you store the acceptable values (-1 and 1) in an array, you can make the random choose one of those based on the length of the array. By storing the values in an array, you not only make the process simpler, but it is extensible because you can always add new values later, if desired.
function getRandom(){
var acceptable = [-1, 1];
// Get a random number from 0 to 1 (the length of the array, 2, will never be reached)
var direction = Math.floor(Math.random() * acceptable.length);
console.log(acceptable[direction]); // Choose either array element 0 or element 1
}
// Run this code snippet a few times and you'll see that you only get -1 and 1
getRandom();
getRandom();
getRandom();
getRandom();
You can also remove the two lines declaring the max and min variables as they are no longer needed.

Best way to generate random number between x and y but not between a and b

I have a canvas that is 1000x600px. I want to spawn sprites outside the canvas (but evenly distributed).
What is the best way to retrieve random values between (-500, -500) and (1500, 1100) but not between (0, 0) and (1000, 600)? I understand a while loop could be used to generate numbers until they are in range but that seems superfluous. Thanks.
If you want to generate a number between -500 and 1500, excluding 0 to 1000, you can just generate a number between 0 and 1000 ( 0 - -500 + 1500 - 1000).
If the number is less than 500, you subtract 500; if the number is greater or equal to 500, add 500.
Or, more generically:
function randomInt(outerMin, outerMax, innerMin, innerMax)
{
var usableRange = innerMin - outerMin + outerMax - innerMax,
threshold = innerMin - outerMin,
num = Math.floor(Math.random() * (usableRange + 1));
if (num < threshold) {
return num - threshold;
} else {
return num - threshold + innerMax;
}
}
randomInt(-500, 1500, 0, 1000);
For two-dimensional points you have to get more creative. First, you generate two points that ARE inside the forbidden area and then spread those values to the good areas:
function randomVector(outer, inner)
{
var innerWidth = inner.right - inner.left,
innerHeight = inner.bottom - inner.top,
x = Math.floor(Math.random() * (innerWidth + 1)),
y = Math.floor(Math.random() * (innerHeight + 1)),
midx = Math.floor(innerWidth / 2),
midy = Math.floor(innerHeight / 2);
if (x < midx) { // left side of forbidden area, spread left
x = x / midx * (inner.left - outer.left) - inner.left;
} else { // right side of forbidden area, spread right
x = (x - midx) / midx * (outer.right - inner.right) + inner.right;
}
if (y < midy) { // top side of forbidden area, spread top
y = y / midy * (inner.top - outer.top) - inner.top;
} else { // bottom side of forbidden area, spread bottom
y = (y - midy) / midy * (outer.bottom - inner.bottom) + inner.bottom;
}
// at this point I'm not sure how to round them
// but it probably should have happened one step above :)
return {
x: Math.floor(x),
y: Math.floor(y)
}
}
randomVector({
left: -500,
top: -500,
right: 1500,
bottom: 1100
}, {
left: 0,
top: 0,
right: 1000,
bottom: 600
});
Important
This works because the areas outside of your "forbidden" area are equal in their respective dimension, i.e. padding-top == padding-bottom && padding-left == padding-right.
If this will be different, the distribution is no longer uniform.
Generate a random number between 0 and 1000, if its over 500 add 500 (or 600 respectivly) if not negate it.
Instead of having a set of forbidden rectangles, you could calculate a set of allowed rectangles. To get a random position inside any allowed rectangle, you first choose a random rectangle and then a random position inside that chosen rectangle.
When the retangles don't have an equal size, you need to weight them by area, otherwise smaller rectangles will have a higher density than larger ones (a 200x100 rectangle needs to be 100 times as likely as a 10x20 rectangle).
Just generate those numbers between (0,0) and (1,1) and then use some linear function to do the mapping.
Otherwise, divide the area where you want the random coordinates to fall in rectangles. Let's say you obtain N such rectangles. Each of those rectangles may be populated through mapping the output of a random generator betweeen (0,0) and (1,1) to that rectangle (this is a linear mapping).

Generate axis scale

I am working on a project where I need to calculate some scale for slider. The user can define min, max and step.
You can find the code below:
var j = Math.round(cfg.max / cfg.step);
var l = (containerWidth / (j - 1));
for (var i = 0; i < j; i++) {
s.push('<span style="left:');
s.push(l * i);
s.push('px">');
s.push(cfg.step * (i + 1));
s.push('</span>');
}
Example: min=1 max=12 step=3
Generated scale: 3 6 9 12
Slider ticks: 1 4 7 10 12
I would like to know how I can generate ticks for slider.
Assuming your question can be rephrased like this:
Calculate n ticks for an arbitrary range with min x and max y
Then we can adapt the linear tick function from D3.js:
function calculateTicks(min, max, tickCount) {
var span = max - min,
step = Math.pow(10, Math.floor(Math.log(span / tickCount) / Math.LN10)),
err = tickCount / span * step;
// Filter ticks to get closer to the desired count.
if (err <= .15) step *= 10;
else if (err <= .35) step *= 5;
else if (err <= .75) step *= 2;
// Round start and stop values to step interval.
var tstart = Math.ceil(min / step) * step,
tstop = Math.floor(max / step) * step + step * .5,
ticks = [];
// now generate ticks
for (i=tstart; i < tstop; i += step) {
ticks.push(i);
}
return ticks;
}
This isn't exactly to your specifications - it generates a set of nicely-rounded ticks, often 1-2 more or fewer than tickCount:
calculateTicks(1, 12, 5); // [2, 4, 6, 8, 10, 12]
calculateTicks(0, 12, 4); // [0, 5, 10]
It's hard to come to an optimum solution here, but I think the D3 approach does it relatively well - in my opinion, I'd rather have the ticks 2, 4, 6, 8, 10, 12 for a range 1-12 than the ticks 1, 4, 7, 10, 12 that you suggest.
Working fiddle: http://jsfiddle.net/nrabinowitz/B3EM4/

Math equation for graph

I am working on a graphing class (in javascript) which uses canvas. This is just for experimental / learning purposes. Currently the graph scales correctly based on whatever height and width the canvas is set at. This is not a problem, and here is basically what I am doing to plot the correct coordinates [pseudo-code].
point[0] = [10, 15]
point[1] = [20, 10]
point[2] = [30, 20]
point[3] = [40, 15]
canvas width = 300
max x = 40
so for any given point:
position x = ( point[i][0] / max x ) * canvas width
simple enough. I get a ratio, then multiply it by the canvas width to plot it at the correct pixel.
The problem however, is coming up with an equation that would cause the minimum value of x to reside at 0 on the x coordinate of the graph, and the max value to be at the maximum point of the graph (which it already does because of the 1:1 ratio in my current equation). Currently the minimum value of x (10 in the example), resides at 75px in the x coordinate, because of the 1:4 ratio being multiplied to the canvas' width.
tldr / summary: I need to make a graph in which the minimum value is plotted at the beginning of the graph(0,0), and the maximum value plotted to the end.
try calculating a value for pixel-width-per-point first.
e.g.
widthPerPoint = canvasWidth / (maxX - minX)
then your position can be normalised to zero by subtracting the minimum value:
position = widthPerPoint * (point[i][0] - minX)
for your first example
widthPerPoint = 300 / (40 - 10) = 10
position = 10 * (point[i][0] - 10) = 10 * 0 = 0
and for the others:
point[0] = [10, 15] -> 0
point[1] = [20, 10] -> 100
point[2] = [30, 20] -> 200
point[3] = [40, 15] -> 300
at least I think that'll work....
Just loop over your points and record what you find (sorry, I can't do algorithm programming in JavaScript. pseudo-Python is so much easier):
minimum = [infinity, infinity, -1]
maximum = [-infinity, -infinity, -1]
for point in points:
if point.x > maximum.x and point.y > maximum.y:
maximum = [point.x, point.y, point.index]
if point.x < minimum.x and point.y < minimum.y:
minimum = [point.x, point.y, point.index]
if maximum.index == -1:
print 'No point is a maximum, so the points all lie in a horizontal line.'
maximum = [points[0].x, points[0].y, 0]
minimum = [points[0].x, points[0].y, 0]
You need to map linearly the range [min_x, max_x] to [0, width]. A point x = point[i][0] is mapped to
position(x) = width/(max_x - min_x) * (x - min_x).
Not sure I understand your question correctly. If so, this is the equation:
position x = (point[i][0] - min x) * canvas width / (max x - min x)
This way when point[i][0] is minimal (min x) your value is 0.0. and when it is maximal (max x) the value is canvas width, growing linearly.

Categories