1 个页面上的多个 Material UI 个滑块共享颜色道具
Multiple Material UI Sliders on 1 page sharing color props
我创建了一个组件“SliderBox”,其中 returns 一个 div 和一个 Material UI 滑块,它实现了 createMuiTheme,还有一个输入组件。
组件“SliderBox”将 onHover 方法应用于 parent div 以更改组件颜色的状态。基本上,我将 colorA 从红色变为蓝色,将 colorB 从蓝色变为红色。不幸的是,当在“SliderBox”的一个实例上调用此函数时,它会将颜色更改应用于每个“Slider”。颜色变化在内部进行管理,在“SliderBox”组件之外不受影响。
图 A 是默认状态下三个“SliderBox”组件的视图。
图 B 是三个“SliderBox”组件的视图,而最上面的组件的光标悬停在它上面。请注意,颜色变化似乎适用于所有三个“Slider”组件,但不适用于它们的包含组件“SliderBox”
尝试过的解决方案
我尝试向两个“SliderBox”组件添加唯一的键值,但行为没有变化。
我尝试使用标题和 Math.random() 添加唯一键值到 child“滑块”组件,没有看到任何变化。
我试图将一个唯一的键值传递给每个标记为“sliderKey”的“SliderBox”组件,然后我将键添加为“props.sliderKey”,这并没有显示错误行为的任何变化。
我试图将“Slider”组件与“SliderBox”组件分开,以便它returns在“SliderBox”而不是“Slider”内部实现的“CustomSlider”组件有些变化是注意到闪烁的颜色值发生变化,但所有 Slider 组件仍然共享相同的值。
我什至在实现“SliderBox”的顶层 parent 组件中添加了一个基础“Slider”组件,并且还应用了应用于“SliderBox”组件的 child 的样式到“SliderBox”组件的 parent 组件中的“Slider”组件。
假设
根据我的测试,我假设问题出在“SliderBox”组件中实现的“createMuiTheme”函数。我无法更改“createMuiTheme”,因为它在“overrides:MuiSlider:root:'& .MuiSlider-valueLabel':'& *':”中具有非常独特的 属性 backgroundColor 和颜色,这让我可以更改缩略图的文字颜色,如图 A 和 B 所示。缩略图的文字颜色对我的网站至关重要。我不能使用带有白色文本的缩略图的“滑块”组件。
我的另一个假设是从“import {Slider} from '@material-ui/core';”返回的组件进口。我的信念之一是“@material-ui/core”没有返回一个唯一的组件,或者他们可能没有将唯一的键应用于他们的组件,这导致在实现多个“滑块”组件时出现颜色溢出。
个人缺点
我相信,如果我在 JavaScript class 中实现我的滑块,我可能能够纠正这种错误行为,但我从未使用过“扩展组件”,所以我希望其他用户遇到并解决了以前这个问题。
不完全是我想要的 material UI 答案...但是我在使用 Material Ui 组件方面有很多负面经验,所以我徒劳地等待我的问题的答案,去制作了我自己的表格。
我的版本易于理解且完全可定制...我什至实现了 css 大多数 post 认为不存在的变量。
从现在开始,我将 post 我的可靠代码,这样任何人都可以复制和粘贴并避免暴虐 material UI 和缺乏可定制性。
码友注意事项
这是我的代码。如果您不喜欢我的命名约定、挂钩使用等,那么您可以随意使用它并编写您自己的版本。但我不会欣赏你对此的看法。我正在为其他受输入范围困扰的人分享我的代码
我的组件的示例图片::
SliderBar.jsx::
import React, {useState, useEffect} from "react";
import "./SliderBar.css";
export default function SliderBar(props){
const backgroundColor = props.backgroundColor?props.backgroundColor:"#000";
const textColor = props.textColor?props.textColor:"#fff";
const hoverColor = props.hoverColor?props.hoverColor:"#888";
const initialState = props.value?props.value:0;
const min = props.min?props.min:0;
const max = props.max?props.max:20;
const bubbleClassName = props.bubbleClassName?props.bubbleClassName:("SliderBar-bubble-"+(Math.floor(Math.random()*100000001)));
const bubbleSize = props.bubbleSize?props.bubbleSize:"30px";
const cssValueChanger = {};
const [sliderValue, sliderUpdate] = useState(initialState);
const [textColorValue, textColorUpdate] = useState(textColor);
const [oppositeColorValue, oppositeColorUpdate] = useState(backgroundColor);
const [thumbColorValue, thumbColorUpdate] = useState(hoverColor)
cssValueChanger["--color"] = props.hoverColor?props.hoverColor:thumbColorValue;
useEffect(()=>{
const element = document.querySelector(`.${bubbleClassName}`);
if(element){
const newVal = Number(((props.value?props.value:sliderValue - min) * 100) / (max - min));
element.innerHTML = props.value?props.value:sliderValue;
// Sorta magic numbers based on size of the native UI thumb
element.style.left = `calc(${newVal}% + (${8 - newVal * 0.15}px))`;
}
});
function onChange(event){
sliderUpdate(event.target.value);
if(props.onChange){
props.onChange(event.target.value);
}
}
function onMouseOver(){
if(!props.over){
textColorUpdate(hoverColor);
oppositeColorUpdate(textColor);
thumbColorUpdate(textColor);
}
}
function onMouseOut(){
if(!props.out){
textColorUpdate(textColor);
oppositeColorUpdate(backgroundColor);
thumbColorUpdate(hoverColor);
}
}
return(<div style={props.outerStyle}>
<div onMouseOut={onMouseOut} onMouseOver={onMouseOver} style={{width:"200px", margin:"auto", position:"relative"}}>
<input
type="range"
className="range"
min={min}
max={max}
style={{
...cssValueChanger,
width:"100%",
background: props.textColor?props.textColor:textColorValue,
color: props.backgroundColor?props.backgroundColor:oppositeColorValue,
}}
value={props.value?props.value:sliderValue}
onChange={onChange}
/>
<output
value={props.value?props.value:sliderValue}
className={bubbleClassName}
style={{
background: props.textColor?props.textColor:textColorValue,
color: props.backgroundColor?props.backgroundColor:oppositeColorValue,
position: "absolute",
borderRadius: "100%",
left: "50%",
transform: "translateX(-50%)",
top:"-30px",
lineHeight:bubbleSize,
width:bubbleSize,
height:bubbleSize,
}}
/>
</div>
</div>);
}
SliderBar.css::
input[type="range"] {
-webkit-appearance: none;
-moz-appearance: none;
width: 300px;
height: 5px;
padding: 0;
border-radius: 2px;
outline: none;
cursor: pointer;
}
/*Chrome thumb*/
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
-moz-appearance: none;
-webkit-border-radius: 5px;
/*16x16px adjusted to be same as 14x14px on moz*/
height: 16px;
width: 16px;
border-radius: 5px;
background: var(--color);
border: 1px solid var(--color);
}
/*Mozilla thumb*/
input[type="range"]::-moz-range-thumb {
-webkit-appearance: none;
-moz-appearance: none;
-moz-border-radius: 5px;
height: 14px;
width: 14px;
border-radius: 5px;
background: var(--color);
border: 1px solid var(--color);
}
/*IE & Edge input*/
input[type=range]::-ms-track {
width: 300px;
height: 6px;
/*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */
background: transparent;
/*leave room for the larger thumb to overflow with a transparent border */
border-color: transparent;
border-width: 2px 0;
/*remove default tick marks*/
color: transparent;
}
/*IE & Edge thumb*/
input[type=range]::-ms-thumb {
height: 14px;
width: 14px;
border-radius: 5px;
background: #e7e7e7;
border: 1px solid #c5c5c5;
}
/*IE & Edge left side*/
input[type=range]::-ms-fill-lower {
background: #919e4b;
border-radius: 2px;
}
/*IE & Edge right side*/
input[type=range]::-ms-fill-upper {
background: #c5c5c5;
border-radius: 2px;
}
/*IE disable tooltip*/
input[type=range]::-ms-tooltip {
display: none;
}
input[type="text"] {
border: none;
}
SliderBox.jsx::
import React, {useState} from "react";
import SliderBar from "./slider/SliderBar";
import "./SliderBox.css";
/***
<SliderBox
title={"TextValue"}
value={"TextValue"}
onChange={function onChange()}
textColor={"#ffffffff"}
backgroundColor={"#00000000"}
hoverColor={"#ff808080"}
min={0}
max={20}
/>
*/
export default function SliderBox(props){
const initialState = props.value?props.value:0;
const backgroundColor = props.backgroundColor?props.backgroundColor:"#000";
const textColor = props.textColor?props.textColor:"#fff";
const hoverColor = props.hoverColor?props.hoverColor:"#888";
const min = props.min?props.min:0;
const max = props.max?props.max:20;
const [sliderValue, sliderUpdate] = useState(initialState);
const [textColorValue, textColorUpdate] = useState(textColor);
const [oppositeColorValue, oppositeColorUpdate] = useState(backgroundColor);
function sliderChange(event){
sliderUpdate(event);
if(props.onChange!==undefined){
props.onChange(event);
}
}
function inputChange(event){
let value = event.target.value;
value = value.replace(/^0+/, '')
if(value===""){
value="0";
}
else if(!/^\d+$/.test(value)){
return;
}
if(value > max){
value = max;
}else if(value < min){
value = min;
}
sliderUpdate(value);
if(props.onChange!==undefined){
props.onChange(value);
}
}
//selected Or Blur
function onFocusOrMouseOut(){
textColorUpdate(textColor);
oppositeColorUpdate(backgroundColor);
}
function onBlur(){
if(sliderValue.length<1){
sliderUpdate(0);
}
}
//hover
function onMouseOver(){
textColorUpdate(hoverColor);
oppositeColorUpdate(textColor);
}
return(<div
onMouseOver={onMouseOver}
onMouseOut={onFocusOrMouseOut}
onFocus={onFocusOrMouseOut}
onBlur={onBlur}
style={{
width:"200px",
margin:"auto",
display:"table",
height:"50px",
padding:"35px 20px 15px",
border:"1px solid "+textColorValue,
borderRadius:"5px",
position:"relative"
}}
>
<p style={{
position: "absolute",
top: "-20px",
margin: "0px",
backgroundColor: backgroundColor,
padding: "5px",
borderRadius: "5px"
}}>{props.title}</p>
<SliderBar
outerStyle={{padding:"20px", display:"table-cell"}}
value={sliderValue}
min={min}
max={max}
onChange={sliderChange}
textColor={textColorValue}
hoverColor={hoverColor}
backgroundColor={oppositeColorValue}
/>
<div
style={{
display:"table-cell",
verticalAlign:"middle",
width:"50px"
}}
>
<input
value={sliderValue}
onChange={inputChange}
style={{
outline:"none",
color:textColor,
textAlign:"center",
backgroundColor: backgroundColor,
border: "1px solid "+textColorValue,
borderRadius:"5px",
width:"30px",
height:"30px",
"&:hover :selected":{
outline:"none",
color:textColorValue,
backgroundColor: backgroundColor,
border: "1px solid "+textColorValue,
}
}}
/>
</div>
</div>);
}
SliderBox.css
.PrivateValueLabel-label-900{
color: "orange";
}
.MuiSlider-root .MuiSlider-valueLabel *{
color: green;
background-color: red;
}
[class^="PrivateValueLabel-label-"]{
color: red;
}
我创建了一个组件“SliderBox”,其中 returns 一个 div 和一个 Material UI 滑块,它实现了 createMuiTheme,还有一个输入组件。
组件“SliderBox”将 onHover 方法应用于 parent div 以更改组件颜色的状态。基本上,我将 colorA 从红色变为蓝色,将 colorB 从蓝色变为红色。不幸的是,当在“SliderBox”的一个实例上调用此函数时,它会将颜色更改应用于每个“Slider”。颜色变化在内部进行管理,在“SliderBox”组件之外不受影响。
图 A 是默认状态下三个“SliderBox”组件的视图。
图 B 是三个“SliderBox”组件的视图,而最上面的组件的光标悬停在它上面。请注意,颜色变化似乎适用于所有三个“Slider”组件,但不适用于它们的包含组件“SliderBox”
尝试过的解决方案 我尝试向两个“SliderBox”组件添加唯一的键值,但行为没有变化。
我尝试使用标题和 Math.random() 添加唯一键值到 child“滑块”组件,没有看到任何变化。
我试图将一个唯一的键值传递给每个标记为“sliderKey”的“SliderBox”组件,然后我将键添加为“props.sliderKey”,这并没有显示错误行为的任何变化。
我试图将“Slider”组件与“SliderBox”组件分开,以便它returns在“SliderBox”而不是“Slider”内部实现的“CustomSlider”组件有些变化是注意到闪烁的颜色值发生变化,但所有 Slider 组件仍然共享相同的值。
我什至在实现“SliderBox”的顶层 parent 组件中添加了一个基础“Slider”组件,并且还应用了应用于“SliderBox”组件的 child 的样式到“SliderBox”组件的 parent 组件中的“Slider”组件。
假设 根据我的测试,我假设问题出在“SliderBox”组件中实现的“createMuiTheme”函数。我无法更改“createMuiTheme”,因为它在“overrides:MuiSlider:root:'& .MuiSlider-valueLabel':'& *':”中具有非常独特的 属性 backgroundColor 和颜色,这让我可以更改缩略图的文字颜色,如图 A 和 B 所示。缩略图的文字颜色对我的网站至关重要。我不能使用带有白色文本的缩略图的“滑块”组件。
我的另一个假设是从“import {Slider} from '@material-ui/core';”返回的组件进口。我的信念之一是“@material-ui/core”没有返回一个唯一的组件,或者他们可能没有将唯一的键应用于他们的组件,这导致在实现多个“滑块”组件时出现颜色溢出。
个人缺点 我相信,如果我在 JavaScript class 中实现我的滑块,我可能能够纠正这种错误行为,但我从未使用过“扩展组件”,所以我希望其他用户遇到并解决了以前这个问题。
不完全是我想要的 material UI 答案...但是我在使用 Material Ui 组件方面有很多负面经验,所以我徒劳地等待我的问题的答案,去制作了我自己的表格。
我的版本易于理解且完全可定制...我什至实现了 css 大多数 post 认为不存在的变量。
从现在开始,我将 post 我的可靠代码,这样任何人都可以复制和粘贴并避免暴虐 material UI 和缺乏可定制性。
码友注意事项 这是我的代码。如果您不喜欢我的命名约定、挂钩使用等,那么您可以随意使用它并编写您自己的版本。但我不会欣赏你对此的看法。我正在为其他受输入范围困扰的人分享我的代码
我的组件的示例图片::
SliderBar.jsx::
import React, {useState, useEffect} from "react";
import "./SliderBar.css";
export default function SliderBar(props){
const backgroundColor = props.backgroundColor?props.backgroundColor:"#000";
const textColor = props.textColor?props.textColor:"#fff";
const hoverColor = props.hoverColor?props.hoverColor:"#888";
const initialState = props.value?props.value:0;
const min = props.min?props.min:0;
const max = props.max?props.max:20;
const bubbleClassName = props.bubbleClassName?props.bubbleClassName:("SliderBar-bubble-"+(Math.floor(Math.random()*100000001)));
const bubbleSize = props.bubbleSize?props.bubbleSize:"30px";
const cssValueChanger = {};
const [sliderValue, sliderUpdate] = useState(initialState);
const [textColorValue, textColorUpdate] = useState(textColor);
const [oppositeColorValue, oppositeColorUpdate] = useState(backgroundColor);
const [thumbColorValue, thumbColorUpdate] = useState(hoverColor)
cssValueChanger["--color"] = props.hoverColor?props.hoverColor:thumbColorValue;
useEffect(()=>{
const element = document.querySelector(`.${bubbleClassName}`);
if(element){
const newVal = Number(((props.value?props.value:sliderValue - min) * 100) / (max - min));
element.innerHTML = props.value?props.value:sliderValue;
// Sorta magic numbers based on size of the native UI thumb
element.style.left = `calc(${newVal}% + (${8 - newVal * 0.15}px))`;
}
});
function onChange(event){
sliderUpdate(event.target.value);
if(props.onChange){
props.onChange(event.target.value);
}
}
function onMouseOver(){
if(!props.over){
textColorUpdate(hoverColor);
oppositeColorUpdate(textColor);
thumbColorUpdate(textColor);
}
}
function onMouseOut(){
if(!props.out){
textColorUpdate(textColor);
oppositeColorUpdate(backgroundColor);
thumbColorUpdate(hoverColor);
}
}
return(<div style={props.outerStyle}>
<div onMouseOut={onMouseOut} onMouseOver={onMouseOver} style={{width:"200px", margin:"auto", position:"relative"}}>
<input
type="range"
className="range"
min={min}
max={max}
style={{
...cssValueChanger,
width:"100%",
background: props.textColor?props.textColor:textColorValue,
color: props.backgroundColor?props.backgroundColor:oppositeColorValue,
}}
value={props.value?props.value:sliderValue}
onChange={onChange}
/>
<output
value={props.value?props.value:sliderValue}
className={bubbleClassName}
style={{
background: props.textColor?props.textColor:textColorValue,
color: props.backgroundColor?props.backgroundColor:oppositeColorValue,
position: "absolute",
borderRadius: "100%",
left: "50%",
transform: "translateX(-50%)",
top:"-30px",
lineHeight:bubbleSize,
width:bubbleSize,
height:bubbleSize,
}}
/>
</div>
</div>);
}
SliderBar.css::
input[type="range"] {
-webkit-appearance: none;
-moz-appearance: none;
width: 300px;
height: 5px;
padding: 0;
border-radius: 2px;
outline: none;
cursor: pointer;
}
/*Chrome thumb*/
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
-moz-appearance: none;
-webkit-border-radius: 5px;
/*16x16px adjusted to be same as 14x14px on moz*/
height: 16px;
width: 16px;
border-radius: 5px;
background: var(--color);
border: 1px solid var(--color);
}
/*Mozilla thumb*/
input[type="range"]::-moz-range-thumb {
-webkit-appearance: none;
-moz-appearance: none;
-moz-border-radius: 5px;
height: 14px;
width: 14px;
border-radius: 5px;
background: var(--color);
border: 1px solid var(--color);
}
/*IE & Edge input*/
input[type=range]::-ms-track {
width: 300px;
height: 6px;
/*remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead */
background: transparent;
/*leave room for the larger thumb to overflow with a transparent border */
border-color: transparent;
border-width: 2px 0;
/*remove default tick marks*/
color: transparent;
}
/*IE & Edge thumb*/
input[type=range]::-ms-thumb {
height: 14px;
width: 14px;
border-radius: 5px;
background: #e7e7e7;
border: 1px solid #c5c5c5;
}
/*IE & Edge left side*/
input[type=range]::-ms-fill-lower {
background: #919e4b;
border-radius: 2px;
}
/*IE & Edge right side*/
input[type=range]::-ms-fill-upper {
background: #c5c5c5;
border-radius: 2px;
}
/*IE disable tooltip*/
input[type=range]::-ms-tooltip {
display: none;
}
input[type="text"] {
border: none;
}
SliderBox.jsx::
import React, {useState} from "react";
import SliderBar from "./slider/SliderBar";
import "./SliderBox.css";
/***
<SliderBox
title={"TextValue"}
value={"TextValue"}
onChange={function onChange()}
textColor={"#ffffffff"}
backgroundColor={"#00000000"}
hoverColor={"#ff808080"}
min={0}
max={20}
/>
*/
export default function SliderBox(props){
const initialState = props.value?props.value:0;
const backgroundColor = props.backgroundColor?props.backgroundColor:"#000";
const textColor = props.textColor?props.textColor:"#fff";
const hoverColor = props.hoverColor?props.hoverColor:"#888";
const min = props.min?props.min:0;
const max = props.max?props.max:20;
const [sliderValue, sliderUpdate] = useState(initialState);
const [textColorValue, textColorUpdate] = useState(textColor);
const [oppositeColorValue, oppositeColorUpdate] = useState(backgroundColor);
function sliderChange(event){
sliderUpdate(event);
if(props.onChange!==undefined){
props.onChange(event);
}
}
function inputChange(event){
let value = event.target.value;
value = value.replace(/^0+/, '')
if(value===""){
value="0";
}
else if(!/^\d+$/.test(value)){
return;
}
if(value > max){
value = max;
}else if(value < min){
value = min;
}
sliderUpdate(value);
if(props.onChange!==undefined){
props.onChange(value);
}
}
//selected Or Blur
function onFocusOrMouseOut(){
textColorUpdate(textColor);
oppositeColorUpdate(backgroundColor);
}
function onBlur(){
if(sliderValue.length<1){
sliderUpdate(0);
}
}
//hover
function onMouseOver(){
textColorUpdate(hoverColor);
oppositeColorUpdate(textColor);
}
return(<div
onMouseOver={onMouseOver}
onMouseOut={onFocusOrMouseOut}
onFocus={onFocusOrMouseOut}
onBlur={onBlur}
style={{
width:"200px",
margin:"auto",
display:"table",
height:"50px",
padding:"35px 20px 15px",
border:"1px solid "+textColorValue,
borderRadius:"5px",
position:"relative"
}}
>
<p style={{
position: "absolute",
top: "-20px",
margin: "0px",
backgroundColor: backgroundColor,
padding: "5px",
borderRadius: "5px"
}}>{props.title}</p>
<SliderBar
outerStyle={{padding:"20px", display:"table-cell"}}
value={sliderValue}
min={min}
max={max}
onChange={sliderChange}
textColor={textColorValue}
hoverColor={hoverColor}
backgroundColor={oppositeColorValue}
/>
<div
style={{
display:"table-cell",
verticalAlign:"middle",
width:"50px"
}}
>
<input
value={sliderValue}
onChange={inputChange}
style={{
outline:"none",
color:textColor,
textAlign:"center",
backgroundColor: backgroundColor,
border: "1px solid "+textColorValue,
borderRadius:"5px",
width:"30px",
height:"30px",
"&:hover :selected":{
outline:"none",
color:textColorValue,
backgroundColor: backgroundColor,
border: "1px solid "+textColorValue,
}
}}
/>
</div>
</div>);
}
SliderBox.css
.PrivateValueLabel-label-900{
color: "orange";
}
.MuiSlider-root .MuiSlider-valueLabel *{
color: green;
background-color: red;
}
[class^="PrivateValueLabel-label-"]{
color: red;
}