HTML+Canvas实现 Photoshop 风格的色相取色器界面效果

实现效果:

在这里插入图片描述

实现步骤:

  • 用户交互:通过点击操作选择色相、饱和度和明度,并更新选中的颜色。
  • 渐变与绘图:利用 和 2D 上下文的渐变特性来绘制色相条和颜色面板。
  • 色彩处理:实现了基本的 RGB 转 HEX 颜色转换功能,便于用户查看颜色的十六进制表示。

代码详情:

1. HTML 部分

<div class="color-picker-container">
    <!-- 饱和度与明度面板 -->
    <canvas id="colorPanel" class="color-panel" width="300" height="300"></canvas>
    <!-- 色相条:用于绘制色相条,用户点击它来选择一个色相(Hue) -->
    <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);
});
  • 初始化绘制:调用 drawHueBardrawColorPanel 函数来初始化界面。
  • 事件监听:监听 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]);
        }

        // RGB 转 HEX
        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>
  • 29
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值