I'm trying to export files from Adobe InDesign to basic HTML + CSS.
A user can select some text and change the text colour. Using the InDesign SDK I can fetch the RGB values for that colour and in the CSS file declare color: rgb(R,G,B) which works perfectly fine.
You can also change the text tint value. Upto now I was just taking the tint value, converting it to the range 0-1 and in the CSS putting an entry as color: rgba(R,G,B,Tint)
During testing I realized that tint = 0 should actually mean white text, but it didn't show on the HTML because A (in RGBA) = 0 means transparent!!!
Anyone knows how to handle tint values in CSS?
There is no tint, hue,saturation or brightness in CSS. You should "build" these properties into your RGB color. To apply tint on your RGB, use this expression:
when R,G,B are from 0..255, tint from 0..1
new R = tint*R + (1-tint)*255;
new G = tint*G + (1-tint)*255;
new B = tint*B + (1-tint)*255;
Tint is the convex combination of your color and white color. See Wikipedia.
Ivan Kuckir's solution is correct, I'm just adding an explanation as it might help someone later.
Explanation - Tint means adding white to a colour.
Tint %X implies = there is a mixture of white and your color where white is (100-X)% of the mixture and your color constitutes X% in the mixture.
Thus, say for color Red (255,0,0) and tint .6 => Create a mixture with 60% RED and 40% WHITE.
Hence, the resulting mixture should be something like -
.6 * RED + .4 * WHITE
This can be followed for mixing any 2 colors (C1, C2) in a certain proportion = p:q
new R = p/(p+q) * R1 + q/(p+q) * R2
new G = p/(p+q) * G1 + q/(p+q) * G2
new B = p/(p+q) * B1 + q/(p+q) * B2
For tint, (R2,G2,B2) = (255,255,255)
new R = tint*R + (1-tint)*255;
new G = tint*G + (1-tint)*255;
new B = tint*B + (1-tint)*255;
Unfortunately there's no way of doing text tint using plain CSS.
Colors in CSS can be specified by the following methods:
Hexadecimal colors - #RRGGBB
RGB colors - rgb(red, green, blue)
RGBA colors - rgb(red, green, blue, alpha)
HSL colors - hsl(hue, saturation, lightness)
HSLA colors - hsl(hue, saturation, lightness, alpha)
Predefined/Cross-browser color names - 'red','aqua', etc
Source
So you would need a JS script for that.
(See Ivan Kuckir's answer);
You can use CSS variables to do this - see this example. Define R, G, B and tint as four different CSS variables.
body {
--content-R: 100%;
--content-G: 0%;
--content-B: 0%;
--text-tint: 0.5;
}
You can then use this as:
.content {
color: rgb(
calc(var(--content-R) * var(--text-tint) + 100% - 100% * var(--text-tint)),
calc(var(--content-G) * var(--text-tint) + 100% - 100% * var(--text-tint)),
calc(var(--content-B) * var(--text-tint) + 100% - 100% * var(--text-tint))
);
}
Note:
It only works if the colors are defined using percentages 0% to 100% (instead of integers 0 to 255). This is because the rgb function will accept floating point numbers for percentages. Trying to use integer 255 would have a calculated value of say 255 * 0.5 which is 127.5 which is not a valid integer color value (so the rgb color won't work). You also need to be careful with the limitations of the calc function.
You can independently vary the colours and tints on child elements using the cascading styles (it didn't work when I put the rgb calc into its own body CSS variable).
I only tried this on Chrome 65 - other browsers may act differently!
It might have negative performance implications on the CSS style engine within the browser?
.Less has a very easy implementation for this.
After you add the .less files you can darken and lighten at will
.element{
color:darken(#444,20%);
// or
// color: lighten(#444,50%);
}
taken from less.org
// Variables
#link-color: #428bca; // sea blue
#link-color-hover: darken(#link-color, 10%);
Related
Can you check how similar a code is to another colour, If e.g. 0xFFFFFF is similar to 0xFBFBFB then change colour.
im not sure how the colour code works, so if you know a tip on the code, can you please share
A simple method to determinate proximity between colors, is to do so for each color component.
In AS3, a color is a number containing 3 components : red, green and blue (There's sometimes a fourth component for transparency - alpha)
Each component is contained in 1 byte, for a value of 0 to 255. (0x00 to 0xFF)
Here is a way to get each color component from the color itself :
var red:int = (color & 0xFF0000) >>> 16;
var green:int = (color & 0xFF00) >>> 8;
var blue:int = color & 0xFF;
Once you have the color components of each color, you can compare them 2 by 2, and combine the results:
var red_proximity = Math.abs(red1 - red2);
var green_proximity = Math.abs(green1 - green2);
var blue_proximity = Math.abs(blue1 - blue2);
var color_proximity = red_proximity + green_proximity + blue_proximity;
The result will be a number between 0 and 765; 0 meaning the color are exactly the same, and 765 meaning that they are completely differents.
(Note that I am using Math.abs() to ensure that the proximity values are always positive.)
The last step now is to choose a threshold value to determine if the colors are "too close". The chosen value is usually arbitrary, so test a few and take your pick. For the example, I'm using the value '84'.
if (color_proximity < 84) {
// color is too close : change it
} else {
// color is okay : do nothing ?
}
This is only one method, and if you have to play a lot with colors, search a bit on the web for other algorithm; It's always usefull.
Given a css color value like:
rgba(0, 0, 0, 0.86)
How do I convert that to a RGB hex value that takes the alpha component into account, assuming a white background?
Since alpha value both attenuates the background color and the color value, something like this could do the trick:
function rgba2rgb(RGB_background, RGBA_color)
{
var alpha = RGBA_color.a;
return new Color(
(1 - alpha) * RGB_background.r + alpha * RGBA_color.r,
(1 - alpha) * RGB_background.g + alpha * RGBA_color.g,
(1 - alpha) * RGB_background.b + alpha * RGBA_color.b
);
}
(Try it interactively: https://marcodiiga.github.io/rgba-to-rgb-conversion)
Assuming that the values are 0...1 per channel.
And assuming that the abbreviation in the method / function call in the question correspond to the arguments, the following should work.
A = 255 * 0.86
R = 255 * 0
G = 255 * 0
B = 255 * 0
Note you may want to change how it rounds off here as it may give inaccuracies in colours.
At this point, the values are in fact still floating point values, but casting them to a byte or a char (depending on language), should in theory work.
var _A = (byte)219.3
var _R = (byte)0
var _G = (byte)0
var _B = (byte)0
Now all you have to do is convert them to a hexadecimal string each, and concatenate them (ARGB) and put a nice little hash tag in front (#)
In C# you could do something akin to:
var hexString = string.Format("#{0:X2}{1:X2}{2:X2}{3:X2}", _A, _R, _G, _B);
Yielding a final result of something like:
#DB000000
you can convert red,green and blue individually using .toString(16) and then combine the result in a case, if you just want to convert a rgb to hex... since you are searching to convert rgba to hex i thought it would be better to convert the rgba to rgb and then to hex as i did in the following Fiddle, which would also consider the background-color of the parent div.
The rgba value you are having is:
rgba(0, 0, 0, 0.86)
First 0 stands for RED
Second 0 stands for GREEN
Third 0 stands for BLUE
and the last digit 0.86 stands for alpha/opacity
Here are some links for rgb to hex converter:
http://www.javascripter.net/faq/rgbtohex.htm
http://www.rgbtohex.net/
http://www.yellowpipe.com/yis/tools/hex-to-rgb/color-converter.php
with you digits 0, 0, 0. The Hex Code will be
#000000
Following is the code for low opacity with a white background
HTML
<div id="parentDiv">
<div id="childDiv">
</div>
</div>
CSS
#parentDiv
{
height:100px; /* The property of Child is Inherit */
width:100px; /* The property of Child is Inherit*/
background-color:#ffffff;
}
#childDiv
{
height:inherit;
width:inherit;
background-color:#000000;
opacity:0.86;
filter:alpha(opacity="86");
}
Now the parent Div is the background with
#ffffff (White color)
I have two images, one of which is a small icon that is superimposed over the first image. My icon has a white background, so when the icon is placed over the other image, we get this effect where a white square appears over the image. Ideally, I do not want to display this white background on top of my other image. Is there is a CSS property I can apply to my icon to make its white background transparent?
Actually there is a way although only currently supported on Chrome, Firefox, and Safari. If the background color is white, you can add the CSS property:
mix-blend-mode: multiply;
You can read more about it here: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode
Opacitator
mix-blend-mode does work for some browsers, but we've found that it causes performance issues in chrome, I have no idea why.
A designer on my team came up with this genius hack, where you create a layer that is mostly transparent, but when it is laid over a white background, it's color will match the color of the surrounding background.
The way this "magical" color is found; is by calculating how much darker each color axis should be for the amount of opacity removed. The formula for this is 255 - ( 255 - x ) / opacity. The issue is: If the opacity is set too low the formula gives you negative numbers (which can't be used). If the opacity is too high, you'll get some coloring on the non-white portions of your image.
Initially we used a spreadsheet that would do the calculations and through manual trial and error we would find that Goldilox color.
Once we started using sass I realized that this can be accomplished with a binary search. So I created a sass function that does the work for us.
Check out this gist on sassmeister. Pass your background color in-to the opacitator function on line 56 of the sass-code. and use the generated rgba color in a div (or a pseudo element) to overlay the image.
I also created a working example on codepen.
As there is no reliable way to remove background with CSS, sharing a code snippet of how I did it with JS:
public async removeImageBackground(image) {
const backgroundColor = { red: 255, green: 255, blue: 255 };
const threshold = 10;
const imageElement = new Image();
imageElement.src = image;
await new Promise(function(resolve) { imageElement.addEventListener('load', resolve); });
var canvas = document.createElement('canvas');
canvas.width = imageElement.naturalWidth;
canvas.height = imageElement.naturalHeight;
var ctx = canvas.getContext('2d');
ctx.drawImage(imageElement, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (var i = 0; i < imageData.data.length; i += 4) {
const red = imageData.data[i];
const green = imageData.data[i + 1];
const blue = imageData.data[i + 2];
if (Math.abs(red - backgroundColor.red) < threshold &&
Math.abs(green - backgroundColor.green) < threshold &&
Math.abs(blue - backgroundColor.blue) < threshold) {
imageData.data[i + 3] = 0;
}
}
ctx.putImageData(imageData, 0, 0);
return canvas.toDataURL(`image/png`);
}
You can make a container for your image.
Then for the css of the container:
overflow:hidden; height: (depends on your image, then make it a smaller px); width:100%;
Hope it helps. :)
No. Not yet...
It is getting very close to possible, though. Check out this article about CSS Filters, an experiemental css feature, that is doing some things client-side that are neat.
CSS Filters
In Canvas/HTML5, I know you can use RGBA to set color and alpha transparency for fillStyle or strokeStyle. You can also use just RGB to set color with no alpha channel. is there a way you can change the alpha value of an item without also supplying the color.
My example would be wanting to change the fillStyle or strokeStyle above a canvas section whose color was random or no longer known. Is there a way to change the alpha through another attribute or by passing nothing to the color (e.g. ctx.fillStyle = 'rgba(,,,alphaValue)';)
There are a few ways.
First, the globalAlpha attribute of the context.
As you ask in the title, it will allow transparency to be set independently of fill or stroke.
You could then use the getImageData on a point to find out the color and save that info, clear that area with clearRect, set globalAlpha, and then redraw that area with the color you saved.
Of course, you don't need globalAlpha at all. You could also do the above and instead of setting global alpha, just modify the alpha of the color that you saved.
If you want to make a large, complex area of canvas more transparent, then you will want to change the globalAlpha and then draw the canvas onto itself using drawImage.
Here's an example of that. I draw two rectangles, then make a rectangular area between them more transparent.
You can use a function to extract the RGB values from whatever is set for the style you are interested in, and then set it with the desired alpha:
var rgb = hexToRgb(canvasCtx.fillStyle);
canvasCtx.fillStyle = "rgba(" + rgb["r"] + "," +rgb["g"] + "," + rgb["b"] + ",0.2)";
You can use an hexToRgb function like this one, taken from this other answer:
function hexToRgb(hex) {
// Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
hex = hex.replace(shorthandRegex, function(m, r, g, b) {
return r + r + g + g + b + b;
});
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
Imagine you have two images A and B, and a third grayscale image T. A and B contain just about anything, but let's assume they're two scenes from a game.
Now, assume that T contains a diamond gradient. Being grayscale, it goes from black on the outside to white on the inside.
Over time, let's assume 256 not further elaborated on "ticks" to match the grayscales, A should transition into B giving a diamond-wipe effect. If T instead contained a grid of smaller rectangular gradients, it would be like each part of the image by itself did a rectangular wipe.
You might recognize this concept if you've ever worked with RPG Maker or most visual novel engines.
The question ofcourse is how this is done. I know it involves per-pixel blending between A and B, but that's all I got.
For added bonus, what about soft edges?
And now, the conclusion
Final experiment, based on eJames's code
Sample from final experiment -- waves up, 50% http://helmet.kafuka.org/TransitionsSample.png
The grayscale values in the T image represent time offsets. Your wipe effect would work essentially as follows, on a per-pixel basis:
for (timeIndex from 0 to 255)
{
for (each pixel)
{
if (timeIndex < T.valueOf[pixel])
{
compositeImage.colorOf[pixel] = A.colorOf[pixel];
}
else
{
compositeImage.colorOf[pixel] = B.colorOf[pixel];
}
}
}
To illustrate, imagine what happens at several values of timeIndex:
timeIndex == 0 (0%): This is the very start of the transition. At this point, most of the pixels in the composite image will be those of image A, except where the corresponding pixel in T is completely black. In those cases, the composite image pixels will be those of image B.
timeIndex == 63 (25%): At this point, more of the pixels from image B have made it into the composite image. Every pixel at which the value of T is less than 25% white will be taken from image B, and the rest will still be image A.
timeIndex == 255 (100%): At this point, every pixel in T will negate the conditional, so all of the pixels in the composite image will be those of image B.
In order to "smooth out" the transition, you could do the following:
for (timeIndex from 0 to (255 + fadeTime))
{
for (each pixel)
{
blendingRatio = edgeFunction(timeIndex, T.valueOf[pixel], fadeTime);
compositeImage.colorOf[pixel] =
(1.0 - blendingRatio) * A.colorOf[pixel] +
blendingRatio * B.colorOf[pixel];
}
}
The choice of edgeFunction is up to you. This one produces a linear transition from A to B:
float edgeFunction(value, threshold, duration)
{
if (value < threshold) { return 0.0; }
if (value >= (threshold + duration)) { return 1.0; }
// simple linear transition:
return (value - threshold)/duration;
}
I'd say you start with image A, then on every step I you use the pixels of image A for every position where T is smaller than I, and pixels of the image B otherwise.
For a soft edge you might define another parameter d, and calculate you pixels P like so:
For every point (x,y) you decide between the following three options:
I < T(x,y) - d then the point is equal to the point of A
T(x,y) - d <= I < T(x,y) + d then let z = I - (T(x,y) -d) and the point is equal to A(x,y)(1-z/(2d)) + B(x,y)(z/(2d))
I < T(x,y) + d then the point is equal to the point of B
This produces a linear edge, of course you can chose between an arbitrary number of functions for the edge.