Getting value of individual box-shadow when set to multiple values - javascript

Trying to get an answer to a recent question, I tried to parse the box-shadow of an element, that had been set as
div {
box-shadow: 0 0 0 5px green, 0 0 0 10px #ff0000, 0 0 0 15px blue;
}
I expected to get that string, do an split(",") on it, and get the array of box-shadows. (with 3 elements)
My problem is that I get the string as
"rgb (0, 255, 0) 0 0 0 5px, rgb (255, 0, 0) 0 0 0 10px, rgb (0, 0, 255) 0 0 0 15px"
And of course when I split that I get a mess.
Is there an easier way to get the values of the individual box-shadows ?

you can try three separate statments
document.getElementById('the-element-id').style['boxShadow']
or do the split but use "px, " as the separator and add the "px" back to all values of the array except the last one
var string ="rgb (0, 255, 0) 0 0 0 5px, rgb (255, 0, 0) 0 0 0 10px, rgb (0, 0, 255) 0 0 0 15px";
var array= string.split("px, ");
var length = array.length;
for (var i=0; i<length; i++) {
if (i != length - 1){
array[i] = array[i] + "px";
}
console.log(array[i]);
}
jsFiddle
[EDIT]
I just realized this won't work if the last value of the box shadow is 0 (ie 15px 0 0 0, rgb)
here's the alternative in that case split on ", rgb" and add "rgb" back to all the values of the array except the first one:
var string ="rgb (0, 255, 0) 0 0 0 5px, rgb (255, 0, 0) 0 0 0 10px, rgb (0, 0, 255) 0 0 0 15px";
var array= string.split(", rgb");
for (var i=0; i<array.length; i++) {
if (i != 0 ){
array[i] = "rgb" + array[i];
}
console.log(array[i]);
}
jsFiddle

Related

2D array replacing values according conditions

I got a 10 x 10 array with the following values:
[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
In this 2D array, I have to randomly choose six values of 0, either horizontally or vertically (also random) and replace them with the value 6.
I've done this with the following code:
function tekenGrootstSchip(bord) {
rand = Math.floor((Math.random() * 10));
rand2 = Math.floor((Math.random() * 10));
directie = Math.floor((Math.random() * 2));
counter = 0;
if (directie == 0) {
for(y = rand2; y < 10; y++) {
if(counter < 6) {
bord[rand][y] = 6;
counter++;
}
}
for(y = rand2; y > 0; y--) {
if(counter < 6) {
bord[rand][y] = 6;
counter++;
}
}
} else {
for(x = rand; x < 10; x++) {
if(counter < 6) {
bord[x][rand2] = 6;
counter++;
}
}
for(x = rand; x > 0; x--) {
if(counter < 6) {
bord[x][rand2] = 6;
counter++;
}
}
}
}
After doing this for the value 6, I also have to do this for the value 4. The rules for value 4 are a bit different however. You can't place a 4 on a 6, neither can you place a 4 next to a 6. And the value 4 only takes four places (so 4x1, while a 6 is 6x1)
So if my randomly generated direction is horizontal, my bord[x-1][y], bord[x][y] and bord[x+1][y], with x and y initialized at the random value, with y going up to y+1, y+2, y+3, y+4 (4x1). All these values have to be checked against == 0, if true, replacing the zeroes with fours can be initialized otherwise not. If so, I have to generate a new [x][y] and check these conditions again until I can change four zeroes in my 2D array succesfully.
Although I have a general idea of implementing this, I would have a bug that, if for instance one null-value would be replaced with a four, but the one next to it can't be replaced since it's next to a != 0 value, I would be stuck with a "illegal" four.
If anyone could help me out in the right direction I would appreciate it.
feasibility
We can (trivially) show that whatever the 6 configuration chosen, we can always put the 4s.
Indeed, the maximal cover area of a 6 is 9 (a 3x3 square)
000
060
000
(we can't put a 4 in the border surrounding the 6).
So a bound for the maximal 6 configuration covered area is 6*9=54
000000xxxx
060060xxxx
000000xxxx
000000xxxx
060060xxxx
000000xxxx
000000xxxx
060060xxxx
000000xxxx
xxxxxxxxxx
and we can put as many 4 in the squares containing 'x' (which is way more than 4)
6-generation
Let's assume the board is indiced as follow:
0 1 2 3 ... 9
10 11 12 ... 19
...
90... 99
let x towards the bottom and y to the right
A square holding value id can be found at (x,y)=((id - id%10)/10, id%10) and reciprocally
id:(x,y)->x*10+y
So we will only consider numbers between 0 and 99 (since we can find back their associated position(x,y) in the grid)
I will use the copy-pasted below getRandomInt taken shamelessly from mdn
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
}
Finally we can draw between 0 and 99. If number already exists then discard it, otherwise take it
let indices = new Set
while(indices.size < 6){
let idx = getRandomInt(0,99)
if(!indices.has(idx)){
indices.add(idx)
}
}
return [...indices]
4-generation
We can apply the same stragy as before: draw a random number between 0 and 99 and discard it as long as it is not valid, until 4 valid positions are found
build the invalid set due to the 6 positionned
let invalids = new Set
indices.forEach(idx=>{
let [x,y] = [(idx - idx%10)/10, idx%10]
//add the adjacent squares
for(let i = -1; i<=1; ++i){
for(let j = -1; j<= 1; ++j){
if( 0<=x+i<10 && 0 <= y+j < 10){//if the cell in the board....
invalids.add( (x+i)*10 + y+j )
}
}
}
})
draw except from the invalid set
let out = []
while(out.length < 4){
let idx = getRandomInt(0,99)
if(!invalids.has(idx)){
invalids.add(idx)
out.push(idx)
}
}
return out
That approach may be not that efficient in worst case: we would have about 54% probability of drawing an invalid number!
We can thus consider an array of only the valid numbers, and draw from it
let valids = Array(100).fill(0).reduce((oks, x,i)=>{
if(invalids.has(i)) return oks
return oks.push(i),oks
},[])
//take numbers from that array
let out = []
for(let i = 0; i<4; ++i){
let idx = getRandomInt(0,valids.length)
//notice that here we take the elem from valids
//not just the idx from getRandomInt
out.push(valids[idx])
//and we takeout the element from valids
valids.splice(idx, 1);
}
return out

increase and decrease number in loop with logical operators

I was looking at this question and notice the way the loop
for( i=0; i < 1<<24; i++) {
r = (i>>16) & 0xff;
g = (i>>8) & 0xff;
b = i & 0xff;
colour = "rgb("+r+","+g+","+b+")";
}
increases the numbers and then "stuck" them to 0 with & 0xFF
So basically as I understood the value of, e.g, b will increase till it's 255 and then will result always 0.
I was wondering if there is a similar way to let the value of a variable increase to 255 and then decrease gradually from 255 to 0.
loop execution example of what I mean:
...
255, 254, 0
255, 255, 0
255, 254, 0
255, 253, 0
...
255, 2, 0
255, 1, 0
255, 0, 0

Centering of binary matrix for OCR

I'm reading characters from an image into 20x20 chunks to perform optical character recognition (OCR) and am wondering how to implement the best way of centering the binary data matrix.
For example, the character h might be converted into the following one-dimensional array (spaces and newlines added for clarity):
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
As far as I know, there are two alternatives:
Center of mass
var mass = 0,
sum = {
x: 0,
y: 0
};
for(y = 0; y < size; y++) {
for(x = 0; x < size; x++) {
if(chunk[size * y + x]) {
sum.x += x;
sum.y += y;
mass++;
}
}
}
// diff center of mass and center of matrix
var diff = {
x: Math.round((size / 2) - (sum.x / mass)),
y: Math.round((size / 2) - (sum.y / mass))
};
// move 1's accordingly
Question is how to handle if this type of centering causes any of the 1's to be placed outside of the chunk and therefore corrupting the data?
Bounding box
Calculate center of min(x, y) and max(x, y) and diff with center of matrix.
Which of these would yield the best (most consistent) results if the input characters are randomly distorted (slightly) in both dimensions?
The resulting chunk is used in training a multi-layer perceptron (MLP) neural network, if that helps.
Ended up using the bounding box method:
var min = {
x: size,
y: size
};
var max = {
x: 0,
y: 0
};
for(y = 0; y < size; y++) {
for(x = 0; x < size; x++) {
if(chunk[size * y + x]) {
if(min.x > x)
min.x = x;
if(min.y > y)
min.y = y;
if(max.x < x)
max.x = x;
if(max.y < y)
max.y = y;
}
}
}
var diff = {
x: Math.floor((size / 2) - (min.x + (max.x - min.x) / 2)),
y: Math.floor((size / 2) - (min.y + (max.y - min.y) / 2))
};
// move 1's accordingly

Capture multiple RGB values

I have a gradient applied to an element and I'm trying to get the RGB values from the background image using regexp.
#gradient {
background: linear-gradient(to right, rgba(255,0,0,1) 0%, rgba(0,0,255,1) 100%);
}
var elm = document.getElementById("gradient");
var elementColor = getComputedStyle(elm).backgroundImage;
// elementColor = "linear-gradient(to right, rgb(255, 0, 0) 0%, rgb(0, 0, 255) 100%)";
var first = elementColor.match(/rgb\((.*)\)/)[0];
var second = elementColor.match(/rgb\((.*)\)/)[1];
Using /rgb\((.*)\)/ doesn't work, because it returns
"rgb(255, 0, 0) 0%, rgb(0, 0, 255) 100%)"
And I'm guessing that's because there are parenthesizes occuring twice. How do I fix this? So that it returns
"255,0,0", "0,0,255"
Your regexp doesn't work because .* matches ) as well - as such if we modify it to [^\)]* it becomes what you're after:
var input = "background: linear-gradient(to right, rgba(255,0,0,1) 0%, rgba(0,0,255,1) 100%);";
var array = input.match(/rgba\([^\)]*\)/gi);
for (var i=0; i<array.length; i++)
console.log(array[i].match(/\((.*)\)/)[1]);
http://jsfiddle.net/4z8Ly/2/
Regular expressions are hard. Complex regular expressions with multiple capture groups should be avoided unless they are clearly the most practical way of parsing something.
It is not clear to me they are, in this scenario. I would:
rgb(255, 0, 0) 0%, rgb(0, 0, 255) 100%)
1- Remove the parenthesis from the expression
string = string.replace(/[()]/g, '');
// "rgb255, 0, 0 0%, rgb0, 0, 255 100%"
2- Split on rgb:
parts = string.split('rgb');
// ["", "255, 0, 0 0%, ", "0, 0, 255 100%"]
3- The first element will always be empty, so get rid of that:
parts.shift()
// ["255, 0, 0 0%, ", "0, 0, 255 100%"]
4- Split each element by /,? / (optional comma, then a space):
parts[0].split(/,? /g)
// ["255", "0", "0", "0%", ""]
There you have your values, and we only needed two dead simple regular expressions.
I wanted to use a single regexp to avoid using multiple lines of code to get the job done, but it seems that what I want to do is not possible with a single regexp.
And I came to understand that you can't capture (but match) if you're using g flag.
I've solved the problem with a one-liner.
elementColor.match(/\(\d+, \d+, \d+\)/g)[0].replace(/[( )]/g, "");
// "linear-gradient(to right, rgb(255, 0, 0) 0%, rgb(0, 0, 255) 100%)" -> "(255, 0, 0)" -> "255,0,0"

Run trough one rgba to another based on percentage

Let's say i have this both rgba codes:
rgba(150, 160, 255, 1) and rgba(195, 0, 0, 1)
I want to pass from one to another by a 0/100 percentage.
0% will be rgba(150, 160, 255, 1)
100% will be rgba(195, 0, 0, 1)
I'm trying to make a HeatMap with this.
How can i determinate what rgba will be at let say... 30%!?
For each value x in your code:
x = min_x + (max_x - min_x)*percentage/100
(Note: max_x can be smaller than min_x)
For each component, you just have to do start+(end-start)*percentage
So for your 30% you'd have:
red = 150 + (195 - 150) * 0.3 = 205.5
green = 160 + (0 - 160) * 0.3 = 112
blue = 255 + (0 - 255) * 0.3 = 178.5
alpha = 1 + (1 - 1) * 0.3 = 1
Your final colour will therefore be rgba(206, 112, 179, 1)

Categories

Resources