如何实现调整颜色Opacity时同步更新TextField中的Hex值
实现滑块调整透明度时同步更新带透明度的Hex颜色值
当前已实现颜色预览框随opacity滑块变化,但TextField中的Hex值未同步更新为带透明度的8位十六进制格式,可通过以下步骤修复:
关键修改点
- 新增透明度转十六进制的工具函数
- 滑块值变化时同步计算并更新带透明度的Hex值
- 调整初始值与表单验证规则适配8位Hex格式
1. 编写透明度转十六进制工具函数
// 将0-1范围的透明度值转换为两位十六进制字符串(00-FF) const opacityToHex = (opacity) => { const hexNum = Math.round(opacity * 255); const hexStr = hexNum.toString(16); // 补前导零确保是两位 return hexStr.length === 1 ? `0${hexStr}` : hexStr; };
2. 修改滑块 onChange 逻辑
更新updateSlider函数,在设置透明度值后,立即计算并更新带透明度的Hex值:
const updateSlider = (event, newValue) => { settingForm.setFieldValue("opacityValue", newValue); // 提取基础Hex值(去除#,只保留前6位) const baseHex = settingForm.values.hexValue.replace('#', '').slice(0, 6); // 拼接透明度Hex,生成完整8位带透明度的颜色值 const fullHex = `#${baseHex}${opacityToHex(newValue)}`; // 更新TextField的Hex值 settingForm.setFieldValue("hexValue", fullHex); };
3. 调整表单初始值
将初始透明度设为1(完全不透明),Hex值设为带全透明度的8位格式:
initialValues: { hexValue: "#272d85FF", opacityValue: 1 },
4. 更新表单验证规则
确保验证规则支持6位(无透明度)或8位(带透明度)的Hex格式:
// 假设使用Yup作为验证库 const settingFormSchema = Yup.object().shape({ hexValue: Yup.string() .matches(/^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/, "请输入有效的6位或8位Hex颜色值") .required("Hex值为必填项"), opacityValue: Yup.number().min(0).max(1).required("透明度为必填项") });
修改后的完整代码
import React from "react"; import { useFormik } from "formik"; import * as Yup from "yup"; import { Card, CardContent, Grid, Box, Typography, TextField, Slider, Button } from "@mui/material"; import LightModeIcon from '@mui/icons-material/LightMode'; const settingFormSchema = Yup.object().shape({ hexValue: Yup.string() .matches(/^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/, "请输入有效的6位或8位Hex颜色值") .required("Hex值为必填项"), opacityValue: Yup.number().min(0).max(1).required("透明度为必填项") }); export default function ColorPicker() { const [newHexCodes, setNewHexCodes] = React.useState([]); const [opacity, setOpacity] = React.useState([]); // 透明度转十六进制工具函数 const opacityToHex = (opacity) => { const hexNum = Math.round(opacity * 255); const hexStr = hexNum.toString(16); return hexStr.length === 1 ? `0${hexStr}` : hexStr; }; const settingForm = useFormik({ initialValues: { hexValue: "#272d85FF", opacityValue: 1 }, validationSchema: settingFormSchema, onSubmit: (values) => { setNewHexCodes([values.hexValue, ...newHexCodes]); setOpacity([values.opacityValue, ...opacity]); } }); const updateSlider = (event, newValue) => { settingForm.setFieldValue("opacityValue", newValue); const baseHex = settingForm.values.hexValue.replace('#', '').slice(0, 6); const fullHex = `#${baseHex}${opacityToHex(newValue)}`; settingForm.setFieldValue("hexValue", fullHex); }; return ( <Card> <CardContent sx={{ pl: 4, mt: 2 }}> <Grid container justifyContent="space-between" alignItems="center" spacing={2} > <Grid item xs={12} sm={6} md={4}> <Box display="flex" justifyContent="space-between" alignItems="center" flexWrap="wrap" gap={1} > <Box> <Typography variant="subtitle2" noWrap> Hex Value </Typography> </Box> <Box> <TextField size="small" variant="outlined" fullWidth required type="text" placeholder="Enter Hex value" name="hexValue" {...settingForm.getFieldProps("hexValue")} helperText={ settingForm?.touched?.hexValue && settingForm?.errors?.hexValue } error={Boolean( settingForm?.touched?.hexValue && settingForm?.errors?.hexValue )} /> </Box> <Box> <Box display="flex" justifyContent="center" component="span" sx={{ backgroundColor: settingForm.values.hexValue, width: "60px", height: "35px" }} /> </Box> </Box> </Grid> <Grid item xs={12} sm={6} md={4}> <Box display="flex" justifyContent="space-evenly" alignItems="center" gap={2} > <LightModeIcon /> <Box> <Typography variant="subtitle2">opacity</Typography> </Box> <Slider aria-label="Default slider" valueLabelDisplay="auto" onChange={updateSlider} value={settingForm.values.opacityValue} name="opacityValue" step={0.1} max={1} /> </Box> </Grid> <Grid item xs={12} md={2}> <Box display="flex" justifyContent="flex-end"> <Button color="primary" variant="contained" size="large" onClick={settingForm.handleSubmit} > ADD </Button> </Box> </Grid> <h2>you picked {newHexCodes.join(', ')}</h2> </Grid> </CardContent> </Card> ); }
内容的提问来源于stack exchange,提问作者user12302978
相关产品推荐
相关产品推荐

