How to add linear-gradient color to Slider?
linear-gradient
creates an image not a color. So you need to use it in CSS that specifies an image (e.g. background-image
).
Below is an example of a Slider
using a gradient.
import React from "react";
import { makeStyles, withStyles } from "@material-ui/core/styles";
import Slider from "@material-ui/core/Slider";
const useStyles = makeStyles({
root: {
width: 200
}
});
const CustomSlider = withStyles({
rail: {
backgroundImage: "linear-gradient(.25turn, #f00, #00f)"
},
track: {
backgroundImage: "linear-gradient(.25turn, #f00, #00f)"
}
})(Slider);
export default function ContinuousSlider() {
const classes = useStyles();
const [value, setValue] = React.useState(30);
const handleChange = (event, newValue) => {
setValue(newValue);
};
return (
<div className={classes.root}>
<CustomSlider
value={value}
onChange={handleChange}
aria-labelledby="continuous-slider"
/>
</div>
);
}
Change color gradient of input slider using js?
In this case I would consider CSS variables to simplify the code. The idea is to change the color variable using JS and the code will be reduced.
Then you can adjust the gradient color by using the variable in the needed place and using only CSS:
var red_slider = document.getElementById("red_slider");var green_slider = document.getElementById("green_slider");var blue_slider = document.getElementById("blue_slider");
var red_output = document.getElementById("red_value");var green_output = document.getElementById("green_value");var blue_output = document.getElementById("blue_value");
red_slider.oninput = function() { red_output.innerHTML = this.value; document.documentElement.style.setProperty('--red-color', this.value);
}green_slider.oninput = function() { green_output.innerHTML = this.value; document.documentElement.style.setProperty('--green-color', this.value);
}blue_slider.oninput = function() { blue_output.innerHTML = this.value; document.documentElement.style.setProperty('--blue-color', this.value);}
:root { --red-color:127; --blue-color:127; --green-color:127;}
.slider { display: inline; -webkit-appearance: none; height: 15px; border-radius: 5px; background: #d3d3d3; outline: none; -webkit-transition: .2s; transition: opacity .2s; width: 80%; margin-left: 5%;}
.slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 25px; height: 25px; border-radius: 50%; background: #4CAF50; cursor: pointer;}
.slider::-moz-range-thumb { width: 25px; height: 25px; border-radius: 50%; background: #4CAF50; cursor: pointer;}
#rgb_value_container { /*margin: 16px auto;*/ text-align: center; font-weight: bold; font-size: 20px;}
#red_slider { background: linear-gradient(to right, rgb(0, 0, 0), rgb(255, var(--green-color), var(--blue-color)));}
#green_slider { background: linear-gradient(to right, rgb(0, 0, 0), rgb(var(--red-color), 255, var(--blue-color)));}
#blue_slider { background: linear-gradient(to right, rgb(0, 0, 0), rgb(var(--red-color), var(--green-color), 255));}
#color_box { width: 250px; height: 250px; margin: 30px auto; background-color: rgb(var(--red-color), var(--green-color), var(--blue-color));}
<div id="color_box"></div>
<input type="range" min="0" max="255" value="127" class="slider" id="red_slider"><p>Red: <span id="red_value">127</span></p>
<input type="range" min="0" max="255" value="127" class="slider" id="green_slider"><p>Green: <span id="green_value">127</span></p>
<input type="range" min="0" max="255" value="127" class="slider" id="blue_slider"><p>Blue: <span id="blue_value">127</span></p>
How to add a gradient in a Slider?
I solved this by using react-native-linear-gradient inside react-native-multi-slider's code.
First use the slider anywhere.
import MultiSlider from '@ptomasroos/react-native-multi-slider'
<MultiSlider
min={100}
max={100000}
/>
Then navigate to MultiSlider.js file in the library, and look for const body
inside render
method.
Then replace this:
<View
style={[
styles.track,
this.props.trackStyle,
trackOneStyle,
{ width: trackOneLength },
]}
/>
With this:
<LinearGradient
style={[
styles.track,
this.props.trackStyle,
trackOneStyle,
{ width: trackOneLength },
]}
colors={['white','chocolate']}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 0 }}
/>
Add Gradient to color slider
I'm sorry if I didn't understand you right.
First of all you have two variables lInput
. I think the second one (for LAB) has to be llInput
(considering your naming technique).
Then you have to add setGradient()
functions. For V in HSV, for instance that should be setGradient(vInput, [hsv(hhInput.value, ssInput.value, 0), hsv(hhInput.value, ssInput.value, 100)]);
. Obviously you have only two function calls here (check yourself this block), they are for 'H' and 'S'.
Also, you have a typo here too, change hsl(300, ssInput.value, vInput.value)
to hsv(300, ssInput.value, vInput.value)
in the setGradient()
for HSV.
For lab it's exactly the same process, if we speak about just gradients, but you have to change the setGradient()
algorithm for this one, because css doesn't support LAB.
I hope this answer will help you :)
How can I make a linear gradient follow the thumb of a range slider in html
The problem is you're binding your function directly to the oninput handler, which does not get triggered just by changing the input
's value programmatically.
You can solve it just by declaring your function outside the oninput
, and then assign your function to it later and calling it inside your timeupdate
listener. It doesn't really matter if you declare your function before or after assigning it to oninput
as long as you're using the function
keyword to declare it, since it gets hoisted.
Working snippet
I also uploaded the following snippet in JSFiddle in which you'll be able to see it more clearly.
var video = document.querySelector(".video");var juice = document.querySelector(".red-juice");var btn = document.getElementById("play-pause");
function togglePlayPause() { if (video.paused) { btn.className = 'pause'; video.play(); } else { btn.className = 'play'; video.pause(); }}
btn.onclick = function(params) { //video.fastSeek(570); // 9:30 // video.currentTime = 570; //test togglePlayPause();}
video.addEventListener('timeupdate', function() {
if (video.ended) { btn.className = "play"; // At the end of the movie, reset the position to the start and pause the playback. video.currentTime = 0; togglePlayPause(); }});
function slidingProgress() { // this.value will not work here, since it points to the global window obj // so I'm using juice.value instead // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#Function_context juice.style.background = 'linear-gradient(to right, red ' + juice.value * 100 / juice.max + '%, rgba(0, 0, 0, 0.4) ' + juice.value + '%, rgba(0, 0, 0, 0.4) 100%)'}
video.addEventListener('timeupdate', () => { juice.value = video.currentTime / video.duration * juice.max slidingProgress() // Call your function here to update .red-juice})
juice.addEventListener('change', () => { video.currentTime = video.duration * juice.value / juice.max})
// And finally assign it to juice.oninputjuice.oninput = slidingProgress;
// you're not specifying any events to listen to here, so it wouldn't work// juice.addEventListener(slidingProgress);
.container { display: flex; background-color: #000000; justify-content: center; align-items: center; height: 100vh;}
.video { width: 100%;}
.c-video { width: 100%; max-width: 800px; position: relative; overflow: hidden;}
.c-video:hover .title { transform: translateY(0);}
.c-video:hover .controls { transform: translateY(0);}
.c-video:hover .buttons { top: 50%; left: 50%; transform: translate(240%, -50%);}
.title { display: flex; position: absolute; top: 0; height: 120px; width: 100%; flex-wrap: wrap; background-image: linear-gradient(rgba(0, 0, 0, 0.9), rgba(0, 0, 0, 0.01)); transform: translateY(-100%); transition: all .2s;}
.controls { display: flex; position: absolute; bottom: 0; height: 70px; width: 100%; flex-wrap: wrap; background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 0.9)); transform: translateY(100%); transition: all .2s;}
.buttons { position: absolute; top: 50%; left: 50%; transform: translate(-999%, -50%);}
.buttons button { background: none; height: 45px; border: none; outline: 0; cursor: pointer; transform: translate(-300%, 0px);}
.buttons button:before { content: "\f144"; font-family: "Font Awesome 5 Free"; display: inline-block; font-size: 300%; color: #ffff; -webkit-font-smoothing: antialiased;}
.buttons button.play:before { content: "\f144"; font-family: 'Font Awesome 5 Free';}
.buttons button.pause:before { content: "\f28b"; font-family: 'Font Awesome 5 Free';}
/* Progress bar container */
.red-bar { height: 2px; margin-top: 15px; margin-bottom: -15px; background-color: rgba(0, 0, 0, 0.4); margin-left: 10px; margin-right: 10px; width: 100%;}
/* This represents the progress bar */
.red-juice { position: relative; width: 100%; height: 2px; /* thumbHeight + (2 x thumbBorderWidth)*/ background-image: linear-gradient(to right, red 1%, rgba(0, 0, 0, 0.4) 1%); -webkit-appearance: none; /*remove the line*/ outline: none; top: -12px; margin-left: 1px; margin-right: 100px;}
.red-juice::-webkit-slider-runnable-track { -webkit-appearance: none; height: 20px;}
.red-juice::-webkit-slider-thumb { -webkit-appearance: none; background: red; /*thumbColor*/ width: 15px; /* thumbHeight + (2 x thumbBorderWidth)*/ height: 15px; /* thumbHeight + (2 x thumbBorderWidth)*/ border-radius: 100%; margin-top: 1px; /* -[thumbHeight + (2 x thumbBorderWidth) - trackHeight]/2*/ cursor: pointer; border: 0px solid #fff; /*border-width should be equal to thumbBorderWidth if you want same border width across all browsers and border-color should match the background*/ transition: 0.3s;}
<!DOCTYPE html><html lang="en">
<head>
<meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Netflix video player</title>
<link rel="stylesheet" href="https://cdnjs.cloudlflare.com/ajax/libs/meyer-reset/2.0/reset.min.css"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous"> <link rel="stylesheet" href="style.css">
</head>
<body> <div class="container"> <div class="c-video"> <video class="video" src="https://www.w3schools.com/html/mov_bbb.mp4"></video> <div class="controls"> <div class="red-bar"> <!-- inputs are self-closing tags. You don't need a closing tag for it! Self-closing tags are single tagged elements - you only need to add a slash before '>', like so: <input /> --> <input class="red-juice" type="range" min="1" max="100" step="1" value="1" />
</div>
</div> <div class="buttons"> <button id="play-pause"></button> </div> <div class="title"></div> </div> </div> <script src="script.js"></script>
</body>
</html>
How to make a custom slider with color gradient?
I am working on something quite similar for one of my projects. I hope this can help you. (!!! It's a work in progress !!!)
It's a generic 1D Selector for a given value
This selector is totally agnostic of the meaning of the [value
] that must be normalized on a {0, 1} range.
The Selector is configured with a [pointerColor
], background [gradientColors
] and [withChecker
], whether or not we should display checkers. The pointer's border is white
by default but if [highContrastPointer
] is used, it becomes black
on light backgrounds.
[onSelect] is called when the User selects a new value.
Here is a sample demo with a Color Hue Selector and another one quite similar to your design:
In the following full source code, you will find the Demo App, the Generic1dSelector
(and its CustomPainter
) as well as three helpers:
isDark
, as an extension on Color, to determine if a Color is dark or lightshowCursorOnHover
, as an extension on Widgets, to display a pointer cursor on a WidgetpaintCheckers
to paint a checkers background if the gradient used by the selector is semi-transparent
Let me know what you think and how to further improve it!
Full source code
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
void main() {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
);
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(16.0),
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SelectorOne(),
const SizedBox(height: 16.0),
SelectorTwo(),
],
),
),
);
}
}
class SelectorOne extends HookWidget {
@override
Widget build(BuildContext context) {
final _valueOne = useState<double>(.2);
final _colorsOne = [Color(0xff5bc5f6), Color(0xff5a3738)];
return SizedBox(
width: 200,
height: 30,
child: Generic1DSelector(
direction: Axis.horizontal,
value: _valueOne.value,
pointerColor: Color.fromARGB(
(_colorsOne[0].alpha +
_valueOne.value *
(_colorsOne[1].alpha - _colorsOne[0].alpha))
.round(),
(_colorsOne[0].red +
_valueOne.value *
(_colorsOne[1].red - _colorsOne[0].red))
.round(),
(_colorsOne[0].green +
_valueOne.value *
(_colorsOne[1].green - _colorsOne[0].green))
.round(),
(_colorsOne[0].blue +
_valueOne.value *
(_colorsOne[1].blue - _colorsOne[0].blue))
.round(),
),
gradientColors: _colorsOne,
onSelect: (value) => _valueOne.value = value,
),
);
}
}
class SelectorTwo extends HookWidget {
@override
Widget build(BuildContext context) {
final _valueTwo = useState<double>(.6);
return SizedBox(
width: 200,
height: 30,
child: Generic1DSelector(
direction: Axis.horizontal,
value: _valueTwo.value,
pointerColor:
HSVColor.fromAHSV(1, 360 * _valueTwo.value, 1, 1).toColor(),
gradientColors: List<Color>.generate(
11,
(i) => HSVColor.fromAHSV(1, i * 36.0, 1, 1).toColor(),
),
onSelect: (value) => _valueTwo.value = value,
),
);
}
}
/// 1D Selector for a given value
///
/// This selector is totally agnostic of the meaning of the [value] that must be
/// normalized on a {0, 1} range.
/// The Selector is configured with a [pointerColor], background [gradientColors]
/// and [withChecker], whether or not we should display checkers. The pointer's
/// border is `white` by default but if [highContrastPointer] is used, it becomes
/// `black` on light backgrounds.
///
/// [onSelect] is called when the User select a new value.
class Generic1DSelector extends StatelessWidget {
final double value;
final Axis direction;
final Color pointerColor;
final bool highContrastPointer;
final List<Color> gradientColors;
final bool withCheckers;
final ValueChanged<double> onSelect;
const Generic1DSelector({
Key key,
@required this.value,
this.direction = Axis.vertical,
this.pointerColor = Colors.transparent,
this.highContrastPointer = false,
this.gradientColors = const [Colors.white, Colors.black],
this.withCheckers = false,
this.onSelect,
}) : super(key: key);
void _update(
BuildContext context,
PointerEvent event,
Size size,
) {
if (event.down) {
final value = direction == Axis.vertical
? event.localPosition.dy / size.height
: event.localPosition.dx / size.width;
if (value >= 0 && value <= 1) onSelect(value);
}
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
final size = constraints.biggest;
return Listener(
onPointerDown: (event) => _update(context, event, size),
onPointerMove: (event) => _update(context, event, size),
child: CustomPaint(
painter: _Painter(
value: value,
direction: direction,
gradientColors: gradientColors,
withCheckers: withCheckers,
pointerColor: pointerColor,
highContrastPointer: highContrastPointer,
),
),
);
}).showCursorOnHover();
}
}
class _Painter extends CustomPainter {
final double value;
final Axis direction;
final Color pointerColor;
final bool highContrastPointer;
final bool withCheckers;
final List<Color> gradientColors;
_Painter({
this.value,
this.direction,
this.pointerColor,
this.highContrastPointer,
this.withCheckers,
this.gradientColors,
});
void paintBackground(Canvas canvas, Size size) {
if (withCheckers) {
(direction == Axis.vertical)
? paintcheckers(canvas, size, nbCols: 2)
: paintcheckers(canvas, size, nbRows: 2);
}
final rect = Rect.fromLTWH(0, 0, size.width, size.height);
final rrect =
RRect.fromRectAndRadius(rect, Radius.circular(size.shortestSide / 4));
final LinearGradient gradient = LinearGradient(
colors: gradientColors,
begin: direction == Axis.vertical
? Alignment.topCenter
: Alignment.centerLeft,
end: direction == Axis.vertical
? Alignment.bottomCenter
: Alignment.centerRight,
);
final paint = Paint()..shader = gradient.createShader(rect);
canvas.drawRRect(rrect, paint);
}
void paintPointer(Canvas canvas, Size size) {
final double x =
direction == Axis.vertical ? size.width / 2 : value * size.width;
final double y =
direction == Axis.vertical ? value * size.height : size.height / 2;
final Offset c = Offset(x, y);
final double w = direction == Axis.vertical ? size.width : size.height;
final RRect rrect = RRect.fromRectAndRadius(
Rect.fromCenter(center: c, width: w, height: w),
Radius.circular(w / 4));
final Color pointerBorderColor = highContrastPointer
? pointerColor.isDark()
? Colors.white
: Colors.black
: Colors.grey;
canvas.drawRRect(
rrect,
Paint()
..color = pointerColor
..style = PaintingStyle.fill);
canvas.drawRRect(
rrect,
Paint()
..color = pointerBorderColor
..strokeWidth = w / 8
..style = PaintingStyle.stroke);
}
@override
void paint(Canvas canvas, Size size) {
paintBackground(canvas, size);
paintPointer(canvas, size);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
extension HoverExtensions on Widget {
/// Changes cursor on Hover to [cursor] (default is `SystemMouseCursors.click`).
Widget showCursorOnHover({
SystemMouseCursor cursor = SystemMouseCursors.click,
}) {
return MouseRegion(cursor: cursor, child: this);
}
}
extension ColorX on Color {
/// Determines if the color is dark based on a [luminance] (default is `0.179`).
bool isDark({double luminance = 0.179}) => computeLuminance() < luminance;
}
/// Paints a checker in the [canvas] of [size].
///
/// User may define either the [nbRows] and/or the [nbCols], or the [checkerSize]
/// (default is `kCheckerSize`). The checkers will be display in [darkColor] and
/// [lightCOlor] (default are `kCheckerDarkColor` and `kCheckerLightColor`).
void paintcheckers(
Canvas canvas,
Size size, {
int nbRows,
int nbCols,
double checkerSize = 10,
Color darkColor = const Color(0xff777777),
Color lightColor = const Color(0xffaaaaaa),
}) {
nbRows ??= (nbCols == null)
? size.height ~/ checkerSize
: size.height ~/ (size.width / nbCols);
nbCols ??= size.width ~/ (size.height / nbRows);
final checkerWidth = size.width / nbCols;
final checkerHeight = size.height / nbRows;
final darkPaint = Paint()..color = darkColor;
final lightPaint = Paint()..color = lightColor;
for (var i = 0; i < nbCols; i++) {
for (var j = 0; j < nbRows; j++) {
canvas.drawRect(
Rect.fromLTWH(
i * checkerWidth,
j * checkerHeight,
checkerWidth,
checkerHeight,
),
(i + j) % 2 == 0 ? darkPaint : lightPaint,
);
}
}
}
Related Topics
Input Doesn't Respect Flex Container Width
How to Simply Add a CSS File to Change The Background Color for My Shiny App
W3C CSS Validation Parse Error on Variables
Is There a Cross-Browser Way to Condense Text on a Page
Why Do Non-Floating Parents of Floating Elements Collapse
How to Get Wkhtmltopdf to Display Th and Td Background Gradients
Import CSS Selector Styles in Another Selector? (Not @Import)
CSS: Selecting Table's <Td> Without The <Td>S of Nested Tables
Safari CSS Word-Break: Keep-All; Is Not Working
Multiple Divs with The Same Id Invalid
How to Create an Infinite Background Pattern Animation Using Linear-Gradient
How to See All Edited Styles in Firefox Developer Tools
CSS Div Center Multi-Line Text Vertically and Horizontally with a Background Image
Easiest Way to Convert Polygon Clip-Path to Microsoft Edge Supported "Clippath" Svg