实现效果:

实现步骤:
- 用户交互:通过点击操作选择色相、饱和度和明度,并更新选中的颜色。
- 渐变与绘图:利用 和 2D 上下文的渐变特性来绘制色相条和颜色面板。
- 色彩处理:实现了基本的 RGB 转 HEX 颜色转换功能,便于用户查看颜色的十六进制表示。
代码详情:
1. HTML 部分
<div class="color-picker-container">
<canvas id="colorPanel" class="color-panel" width="300" height="300"></canvas>
<canvas id="hueBar" class="hue-bar" width="300" height="30"></canvas>
<div id="colorDisplay" class="color-display"></div>
<span id="colorCode">#ff0000</span>
</div>
2. CSS 样式
.color-picker-container {
display: flex;
flex-direction: column;
gap: 10px;
align-items: center;
}
.color-panel, .hue-bar {
cursor: crosshair;
}
.color-display {
width: 50px;
height: 50px;
border: 1px solid #ccc;
}
3. JavaScript 部分
const colorPanel = document.getElementById('colorPanel');
const hueBar = document.getElementById('hueBar');
const colorDisplay = document.getElementById('colorDisplay');
const colorCode = document.getElementById('colorCode');
const panelCtx = colorPanel.getContext('2d');
const hueCtx = hueBar.getContext('2d');
let hue = 0;
- 获取元素与上下文:通过
getElementById
获取 canvas
元素和显示元素,然后使用 getContext('2d')
获取 2D 绘图上下文,以便后续进行绘图操作。 let hue = 0
:初始化色相值为 0(红色)。
3.1 绘制色相条
function drawHueBar() {
const gradient = hueCtx.createLinearGradient(0, 0, hueBar.width, 0);
gradient.addColorStop(0, 'rgb(255, 0, 0)');
gradient.addColorStop(1 / 6, 'rgb(255, 255, 0)');
gradient.addColorStop(2 / 6, 'rgb(0, 255, 0)');
gradient.addColorStop(3 / 6, 'rgb(0, 255, 255)');
gradient.addColorStop(4 / 6, 'rgb(0, 0, 255)');
gradient.addColorStop(5 / 6, 'rgb(255, 0, 255)');
gradient.addColorStop(1, 'rgb(255, 0, 0)');
hueCtx.fillStyle = gradient;
hueCtx.fillRect(0, 0, hueBar.width, hueBar.height);
}
- 线性渐变:创建一个线性渐变,表示所有色相的变化(红、黄、绿、青、蓝、洋红,再回到红)。
addColorStop
方法设置了每个色相的位置。 - 绘制色相条:使用
fillRect
方法绘制一个填充了渐变的矩形,表示整个色相条。
3.2 **绘制饱和度与明度面板 **
function drawColorPanel(hue) {
const width = colorPanel.width;
const height = colorPanel.height;
const gradientWhite = panelCtx.createLinearGradient(0, 0, width, 0);
gradientWhite.addColorStop(0, 'white');
gradientWhite.addColorStop(1, `hsl(${hue}, 100%, 50%)`);
panelCtx.fillStyle = gradientWhite;
panelCtx.fillRect(0, 0, width, height);
const gradientBlack = panelCtx.createLinearGradient(0, 0, 0, height);
gradientBlack.addColorStop(0, 'rgba(0,0,0,0)');
gradientBlack.addColorStop(1, 'black');
panelCtx.fillStyle = gradientBlack;
panelCtx.fillRect(0, 0, width, height);
}
- 水平渐变(白色到当前色相):在
canvas
上创建一个从白色到选中色相(使用 HSL 色彩模型定义)的水平渐变。 - 垂直渐变(透明到黑色):在
canvas
上创建一个从透明到黑色的垂直渐变。 - 组合渐变:先绘制水平渐变,再绘制垂直渐变,形成类似 Photoshop 的饱和度与明度面板。
3.3 更新选中颜色
function updateSelectedColor(x, y) {
const colorData = panelCtx.getImageData(x, y, 1, 1).data;
const selectedColor = `rgb(${colorData[0]}, ${colorData[1]}, ${colorData[2]})`;
colorDisplay.style.backgroundColor = selectedColor;
colorCode.textContent = rgbToHex(colorData[0], colorData[1], colorData[2]);
}
- 获取颜色数据:使用
getImageData
获取指定位置的像素数据(RGBA 值)。 - 更新显示区域:根据选中的颜色更新颜色显示区域和十六进制颜色代码。
3.4 RGB 转换为 HEX 格式
function rgbToHex(r, g, b) {
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase()}`;
}
- 颜色格式转换:将 RGB 颜色转换为 HEX 格式,以便更直观地显示颜色值。
3.5 初始化和事件处理
drawHueBar();
drawColorPanel(hue);
hueBar.addEventListener('click', (event) => {
const x = event.offsetX;
hue = (x / hueBar.width) * 360;
drawColorPanel(hue);
});
colorPanel.addEventListener('click', (event) => {
const x = event.offsetX;
const y = event.offsetY;
updateSelectedColor(x, y);
});
- 初始化绘制:调用
drawHueBar
和 drawColorPanel
函数来初始化界面。 - 事件监听:监听
click
事件来处理用户交互:
- 色相条点击:根据用户点击的位置计算色相值,并重新绘制颜色面板。
- 颜色面板点击:获取用户点击位置的颜色,并更新显示区域。
完整代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PS 色相取色器示例</title>
<style>
.color-picker-container {
display: flex;
flex-direction: column;
gap: 10px;
align-items: center;
}
.color-panel, .hue-bar {
cursor: crosshair;
}
.color-display {
width: 50px;
height: 50px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<div class="color-picker-container">
<canvas id="colorPanel" class="color-panel" width="300" height="300"></canvas>
<canvas id="hueBar" class="hue-bar" width="300" height="30"></canvas>
<div id="colorDisplay" class="color-display"></div>
<span id="colorCode">#ff0000</span>
</div>
<script>
const colorPanel = document.getElementById('colorPanel');
const hueBar = document.getElementById('hueBar');
const colorDisplay = document.getElementById('colorDisplay');
const colorCode = document.getElementById('colorCode');
const panelCtx = colorPanel.getContext('2d');
const hueCtx = hueBar.getContext('2d');
let hue = 0;
function drawHueBar() {
const gradient = hueCtx.createLinearGradient(0, 0, hueBar.width, 0);
gradient.addColorStop(0, 'rgb(255, 0, 0)');
gradient.addColorStop(1 / 6, 'rgb(255, 255, 0)');
gradient.addColorStop(2 / 6, 'rgb(0, 255, 0)');
gradient.addColorStop(3 / 6, 'rgb(0, 255, 255)');
gradient.addColorStop(4 / 6, 'rgb(0, 0, 255)');
gradient.addColorStop(5 / 6, 'rgb(255, 0, 255)');
gradient.addColorStop(1, 'rgb(255, 0, 0)');
hueCtx.fillStyle = gradient;
hueCtx.fillRect(0, 0, hueBar.width, hueBar.height);
}
function drawColorPanel(hue) {
const width = colorPanel.width;
const height = colorPanel.height;
const gradientWhite = panelCtx.createLinearGradient(0, 0, width, 0);
gradientWhite.addColorStop(0, 'white');
gradientWhite.addColorStop(1, `hsl(${hue}, 100%, 50%)`);
panelCtx.fillStyle = gradientWhite;
panelCtx.fillRect(0, 0, width, height);
const gradientBlack = panelCtx.createLinearGradient(0, 0, 0, height);
gradientBlack.addColorStop(0, 'rgba(0,0,0,0)');
gradientBlack.addColorStop(1, 'black');
panelCtx.fillStyle = gradientBlack;
panelCtx.fillRect(0, 0, width, height);
}
function updateSelectedColor(x, y) {
const colorData = panelCtx.getImageData(x, y, 1, 1).data;
const selectedColor = `rgb(${colorData[0]}, ${colorData[1]}, ${colorData[2]})`;
colorDisplay.style.backgroundColor = selectedColor;
colorCode.textContent = rgbToHex(colorData[0], colorData[1], colorData[2]);
}
function rgbToHex(r, g, b) {
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase()}`;
}
drawHueBar();
drawColorPanel(hue);
hueBar.addEventListener('click', (event) => {
const x = event.offsetX;
hue = (x / hueBar.width) * 360;
drawColorPanel(hue);
});
colorPanel.addEventListener('click', (event) => {
const x = event.offsetX;
const y = event.offsetY;
updateSelectedColor(x, y);
});
</script>
</body>
</html>