Jquery UI slider gives access to class ui-slider-range to do custom css on the selected range. Is there an easy way to add custom css (in my case background color) to what is left and right of the selected range?
Changing the slider background color changes both left and right, I however want a trio effect essentially of 3 separate background colors for the 3 divided regions created by the range min/max selectors;
You could use jQuery to add a background-image style property to your .ui-slider. You'll have to calculate the position of the sliders as a percentage.
For example, check out the CSS
.ui-slider {
background-image: -webkit-linear-gradient(left, red 50%, blue 50%);
}
Your jQuery would update the style for that specific slider whenever the user moves the slider. Check out this jsFiddle.
var myMin = 0, myMax = 500;
$("#slider-range").slider({
range: true,
min: myMin,
max: myMax,
values: [75, 300],
slide: function (event, ui) {
// Update amount text
$("#amount").val("$" + ui.values[0] + " - $" + ui.values[1]);
// Update left/right color
var left = 100 * (ui.values[0] - myMin) / (myMax - myMin);
var right = 100 * (ui.values[1] - myMin) / (myMax - myMin);
$(this).css('background-image', '-webkit-linear-gradient(left, red ' + left + '%, blue ' + right + '%)');
}
});
Note, you'll have to find a way to initially color the left/right side. Also, there are a few browser-specific background-image properties, see this answer.
Related
I have a css variable named --color. I want to change the value of this css variable as the page scrolls down. The scrolling of the page should "scrub" the value.
Example: --color starts out at rgb(255, 255, 255). As the page scrolls down, the value gets closer to and eventually reaches rgb(0, 0, 0) upon scrolling down all the way. When scrolling back up, the value should slowly advance back to rgb(255, 255, 255), reaching it by the time the page is scrolled up completely.
I have been trying to achieve this with GSAP but have yet to find any success, although I believe it must be possible with the library.
Sure, here you go:
gsap.to("body", {
"--color": "black",
scrollTrigger: {
start: 0,
end: "max",
scrub: true
}
});
https://codepen.io/GreenSock/pen/WNOzWaM?editors=0110
By the way, there are dedicated GSAP forums at https://greensock.com/forums
unfortunately I am not familiar with GSAP, but
here is the link that describes how to get the computed styles and the property value of that style with JS.
You need to listen to scroll event and change the value of the css variable inside of the listener, like so:
document.addEventListener('scroll', function(e) {
var root = document.querySelector(':root');
var newColor = // do your color calculations here;
root.style.setProperty('--color', newColor);
}
here are some useful links.
https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/setProperty
https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration/getPropertyValue
https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
Here is an average calculation for your rgb() color that might be fine enough to go from light to dark and back. It is far to be perfect.
const body = document.querySelector("body ");
const bodyHeight = document.querySelector("body").offsetHeight;
body.innerHTML = '<p style="position:sticky;top:0;">Body Height: ' + bodyHeight + 'px <br>Window Height: ' + window.innerHeight + 'px</p>';
const root = document.querySelector(":root");
window.addEventListener("scroll", (event) => {
let scroll = this.scrollY;
let ratio = (scroll / (bodyHeight - window.innerHeight ) ) ;
let rgbvalue = 255 - ratio * 255;
root.style.setProperty( "--color", "rgba(" + rgbvalue + "," + rgbvalue + "," + rgbvalue + ")"
);
console.log(rgbvalue);
});
body {
background: var(--color, rgb(255, 255, 255));/* use defaul trgb(255, 255, 255) untill var is set from js */
height: 300vh;
}
<div></div>
It's helpful when you provide a code snippet to show what has already been attempted. Helps with specificity of the answer.
To give a general answer to your question, you can use ScrollTrigger to define the point at which the color changes. Define the markers where it should start changing and use properties such as coloronEnter, onLeave, onEnterBack to your callback to change the color.
I have a design system with many, many colors. I have created a table of colors where all colors are mixed with every other color and color contrast ratio (CCR) of each combination is output. The goal is to flag inaccessible color combinations.
I am using Chroma.js to manipulate the colors and output the CCRs. It works brilliantly with the bulk of my HSL-defined colors.
The trouble comes when my design system uses a color with an alpha channel. Determining how a pair of colors performs with CCR when one or both of them are transparent is problematic. I am trying a few different things to mix or blend a HSLA color with white and then run the contrast function on that. Here is a snippet of what I am doing:
// where either foreground or background has an alpha value present less than 1
var background = chroma.mix(background, '#fff', 1, 'lab').css();
var foreground = chroma.mix(foreground, background, 1, 'lab').css();
var ccr = chroma.contrast(foreground, background);
// lab gets the closest but not the same as the way CSS overlays colors
The results are visualized with this graphic I put together. Left are two colors with an overlay of them in the middle. In Adobe Illustrator, I used 25% transparency on the tan color and a "normal" blend mode. I did the same in CSS and then screen-shotted it, then measured the resulting color mix in Photoshop. To the right are the outputs of Chroma color functions:
Having tried what I understand to be the options in Chroma.js, I am wondering what else I can try to get my results closer to the browser output so that my CCR tests will be accurate. Thanks all.
Thanks to the accepted answer from #GrahamRitchie, my output table now looks like this. The little "composite" labels show the colors that were produced by these functions, while the main output still layers the transparent colors over each other and the background.
I do not know how to do this with the library you mentioned (Chroma.js) but hopefully a vanilla JavaScript function will help.
Please note that the below function always assumes an opaque background colour to work correctly (hence background RGB and foreground RGBA).
If you need to work with 2 colours that both have alpha channels you would run the function on the background colour first (as the foreground colour) with a white background and then combine the two colours.
The function will also combine two RGB colours, simply omit the alpha channel when passing your RGB colour (convertToRGB({r,g,b}, {r,g,b}))
function convertToRGB(frontRGBA, backgroundRGB){
var rtrn = {};
//allows the function to just accept a front colour and assume the background is a plain white.
backgroundRGB = backgroundRGB || {r:255,g:255,b:255};
//allows a RGB value to be passed in assuming full alpha channel.
frontRGBA.a = frontRGBA.a || 1;
//normalise the alpha channel across the foreground and background.
rtrn.r = ((1 - frontRGBA.a) * backgroundRGB.r) + (frontRGBA.a * frontRGBA.r);
rtrn.g = ((1 - frontRGBA.a) * backgroundRGB.g) + (frontRGBA.a * frontRGBA.g);
rtrn.b = ((1 - frontRGBA.a) * backgroundRGB.b) + (frontRGBA.a * frontRGBA.b);
//just check that we don't end up with a value greater than 255 for any channel.
rtrn.r = (rtrn.r > 255) ? 255 : rtrn.r;
rtrn.g = (rtrn.g > 255) ? 255 : rtrn.g;
rtrn.b = (rtrn.b > 255) ? 255 : rtrn.b;
return rtrn;
}
var backgroundRGB = {r:165,g:193,b:211};
var frontRGBA = {r:210,g:203,b:178,a:0.25};
//used for example
var rgb = convertToRGB(frontRGBA, backgroundRGB);
document.querySelector(".output").style.background = "rgb(" + rgb.r + "," + rgb.g + "," + rgb.b + ")";
document.querySelector(".output").innerHTML = "Output<br/>R:" + rgb.r + "<br/>G:" + rgb.g + "<br/>B:" + rgb.b;
.container div{
width: 200px;
height: 200px;
float: left;
}
.div1{
background: rgba(165,193,211,1);
}
.div2{
background: rgba(210,203,178,0.25);
}
<div class="container">
<div class="div1">Background<br/>R:165<br/>G:193<br/>B:211<br/>A:1</div>
<div class="output">Output</div>
<div class="div2">Foreground<br/>R:210<br/>G:203<br/>B:178<br/>A:0.25</div>
</div>
image indicates 70% when x=0.7
Observe this fiddle :http://jsfiddle.net/jayeshjain24/ddfsb/1/
According to the values inside the boxes,gradient should appear.The following details has some info about what should be done:::
Formula------> (x/1)*100=Percentage.(this determines the % of gradient!!!)
x will vary from 0 to 0.999
where x=the values that you see in boxes(viz.0.06,0.09,0.9 etc).These value come from var data which is array having first element=some random id(ignore this) and second element as multidimensional or simple array()!!!All the values that you see in boxes are second parameter of the array
What I want is to calcutate the percentage based on that value using above formula and then display it in percentage like i did with the above image.
COLOR-CODE for above image--->background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(30,87,153,1)), color-stop(67%,rgba(28,31,178,1)), color-stop(80%,rgba(144,192,229,1))); /* Chrome,Safari4+ */
Generated From--> http://www.colorzilla.com/gradient-editor/
-----------------------------------------------------------Simplification-------------------------------------------------
Lets say if value==0.5
if the cell is from first row-->then
assume blue as a parent color(so the gradient will be blue and light
blue,you can have any parent color you wish,but gradient should be
relative)
convert 0.5 in percentage using above formula--->gives you 50%...so
50 percent dark blue followed by 50% light blue.
You can generate the same webkit-gradient string dynamically. I've updated your jsfiddle here with what I think you mean. The relevant code is below.
.style('background', function(d) {
if(d.value) {
var col = d3.rgb(colors(d.value[0]));
return "-webkit-gradient(linear, left top, right top, color-stop(0%," +
col.darker(3) + "), color-stop(" + (d.value[2] * 100) + "%," +
col + "), color-stop(100%," + col.brighter(3) + "))";
} else {
return "white";
}
})
The methods .darker() and .brighter() are provided by D3 and do what they say -- you may want to replace them with custom start/end colours.
I'm working on an iPad webview project that requires a slider to move back and forth over two pictures, revealing one or the other when sliding to the left or right. Due to project restraints, I can't utilize jQuery. I currently have the left picture on top with a transparent mask over it and when the -webkit-mask-position is increased, it reveals more of the bottom picture, when decreased, more of the top (covering the bottom one).
I'm using a javascript plugin called Draggy (https://github.com/jofan/Draggy) to move the slider back and forth and want to use its onChange function call to update the position of the mask, but I can't figure out what javascript calls "-webkit-mask-position" to save my life.
Any ideas?
PS: webkitMaskPosition adds style="-webkit-mask: XX" to the element, which I COULD use (filling in the other values in the js), but it's being really buggy. I'm looking into it now.
OH MAN I GOT IT.
var maskSlider = document.getElementById('molecule');
function moveMask(x, y) {
var xx = x - 285;
var z = "-webkit-gradient(linear, left center, right center, color-stop(0.5, black), color-stop(0.5, transparent)) no-repeat scroll " + xx + "px padding padding";
maskSlider.style.webkitMask = z;
}
The -285 is to get it to line up to where the slider is on the image. I have no idea if I'm really doing this the right way, but it worked. If anyone can think of a better/ more efficient way to do this, please let me know.
I've recently worked a lot about webkit masks which are using CSS3 gradients to make transitions between images.
I preferred to append a style tag to head tag which is made dynamically by my calculations. And also I used CSS3 animation too. Something like this:
var cssStr = '<style id="myTransition">.myTransition_wipe{' +
'-webkit-mask-size: 200% 200%;' +
'-webkit-mask-repeat: no-repeat;' +
'-webkit-animation: wipe 2s;' +
'-webkit-animation-direction: normal;' +
'-webkit-animation-iteration-count: 1;' +
'-webkit-animation-fill-mode: forwards;' +
'-webkit-mask-position: offsetLeftS 0;' +
'-webkit-mask-image: -webkit-gradient(linear, left top, right top, ' +
'color-stop(0%, transparent), color-stop(20%, transparent), ' +
'color-stop(25%, transparent), color-stop(30%, transparent), ' +
'color-stop(50%, rgba(0, 0, 0, 1)), color-stop(98%, rgba(0, 0, 0, 1)), ' +
'color-stop(100%, rgba(0, 0, 0, 1)));}' +
'#-webkit-keyframes wipe {' +
'0% { -webkit-mask-position: offsetLeftS 0; }' +
'100% { -webkit-mask-position: offsetLeftD 0; }' +
'}' +
'</style>';
var compStyle = getComputedStyle(currentElement);
var width = parseInt(compStyle.getPropertyValue("width"));
var height = parseInt(compStyle.getPropertyValue("height"));
cssStr = cssStr.replace(/offsetLeftS/g, '-' + (width * 1) + 'px');
cssStr = cssStr.replace(/offsetLeftD/g, '+' + (width * 1) + 'px');
$('head').append(cssStr);
When I want to apply a transition, I remove the style tag by its ID and remove the class myTransition_wipe from element too, then append a new one to head tag and add the class name to element too.
Pay Attention: You must store the styles that element should have after the animation is finished and add them right after the animation is finished. Otherwise, when you remove class name and style tag, everything will be reset.
Good Luck
I'm trying to make a slider from scratch like the jQuery UI one but i'm not sure how to detect the horizontal position where the user clicks on the slider.
Example, if i click on foo div in the middle, it'd return 50%. If i have that it would be easy for me to adjust the slider's filler div width accordingly.
Try this fiddle: http://jsfiddle.net/UCFtB/1/
Script:
$("#test").mousemove(function(e){
var perc = e.offsetX/ $(this).width() * 100;
$(this).html(e.offsetX + " | " + perc + " perc");
});