I want to use the grayscale function but LESS keeps throwing this error and I don't see a mixin for grayscale or how to use it. Any help?
Error 148 Expected color in function 'grayscale'
img {
-webkit-filter: blur(2px) grayscale(1);
-moz-filter: blur(2px) grayscale(1);
-o-filter: blur(2px) grayscale(1);
-ms-filter: blur(2px) grayscale(1);
filter: blur(2px) grayscale(1);
}
Try the following. LESS is probably not recognizing grayscale(1) as a valid function for itself, but also not seeing is as a property value, so that is when you need to use string interpolation to get LESS to compile nicely.
img {
#filterString: ~"blur(2px) grayscale(1)";
-webkit-filter: #filterString;
-moz-filter: #filterString;
-o-filter: #filterString;
-ms-filter: #filterString;
filter: #filterString;
}
Related
I am attempting to calculate some statistics for pixel values using openlayers 6.3.1 & I am having an issue iterating over all pixels. I have read the docs for the pixels array that gets passed to the operation callback and it states:
For pixel type operations, the function will be called with an array
of * pixels, where each pixel is an array of four numbers ([r, g, b, a]) in the * range of 0 - 255. It should return a single pixel
array.
I have taken this to mean that the array passed contains all the pixels but everything I do seems to prove that I only get the current pixel to work on.
if(this.rasterSource == null) {
this.rasterSource = new Raster({
sources: [this.imageLayer],
operation: function (pixels, data) {
data['originalPixels'] = pixels;
if(!isSetUp) {
// originalPixels = pixels as number[][];
// const originalPixels = Array.from(pixels as number[][]);
// let originals = generateOriginalHistograms(pixels as number[][]);
isSetUp = true;
}
// console.log(pixels[0]);
let pixel = pixels[0];
pixel[data['channel']] = data['value'];
return pixel;
},
lib: {
isSetUp: isSetUp,
numBins: numBins,
// originalPixels: originalPixels,
// originalRed: originalRed,
// originalGreen: originalGreen,
// originalBlue: originalBlue,
generateOriginalHistograms: generateOriginalHistograms,
}
});
this.rasterSource.on('beforeoperations', function(event) {
event.data.channel = 0;
event.data.value = 255;
});
this.rasterSource.on('afteroperations', function(event) {
console.debug("After Operations");
});
I have realised that I cannot pass arrays through the lib object so I have had to stop attempting that. These are the declarations I am currently using:
const numBins = 256;
var isSetUp: boolean = false;
function generateOriginalHistograms(pixels: number[][]) {
let originalRed = new Array(numBins).fill(0);
let originalGreen = new Array(numBins).fill(0);
let originalBlue = new Array(numBins).fill(0);
for(let i = 0; i < numBins; ++i) {
originalRed[Math.floor(pixels[i][0])]++
originalGreen[Math.floor(pixels[i][1])]++;
originalBlue[Math.floor(pixels[i][2])]++;
}
return {red: originalRed, blue: originalBlue, green: originalGreen};
}
& they are declared outside of the current angular component that I am writing this in. I did have another question on this but I have since realised that I was way off in what I could and couldn't use here;
This now runs and, as it is currently commented will tint the image red. But the value of data['originalPixels'] = pixels; only ever produces one pixel. Can anyone tell me why this is & what I need to do to access the whole pixel array. I have tried to slice & spread the array to no avail. If I uncomment the line // let originals = generateOriginalHistograms(pixels as number[][]); I get an error
Uncaught TypeError: Cannot read properties of undefined (reading '0')
generateOriginalHistograms # blob:http://localhos…a7fa-b5a410582c06:6
(anonymous) # blob:http://localhos…7fa-b5a410582c06:76
(anonymous) # blob:http://localhos…7fa-b5a410582c06:62
(anonymous) # blob:http://localhos…7fa-b5a410582c06:83
& if I uncomment the line // console.log(pixels[0]); I get all the pixel values streaming in the console but quite slowly.
The answer appears to be change the operationType to 'image' and work with the ImageData object.
this.rasterSource = new Raster({
sources: [this.imageLayer],
operationType: "image",
operation: function (pixels, data) {
let imageData = pixels[0] as ImageData;
...
I now have no issues calculating the stats I need.
I'm trying to my grid system to LESS.
I'm using fractions as strings (there's a reason) and need to interpolate them in the calc() expression.
In Sass I can do this...
#mixin move($fraction: '1/1') {
position: relative;
left: calc(99.999999% * #{$fraction});
}
In LESS when I try this...
.move(#fraction: '1/1') {
#_fraction: ~'#{fraction}';
left: calc(99.999999% * #_fraction);
}
It ends up throwing a Cannot read property 'numerator' of undefined error.
Apparently LESS can tell it's a fraction but then it poops out.
Can any LESS pros enlighten me?
You need to escape multiplication, addition, division, and subtraction in LESS or it will try output the calculated result. When less sees * in your code, it is trying to multiply 99.999999% and #_fraction.
For example when LESS sees calc(5px + 5px); it will output left: calc(10px);. You can except it like this ~'calc(5px + 5px);'.
Try using this code.
.move(#fraction: '1/1') {
#_fraction: ~'#{fraction}';
left: calc(~'99.999999% *' #_fraction);
}
I am trying to make a mixin which evaluates both the parameters typ and compare values.
Say I have a mixin to create a CSS3 gradient with fallbacks for older browsers but if no start and/or end color is entered only output the background-color. In addition to checking all colors are being entered correctly I want to make sure that neither the start or end color is equal to the fallback color.
This is how I would like to write it using standard logic but I am not allowed to nest the guards together.
.gradient(#color, #start: 0, #stop: 0) when (iscolor(#color)) and (iscolor(#start)) and (iscolor(#stop)) and not ((#start = #color) and (#stop = #color)) {
background: #color;
background: -webkit-gradient(linear,left bottom,left top,color-stop(0, #start),color-stop(1, #stop));
additional-browser-specific-prefixes;
}
.gradient(#color, #start: 0, #stop: 0) when (default()) {
background-color: #color;
}
Essentially I want to do the following Javascript condition: if(iscolor(color) && iscolor(start) && iscolor(end) && (start !== color && end !== color)). Does anyone have any clue if this is possible?
Any ideas would be greatly appreciated.
Less guards should have the same implementation as CSS #media (this maybe only apply for the syntax??). I can not find examples for the #media, which use the kind of nesting for operators you try to use. So it is not possible for CSS #media and so also not possible for Less guards?
But, on http://mdn.beonex.com/en/CSS/Media_queries.html i found:
The not operator has a very low precedence. For example, the not is
evaluated last in the following query:
#media not all and (-moz-windows-compositor) { ... }
This means that the query is evaluated like this:
#media not (all and (-moz-windows-compositor)) { ... }
... rather than like this:
#media (not all) and (-moz-windows-compositor) { ... }
This should mean that you do not have to wrap in extra parentheses your conditions after the not keyword. The following code should work:
.gradient(#color, #start: 0, #stop: 0) when (iscolor(#color)) and (iscolor(#start) and not #start = #color) and (#stop = #color), but unfortunately this does not works as expected.
If the operator precedence of Less guards have to equal to the operator precedence of the CSS #media, this could be considered as a bug maybe.
update My above assumption was wrong, the not keyword will be applied on the whole media query (or guard) only, so not (a), not (b) make no sense at all. Also see: https://github.com/less/less.js/issues/2149
If all the above is truth, try to revert the conditions:
.gradient(#color, #start: 0, #stop: 0)
when (#start = #color) and (#stop = #color), not (iscolor(#color)), not (iscolor(#start)), not (iscolor(#stop)) {
background-color: #color;
}
.gradient(#color, #start: 0, #stop: 0)
when (#start = #color) and (#stop = #color), (iscolor(#color)=false), (iscolor(#start)=false), (iscolor(#stop)=false) {
background-color: #color;
}
.gradient(#color, #start: 0, #stop: 0) when (default()) {
background: #color;
background: -webkit-gradient(linear,left bottom,left top,color-stop(0, #start),color-stop(1, #stop));
additional-browser-specific-prefixes;
}
or try to use nested mixins as follows:
default(#a,#b,#c){
property: default;
}
.fallback(#a,#b,#c){
property: fallback;
}
.background(#a,#b,#c) when (#a>0) and (#b>0) and (#c>0)
{
.and(#a,#b,#c) when (#a=#c) and (#b=#c) {
.fallback(#a,#b,#a);
}
.and(#a,#b,#c) when (default()){
.default(#a,#b,#a);
}
.and(#a,#b,#c);
}
.background(#a,#b,#c) when (default())
{
.fallback(#a,#b,#c);
}
test0 { .background(0,1,1); }
test1 { .background(1,1,1); }
test2 { .background(2,1,1); }
test3 { .background(1,2,1); }
test4 { .background(1,1,2); }
I'm trying to write a mixin that returns a variable for converting px to em. I've toyed with a few things, but ultimately i'd like to call a mixin and get a return value similar to SASS's functions. Based on on return values here: http://www.lesscss.org/#-return-values, I can only define a variable once as a return value. Example:
Mixin
.px-to-emz( #size, #base: #font-size-base ){
#em: round( unit( (#size / #base), ~"em" ), 3 );
}
Call it:
.foo {
font-size: #em;
.px-to-emz(10, 16px);
height: #em;
.px-to-emz(200, 16px);
}
Fine, if you want to only return one variable, but if i want to return multiple variables I need to define new variable names. Here's what i'd ideally like to do
Mixin:
.px-to-ems( #size, #var: 'em', #base: #font-size-base ){
~'#{var}': round( unit( (#size / #base), ~"em" ), 3 );
}
Call it:
.foo {
font-size: #font-size;
.px-to-ems(10, 'font-size', 16px);
height: #height;
.px-to-ems(200, 'height', 16px);
}
#1
So far the best known solution for this problem is to put each mixin call into its own scope:
.px-to-ems(#size, #base: #font-size-base) {
#-: round(unit((#size / #base), em), 3);
}
.foo {
.-() {font-size: #-; .px-to-ems( 10, 16px)}
.-() {height: #-; .px-to-ems(200, 16px)}
.-;
}
Replace #- and .- with whatever identifiers you find suitable.
#2
The other way around is to use recently added (Less 1.6.x) property interpolation feature:
.px-to-ems(#property, #size, #base: #font-size-base) {
#{property}: round(unit((#size / #base), em), 3);
}
.foo {
.px-to-ems(font-size, 10, 16px);
.px-to-ems(height, 200, 16px);
}
It's more clean than #1 if you simply need to assign the "function" result to a property.
I'm trying to convert a negative variable in lesscss in to a positive:
#var: -100px;
.test {
height: #var * -1; // expect result to be 100px
}
But when I try and compile this code, I get 'unrecognized input' error.
Use the Abs function:
#var: -100px;
.test {
height: abs(#var);
}