引言

在当今的网页应用中,颜色选择器(调色板)是一个不可或缺的UI组件,广泛应用于图像编辑、设计工具、主题定制等场景。jQuery UI作为一个强大的前端框架,提供了丰富的交互组件和灵活的定制能力,使得构建功能强大的调色板应用变得简单而高效。本文将从基础概念出发,逐步深入到高级定制技巧,全面解析如何利用jQuery UI构建出色的调色板应用,从而显著提升用户体验。

jQuery UI基础概述

jQuery UI是基于jQuery的用户界面库,提供了一套完整的交互组件、效果、主题和工具。它使得开发者能够轻松创建具有专业外观和丰富交互的网页应用。

jQuery UI核心特性

  • 丰富的组件库:包括日期选择器、对话框、滑块、进度条等多种UI组件
  • 主题系统:通过ThemeRoller可以轻松创建和定制应用主题
  • 交互助手:提供拖放、排序、选择等交互功能
  • 效果库:包含多种动画和视觉效果
  • 可访问性支持:遵循WAI-ARIA标准,确保应用对所有用户友好

引入jQuery UI

在开始构建调色板应用之前,首先需要引入jQuery和jQuery UI库。可以通过CDN或本地文件引入:

<!-- 引入jQuery --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <!-- 引入jQuery UI --> <link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"> <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script> 

调色板应用基础构建

基本颜色选择器

jQuery UI本身没有直接提供调色板组件,但我们可以利用其现有的组件(如按钮、滑块等)来构建一个功能完善的调色板应用。首先,让我们创建一个基本的颜色选择器:

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>jQuery UI 调色板应用</title> <link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"> <style> .color-picker-container { width: 400px; margin: 50px auto; padding: 20px; border: 1px solid #ddd; border-radius: 5px; box-shadow: 0 0 10px rgba(0,0,0,0.1); } .color-display { width: 100%; height: 100px; border: 1px solid #ccc; border-radius: 3px; margin-bottom: 20px; } .slider-container { margin-bottom: 15px; } .slider-label { display: inline-block; width: 50px; text-align: right; margin-right: 10px; } .color-value { display: inline-block; width: 60px; text-align: left; margin-left: 10px; } .preset-colors { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; } .preset-color { width: 30px; height: 30px; border-radius: 3px; cursor: pointer; border: 1px solid #ddd; } .hex-input { width: 100%; padding: 8px; margin-top: 10px; box-sizing: border-box; } </style> </head> <body> <div class="color-picker-container"> <h2>jQuery UI 调色板</h2> <div class="color-display" id="colorDisplay"></div> <div class="slider-container"> <span class="slider-label">R:</span> <div id="redSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="redValue">255</span> </div> <div class="slider-container"> <span class="slider-label">G:</span> <div id="greenSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="greenValue">0</span> </div> <div class="slider-container"> <span class="slider-label">B:</span> <div id="blueSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="blueValue">0</span> </div> <div class="slider-container"> <span class="slider-label">H:</span> <div id="hueSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="hueValue">0</span> </div> <div class="slider-container"> <span class="slider-label">S:</span> <div id="saturationSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="saturationValue">100</span> </div> <div class="slider-container"> <span class="slider-label">V:</span> <div id="valueSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="valueValue">100</span> </div> <input type="text" class="hex-input" id="hexInput" placeholder="#FF0000"> <div class="preset-colors" id="presetColors"></div> </div> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script> <script> $(function() { // 初始化变量 let red = 255, green = 0, blue = 0; let hue = 0, saturation = 100, value = 100; // 预设颜色 const presetColors = [ '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF', '#FFA500', '#800080', '#008000', '#000080', '#800000', '#008080', '#FFFFFF', '#C0C0C0', '#808080', '#000000', '#FFC0CB', '#A52A2A' ]; // 初始化滑块 $("#redSlider").slider({ min: 0, max: 255, value: red, slide: function(event, ui) { red = ui.value; $("#redValue").text(red); updateColorFromRGB(); } }); $("#greenSlider").slider({ min: 0, max: 255, value: green, slide: function(event, ui) { green = ui.value; $("#greenValue").text(green); updateColorFromRGB(); } }); $("#blueSlider").slider({ min: 0, max: 255, value: blue, slide: function(event, ui) { blue = ui.value; $("#blueValue").text(blue); updateColorFromRGB(); } }); $("#hueSlider").slider({ min: 0, max: 360, value: hue, slide: function(event, ui) { hue = ui.value; $("#hueValue").text(hue); updateColorFromHSV(); } }); $("#saturationSlider").slider({ min: 0, max: 100, value: saturation, slide: function(event, ui) { saturation = ui.value; $("#saturationValue").text(saturation); updateColorFromHSV(); } }); $("#valueSlider").slider({ min: 0, max: 100, value: value, slide: function(event, ui) { value = ui.value; $("#valueValue").text(value); updateColorFromHSV(); } }); // 创建预设颜色 presetColors.forEach(color => { const colorDiv = $('<div class="preset-color"></div>'); colorDiv.css('background-color', color); colorDiv.click(function() { setColorFromHex(color); }); $('#presetColors').append(colorDiv); }); // HEX输入框处理 $('#hexInput').on('input', function() { const hex = $(this).val(); if (/^#[0-9A-F]{6}$/i.test(hex)) { setColorFromHex(hex); } }); // 更新颜色显示 function updateColorDisplay() { const rgbColor = `rgb(${red}, ${green}, ${blue})`; $('#colorDisplay').css('background-color', rgbColor); $('#hexInput').val(rgbToHex(red, green, blue)); } // RGB转HEX function rgbToHex(r, g, b) { return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); } // HEX转RGB function hexToRgb(hex) { const result = /^#?([a-fd]{2})([a-fd]{2})([a-fd]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } // RGB转HSV function rgbToHsv(r, g, b) { r /= 255, g /= 255, b /= 255; const max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, v = max; const d = max - min; s = max == 0 ? 0 : d / max; if (max == min) { h = 0; // 灰色 } else { switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { h: Math.round(h * 360), s: Math.round(s * 100), v: Math.round(v * 100) }; } // HSV转RGB function hsvToRgb(h, s, v) { h /= 360, s /= 100, v /= 100; let r, g, b; const i = Math.floor(h * 6); const f = h * 6 - i; const p = v * (1 - s); const q = v * (1 - f * s); const t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v, g = t, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = t; break; case 3: r = p, g = q, b = v; break; case 4: r = t, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) }; } // 从RGB更新颜色 function updateColorFromRGB() { updateColorDisplay(); // 更新HSV值 const hsv = rgbToHsv(red, green, blue); hue = hsv.h; saturation = hsv.s; value = hsv.v; // 更新HSV滑块 $("#hueSlider").slider("value", hue); $("#saturationSlider").slider("value", saturation); $("#valueSlider").slider("value", value); $("#hueValue").text(hue); $("#saturationValue").text(saturation); $("#valueValue").text(value); } // 从HSV更新颜色 function updateColorFromHSV() { // 更新RGB值 const rgb = hsvToRgb(hue, saturation, value); red = rgb.r; green = rgb.g; blue = rgb.b; // 更新RGB滑块 $("#redSlider").slider("value", red); $("#greenSlider").slider("value", green); $("#blueSlider").slider("value", blue); $("#redValue").text(red); $("#greenValue").text(green); $("#blueValue").text(blue); updateColorDisplay(); } // 从HEX设置颜色 function setColorFromHex(hex) { const rgb = hexToRgb(hex); if (rgb) { red = rgb.r; green = rgb.g; blue = rgb.b; // 更新RGB滑块 $("#redSlider").slider("value", red); $("#greenSlider").slider("value", green); $("#blueSlider").slider("value", blue); $("#redValue").text(red); $("#greenValue").text(green); $("#blueValue").text(blue); updateColorFromRGB(); } } // 初始化颜色显示 updateColorDisplay(); }); </script> </body> </html> 

这个基本的调色板应用包含了以下功能:

  1. RGB颜色滑块控制
  2. HSV颜色滑块控制
  3. 颜色预览区域
  4. HEX颜色值输入
  5. 预设颜色选择

基本组件解析

让我们详细解析上述代码中的关键部分:

1. 滑块组件

jQuery UI的滑块组件(Slider)是调色板应用的核心。我们使用了六个滑块分别控制RGB和HSV值:

$("#redSlider").slider({ min: 0, max: 255, value: red, slide: function(event, ui) { red = ui.value; $("#redValue").text(red); updateColorFromRGB(); } }); 

这段代码创建了一个红色通道的滑块,设置了最小值0、最大值255,并定义了滑动时的回调函数。当用户拖动滑块时,会更新红色值并重新计算显示颜色。

2. 颜色空间转换

调色板应用需要在不同颜色空间之间进行转换,我们实现了RGB、HSV和HEX之间的转换函数:

// RGB转HEX function rgbToHex(r, g, b) { return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); } // HEX转RGB function hexToRgb(hex) { const result = /^#?([a-fd]{2})([a-fd]{2})([a-fd]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } // RGB转HSV function rgbToHsv(r, g, b) { r /= 255, g /= 255, b /= 255; const max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, v = max; const d = max - min; s = max == 0 ? 0 : d / max; if (max == min) { h = 0; // 灰色 } else { switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { h: Math.round(h * 360), s: Math.round(s * 100), v: Math.round(v * 100) }; } // HSV转RGB function hsvToRgb(h, s, v) { h /= 360, s /= 100, v /= 100; let r, g, b; const i = Math.floor(h * 6); const f = h * 6 - i; const p = v * (1 - s); const q = v * (1 - f * s); const t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v, g = t, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = t; break; case 3: r = p, g = q, b = v; break; case 4: r = t, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) }; } 

这些函数使得我们的调色板能够在不同的颜色表示方法之间无缝切换,提供更灵活的颜色选择体验。

3. 预设颜色

预设颜色提供了快速选择常用颜色的功能:

// 创建预设颜色 presetColors.forEach(color => { const colorDiv = $('<div class="preset-color"></div>'); colorDiv.css('background-color', color); colorDiv.click(function() { setColorFromHex(color); }); $('#presetColors').append(colorDiv); }); 

这段代码遍历预设颜色数组,为每个颜色创建一个可点击的色块,当用户点击时,会调用setColorFromHex函数将调色板设置为对应的颜色。

功能扩展:增强调色板应用

基本调色板已经可以满足简单的颜色选择需求,但为了提供更强大的功能和更好的用户体验,我们需要添加更多高级功能。

添加颜色历史记录

颜色历史记录功能允许用户快速访问之前使用过的颜色:

// 在初始化变量部分添加 let colorHistory = []; const maxHistoryItems = 10; // 在HTML中添加历史记录容器 // 在 <div class="preset-colors" id="presetColors"></div> 后添加 <div class="color-history" id="colorHistory"> <h3>颜色历史</h3> <div class="history-colors" id="historyColors"></div> </div> // 在CSS中添加样式 .color-history { margin-top: 20px; } .history-colors { display: flex; flex-wrap: wrap; gap: 5px; } .history-color { width: 25px; height: 25px; border-radius: 3px; cursor: pointer; border: 1px solid #ddd; } // 在JavaScript中添加历史记录功能 function addToColorHistory(hex) { // 检查颜色是否已在历史中 const index = colorHistory.indexOf(hex); if (index !== -1) { // 如果已存在,先移除 colorHistory.splice(index, 1); } // 添加到历史记录开头 colorHistory.unshift(hex); // 限制历史记录数量 if (colorHistory.length > maxHistoryItems) { colorHistory.pop(); } updateColorHistoryDisplay(); } function updateColorHistoryDisplay() { const historyContainer = $('#historyColors'); historyContainer.empty(); colorHistory.forEach(color => { const colorDiv = $('<div class="history-color"></div>'); colorDiv.css('background-color', color); colorDiv.attr('title', color); colorDiv.click(function() { setColorFromHex(color); }); historyContainer.append(colorDiv); }); } // 修改updateColorDisplay函数,在末尾添加 function updateColorDisplay() { const rgbColor = `rgb(${red}, ${green}, ${blue})`; $('#colorDisplay').css('background-color', rgbColor); const hex = rgbToHex(red, green, blue); $('#hexInput').val(hex); // 添加到颜色历史 addToColorHistory(hex); } 

添加颜色吸管工具

颜色吸管工具允许用户从页面上的任何位置提取颜色:

// 在HTML中添加吸管按钮 // 在 <input type="text" class="hex-input" id="hexInput" placeholder="#FF0000"> 后添加 <button id="eyedropperBtn" class="ui-button ui-widget ui-corner-all">吸管工具</button> // 在CSS中添加样式 #eyedropperBtn { margin-top: 10px; width: 100%; } .eyedropper-cursor { cursor: crosshair; } // 在JavaScript中添加吸管工具功能 let isEyedropperActive = false; $('#eyedropperBtn').click(function() { isEyedropperActive = !isEyedropperActive; if (isEyedropperActive) { $(this).text('取消吸管'); $('body').addClass('eyedropper-cursor'); // 创建临时canvas用于颜色采样 const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); // 添加点击事件监听器 $(document).on('click.eyedropper', function(e) { // 获取点击位置的颜色 const x = e.clientX; const y = e.clientY; // 使用html2canvas或类似方法获取屏幕颜色 // 这里简化处理,实际应用中可能需要更复杂的实现 const element = document.elementFromPoint(x, y); if (element) { const bgColor = window.getComputedStyle(element).backgroundColor; if (bgColor && bgColor !== 'rgba(0, 0, 0, 0)' && bgColor !== 'transparent') { // 提取RGB值 const match = bgColor.match(/^rgb((d+),s*(d+),s*(d+))$/); if (match) { const r = parseInt(match[1]); const g = parseInt(match[2]); const b = parseInt(match[3]); // 更新颜色 red = r; green = g; blue = b; // 更新滑块 $("#redSlider").slider("value", red); $("#greenSlider").slider("value", green); $("#blueSlider").slider("value", blue); $("#redValue").text(red); $("#greenValue").text(green); $("#blueValue").text(blue); updateColorFromRGB(); } } } // 关闭吸管工具 isEyedropperActive = false; $('#eyedropperBtn').text('吸管工具'); $('body').removeClass('eyedropper-cursor'); $(document).off('click.eyedropper'); }); } else { $(this).text('吸管工具'); $('body').removeClass('eyedropper-cursor'); $(document).off('click.eyedropper'); } }); 

注意:上述吸管工具的实现是简化版本,实际应用中可能需要使用html2canvas等库来获取准确的屏幕颜色。这里仅展示基本概念。

添加颜色对比度检查器

颜色对比度检查器帮助用户选择具有良好可读性的颜色组合:

// 在HTML中添加对比度检查器 // 在 <div class="color-history" id="colorHistory">...</div> 后添加 <div class="contrast-checker"> <h3>对比度检查器</h3> <div class="contrast-controls"> <label for="bgColor">背景颜色:</label> <input type="text" id="bgColor" class="hex-input" value="#FFFFFF"> <label for="fgColor">前景颜色:</label> <input type="text" id="fgColor" class="hex-input" value="#000000"> <button id="checkContrast" class="ui-button ui-widget ui-corner-all">检查对比度</button> </div> <div class="contrast-result" id="contrastResult"></div> <div class="contrast-preview" id="contrastPreview"> <div class="preview-text">示例文本</div> </div> </div> // 在CSS中添加样式 .contrast-checker { margin-top: 20px; } .contrast-controls { margin-bottom: 10px; } .contrast-controls label { display: block; margin-top: 10px; } .contrast-result { margin: 10px 0; font-weight: bold; } .contrast-preview { padding: 15px; border: 1px solid #ddd; border-radius: 3px; } .preview-text { font-size: 18px; padding: 10px; } // 在JavaScript中添加对比度检查功能 // 计算相对亮度 function getLuminance(r, g, b) { const rsRGB = r / 255; const gsRGB = g / 255; const bsRGB = b / 255; const rLinear = (rsRGB <= 0.03928) ? rsRGB / 12.92 : Math.pow((rsRGB + 0.055) / 1.055, 2.4); const gLinear = (gsRGB <= 0.03928) ? gsRGB / 12.92 : Math.pow((gsRGB + 0.055) / 1.055, 2.4); const bLinear = (bsRGB <= 0.03928) ? bsRGB / 12.92 : Math.pow((bsRGB + 0.055) / 1.055, 2.4); return 0.2126 * rLinear + 0.7152 * gLinear + 0.0722 * bLinear; } // 计算对比度 function getContrastRatio(color1, color2) { const lum1 = getLuminance(color1.r, color1.g, color1.b); const lum2 = getLuminance(color2.r, color2.g, color2.b); const brightest = Math.max(lum1, lum2); const darkest = Math.min(lum1, lum2); return (brightest + 0.05) / (darkest + 0.05); } // 评估对比度等级 function evaluateContrast(ratio) { if (ratio >= 7) { return { level: "AAA", text: "极好", color: "#4CAF50" }; } else if (ratio >= 4.5) { return { level: "AA", text: "良好", color: "#8BC34A" }; } else if (ratio >= 3) { return { level: "AA Large", text: "一般(大文本)", color: "#FFC107" }; } else { return { level: "Fail", text: "不足", color: "#F44336" }; } } // 检查对比度按钮事件 $('#checkContrast').click(function() { const bgColorHex = $('#bgColor').val(); const fgColorHex = $('#fgColor').val(); if (!/^#[0-9A-F]{6}$/i.test(bgColorHex) || !/^#[0-9A-F]{6}$/i.test(fgColorHex)) { $('#contrastResult').html('<span style="color: #F44336;">请输入有效的十六进制颜色值</span>'); return; } const bgColorRgb = hexToRgb(bgColorHex); const fgColorRgb = hexToRgb(fgColorHex); const ratio = getContrastRatio(bgColorRgb, fgColorRgb); const evaluation = evaluateContrast(ratio); $('#contrastResult').html( `对比度: <strong>${ratio.toFixed(2)}:1</strong> - ` + `<span style="color: ${evaluation.color}">${evaluation.level} (${evaluation.text})</span>` ); // 更新预览 $('#contrastPreview').css('background-color', bgColorHex); $('.preview-text').css('color', fgColorHex); }); // 背景颜色输入框事件 $('#bgColor').on('input', function() { const hex = $(this).val(); if (/^#[0-9A-F]{6}$/i.test(hex)) { $('#contrastPreview').css('background-color', hex); } }); // 前景颜色输入框事件 $('#fgColor').on('input', function() { const hex = $(this).val(); if (/^#[0-9A-F]{6}$/i.test(hex)) { $('.preview-text').css('color', hex); } }); // 将当前选中的颜色应用到对比度检查器 function updateContrastChecker() { const currentColor = rgbToHex(red, green, blue); $('#fgColor').val(currentColor); $('.preview-text').css('color', currentColor); // 如果背景颜色未设置,则使用当前颜色的对比色 if (!$('#bgColor').val() || $('#bgColor').val() === '#FFFFFF') { const luminance = getLuminance(red, green, blue); const contrastColor = luminance > 0.5 ? '#000000' : '#FFFFFF'; $('#bgColor').val(contrastColor); $('#contrastPreview').css('background-color', contrastColor); } // 自动检查对比度 $('#checkContrast').click(); } // 修改updateColorDisplay函数,在末尾添加 function updateColorDisplay() { const rgbColor = `rgb(${red}, ${green}, ${blue})`; $('#colorDisplay').css('background-color', rgbColor); const hex = rgbToHex(red, green, blue); $('#hexInput').val(hex); // 添加到颜色历史 addToColorHistory(hex); // 更新对比度检查器 updateContrastChecker(); } 

添加颜色方案生成器

颜色方案生成器可以根据当前选择的颜色生成协调的颜色组合:

// 在HTML中添加颜色方案生成器 // 在 <div class="contrast-checker">...</div> 后添加 <div class="color-scheme-generator"> <h3>颜色方案生成器</h3> <div class="scheme-controls"> <button id="complementaryScheme" class="ui-button ui-widget ui-corner-all">互补色</button> <button id="triadicScheme" class="ui-button ui-widget ui-corner-all">三角色</button> <button id="analogousScheme" class="ui-button ui-widget ui-corner-all">类似色</button> <button id="monochromaticScheme" class="ui-button ui-widget ui-corner-all">单色</button> </div> <div class="scheme-colors" id="schemeColors"></div> </div> // 在CSS中添加样式 .color-scheme-generator { margin-top: 20px; } .scheme-controls { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 10px; } .scheme-controls button { flex: 1; min-width: 100px; } .scheme-colors { display: flex; flex-wrap: wrap; gap: 10px; } .scheme-color { width: 60px; height: 60px; border-radius: 3px; cursor: pointer; border: 1px solid #ddd; display: flex; flex-direction: column; align-items: center; justify-content: center; } .scheme-color-hex { font-size: 10px; margin-top: 5px; background: rgba(255, 255, 255, 0.7); padding: 2px 4px; border-radius: 2px; } // 在JavaScript中添加颜色方案生成功能 // HSV调整函数 function adjustHSV(h, s, v, hAdjust = 0, sAdjust = 0, vAdjust = 0) { h = (h + hAdjust + 360) % 360; s = Math.max(0, Math.min(100, s + sAdjust)); v = Math.max(0, Math.min(100, v + vAdjust)); const rgb = hsvToRgb(h, s, v); return { h: h, s: s, v: v, r: rgb.r, g: rgb.g, b: rgb.b, hex: rgbToHex(rgb.r, rgb.g, rgb.b) }; } // 生成互补色方案 function generateComplementaryScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: (currentHsv.h + 180) % 360, s: currentHsv.s, v: currentHsv.v, name: "互补色" } ]; displayColorScheme(colors); } // 生成三角色方案 function generateTriadicScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: (currentHsv.h + 120) % 360, s: currentHsv.s, v: currentHsv.v, name: "第二色" }, { h: (currentHsv.h + 240) % 360, s: currentHsv.s, v: currentHsv.v, name: "第三色" } ]; displayColorScheme(colors); } // 生成类似色方案 function generateAnalogousScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: (currentHsv.h - 30 + 360) % 360, s: currentHsv.s, v: currentHsv.v, name: "类似色1" }, { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: (currentHsv.h + 30) % 360, s: currentHsv.s, v: currentHsv.v, name: "类似色2" } ]; displayColorScheme(colors); } // 生成单色方案 function generateMonochromaticScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: currentHsv.h, s: currentHsv.s, v: Math.min(100, currentHsv.v + 40), name: "亮色" }, { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: currentHsv.h, s: currentHsv.s, v: Math.max(0, currentHsv.v - 40), name: "暗色" } ]; displayColorScheme(colors); } // 显示颜色方案 function displayColorScheme(colors) { const schemeContainer = $('#schemeColors'); schemeContainer.empty(); colors.forEach(color => { const rgb = hsvToRgb(color.h, color.s, color.v); const hex = rgbToHex(rgb.r, rgb.g, rgb.b); const colorDiv = $(` <div class="scheme-color" title="${color.name}: ${hex}"> <div class="scheme-color-hex">${hex}</div> </div> `); colorDiv.css('background-color', hex); colorDiv.click(function() { setColorFromHex(hex); }); schemeContainer.append(colorDiv); }); } // 绑定颜色方案按钮事件 $('#complementaryScheme').click(generateComplementaryScheme); $('#triadicScheme').click(generateTriadicScheme); $('#analogousScheme').click(generateAnalogousScheme); $('#monochromaticScheme').click(generateMonochromaticScheme); // 修改updateColorDisplay函数,在末尾添加 function updateColorDisplay() { const rgbColor = `rgb(${red}, ${green}, ${blue})`; $('#colorDisplay').css('background-color', rgbColor); const hex = rgbToHex(red, green, blue); $('#hexInput').val(hex); // 添加到颜色历史 addToColorHistory(hex); // 更新对比度检查器 updateContrastChecker(); // 自动生成互补色方案 generateComplementaryScheme(); } 

高级定制技巧

主题定制

jQuery UI提供了强大的主题定制功能,通过ThemeRoller可以轻松创建符合品牌风格的自定义主题。

使用ThemeRoller

  1. 访问 jQuery UI ThemeRoller
  2. 调整各种设置,如颜色、字体、圆角等
  3. 下载自定义主题

应用自定义主题

将下载的主题CSS文件替换默认的jQuery UI主题:

<!-- 替换默认主题 --> <link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"> <!-- 使用自定义主题 --> <link rel="stylesheet" href="path/to/your/custom-theme/jquery-ui.css"> 

动态切换主题

实现动态主题切换功能:

// 在HTML中添加主题选择器 // 在 <div class="color-picker-container"> 的开头添加 <div class="theme-selector"> <label for="themeSelect">选择主题:</label> <select id="themeSelect"> <option value="base">Base</option> <option value="black-tie">Black Tie</option> <option value="blitzer">Blitzer</option> <option value="cupertino">Cupertino</option> <option value="dark-hive">Dark Hive</option> <option value="dot-luv">Dot Luv</option> <option value="eggplant">Eggplant</option> <option value="excite-bike">Excite Bike</option> <option value="flick">Flick</option> <option value="hot-sneaks">Hot Sneaks</option> <option value="humanity">Humanity</option> <option value="le-frog">Le Frog</option> <option value="mint-choc">Mint Choc</option> <option value="overcast">Overcast</option> <option value="pepper-grinder">Pepper Grinder</option> <option value="redmond">Redmond</option> <option value="smoothness">Smoothness</option> <option value="south-street">South Street</option> <option value="start">Start</option> <option value="sunny">Sunny</option> <option value="swanky-purse">Swanky Purse</option> <option value="trontastic">Trontastic</option> <option value="ui-darkness">UI Darkness</option> <option value="ui-lightness">UI Lightness</option> <option value="vader">Vader</option> </select> </div> // 在CSS中添加样式 .theme-selector { margin-bottom: 15px; } .theme-selector label { margin-right: 10px; } // 在JavaScript中添加主题切换功能 $('#themeSelect').change(function() { const theme = $(this).val(); const themeUrl = `https://code.jquery.com/ui/1.13.2/themes/${theme}/jquery-ui.css`; // 移除旧的jQuery UI主题CSS $('link[href*="jquery-ui.css"]').not('[href*="custom"]').remove(); // 添加新的主题CSS $('<link>', { rel: 'stylesheet', type: 'text/css', href: themeUrl }).appendTo('head'); }); 

高级事件处理

jQuery UI提供了丰富的事件系统,我们可以利用这些事件来增强调色板应用的交互性。

添加键盘快捷键

// 在JavaScript中添加键盘快捷键支持 $(document).keydown(function(e) { // Alt+C: 复制当前颜色的HEX值 if (e.altKey && e.keyCode === 67) { // C键 const hex = rgbToHex(red, green, blue); copyToClipboard(hex); showNotification(`已复制颜色: ${hex}`); } // Alt+H: 显示/隐藏颜色历史 if (e.altKey && e.keyCode === 72) { // H键 $('.color-history').toggle(); } // Alt+S: 显示/隐藏颜色方案生成器 if (e.altKey && e.keyCode === 83) { // S键 $('.color-scheme-generator').toggle(); } }); // 复制到剪贴板函数 function copyToClipboard(text) { const textarea = document.createElement('textarea'); textarea.value = text; document.body.appendChild(textarea); textarea.select(); document.execCommand('copy'); document.body.removeChild(textarea); } // 显示通知函数 function showNotification(message) { const notification = $(` <div class="notification"> ${message} </div> `); notification.css({ position: 'fixed', bottom: '20px', right: '20px', background: '#333', color: '#fff', padding: '10px 15px', borderRadius: '4px', zIndex: 1000, opacity: 0.9 }); $('body').append(notification); // 3秒后淡出并移除 setTimeout(function() { notification.fadeOut(300, function() { $(this).remove(); }); }, 3000); } 

添加拖放功能

使用jQuery UI的拖放功能,允许用户将颜色拖放到其他元素:

// 使颜色显示区域可拖动 $("#colorDisplay").draggable({ helper: 'clone', revert: 'invalid', start: function(event, ui) { ui.helper.css('width', '50px'); ui.helper.css('height', '50px'); ui.helper.css('zIndex', 1000); } }); // 使预设颜色和历史颜色可拖动 $(document).on('mousedown', '.preset-color, .history-color, .scheme-color', function() { $(this).draggable({ helper: 'clone', revert: 'invalid', start: function(event, ui) { ui.helper.css('width', '30px'); ui.helper.css('height', '30px'); ui.helper.css('zIndex', 1000); } }); }); // 创建可放置区域 $('.color-display, .preset-colors, .history-colors, .scheme-colors').droppable({ accept: '.preset-color, .history-color, .scheme-color, #colorDisplay', drop: function(event, ui) { const color = ui.draggable.css('background-color'); if (color && color !== 'rgba(0, 0, 0, 0)' && color !== 'transparent') { // 提取RGB值 const match = color.match(/^rgb((d+),s*(d+),s*(d+))$/); if (match) { const r = parseInt(match[1]); const g = parseInt(match[2]); const b = parseInt(match[3]); // 更新颜色 red = r; green = g; blue = b; // 更新滑块 $("#redSlider").slider("value", red); $("#greenSlider").slider("value", green); $("#blueSlider").slider("value", blue); $("#redValue").text(red); $("#greenValue").text(green); $("#blueValue").text(blue); updateColorFromRGB(); } } } }); 

插件开发:创建自定义调色板组件

将调色板功能封装为可重用的jQuery插件:

// 创建jQuery插件 (function($) { $.fn.colorPicker = function(options) { // 默认设置 const settings = $.extend({ showRGB: true, showHSV: true, showHex: true, showPresets: true, showHistory: true, showContrast: true, showScheme: true, presetColors: [ '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF', '#FFA500', '#800080', '#008000', '#000080', '#800000', '#008080', '#FFFFFF', '#C0C0C0', '#808080', '#000000', '#FFC0CB', '#A52A2A' ], maxHistoryItems: 10, defaultColor: '#FF0000', onChange: null }, options); // 为每个匹配的元素初始化调色板 return this.each(function() { const container = $(this); // 初始化变量 let red = 255, green = 0, blue = 0; let hue = 0, saturation = 100, value = 100; let colorHistory = []; // 设置默认颜色 if (settings.defaultColor) { const rgb = hexToRgb(settings.defaultColor); if (rgb) { red = rgb.r; green = rgb.g; blue = rgb.b; const hsv = rgbToHsv(red, green, blue); hue = hsv.h; saturation = hsv.s; value = hsv.v; } } // 构建调色板HTML let html = ` <div class="color-picker-container"> <h2>jQuery UI 调色板</h2> <div class="color-display" id="colorDisplay"></div> `; // RGB滑块 if (settings.showRGB) { html += ` <div class="slider-container"> <span class="slider-label">R:</span> <div id="redSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="redValue">${red}</span> </div> <div class="slider-container"> <span class="slider-label">G:</span> <div id="greenSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="greenValue">${green}</span> </div> <div class="slider-container"> <span class="slider-label">B:</span> <div id="blueSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="blueValue">${blue}</span> </div> `; } // HSV滑块 if (settings.showHSV) { html += ` <div class="slider-container"> <span class="slider-label">H:</span> <div id="hueSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="hueValue">${hue}</span> </div> <div class="slider-container"> <span class="slider-label">S:</span> <div id="saturationSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="saturationValue">${saturation}</span> </div> <div class="slider-container"> <span class="slider-label">V:</span> <div id="valueSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="valueValue">${value}</span> </div> `; } // HEX输入 if (settings.showHex) { html += `<input type="text" class="hex-input" id="hexInput" placeholder="#FF0000">`; } // 预设颜色 if (settings.showPresets) { html += `<div class="preset-colors" id="presetColors"></div>`; } // 颜色历史 if (settings.showHistory) { html += ` <div class="color-history" id="colorHistory"> <h3>颜色历史</h3> <div class="history-colors" id="historyColors"></div> </div> `; } // 对比度检查器 if (settings.showContrast) { html += ` <div class="contrast-checker"> <h3>对比度检查器</h3> <div class="contrast-controls"> <label for="bgColor">背景颜色:</label> <input type="text" id="bgColor" class="hex-input" value="#FFFFFF"> <label for="fgColor">前景颜色:</label> <input type="text" id="fgColor" class="hex-input" value="#000000"> <button id="checkContrast" class="ui-button ui-widget ui-corner-all">检查对比度</button> </div> <div class="contrast-result" id="contrastResult"></div> <div class="contrast-preview" id="contrastPreview"> <div class="preview-text">示例文本</div> </div> </div> `; } // 颜色方案生成器 if (settings.showScheme) { html += ` <div class="color-scheme-generator"> <h3>颜色方案生成器</h3> <div class="scheme-controls"> <button id="complementaryScheme" class="ui-button ui-widget ui-corner-all">互补色</button> <button id="triadicScheme" class="ui-button ui-widget ui-corner-all">三角色</button> <button id="analogousScheme" class="ui-button ui-widget ui-corner-all">类似色</button> <button id="monochromaticScheme" class="ui-button ui-widget ui-corner-all">单色</button> </div> <div class="scheme-colors" id="schemeColors"></div> </div> `; } html += `</div>`; // 添加HTML到容器 container.html(html); // 初始化滑块 if (settings.showRGB) { $("#redSlider", container).slider({ min: 0, max: 255, value: red, slide: function(event, ui) { red = ui.value; $("#redValue", container).text(red); updateColorFromRGB(); } }); $("#greenSlider", container).slider({ min: 0, max: 255, value: green, slide: function(event, ui) { green = ui.value; $("#greenValue", container).text(green); updateColorFromRGB(); } }); $("#blueSlider", container).slider({ min: 0, max: 255, value: blue, slide: function(event, ui) { blue = ui.value; $("#blueValue", container).text(blue); updateColorFromRGB(); } }); } if (settings.showHSV) { $("#hueSlider", container).slider({ min: 0, max: 360, value: hue, slide: function(event, ui) { hue = ui.value; $("#hueValue", container).text(hue); updateColorFromHSV(); } }); $("#saturationSlider", container).slider({ min: 0, max: 100, value: saturation, slide: function(event, ui) { saturation = ui.value; $("#saturationValue", container).text(saturation); updateColorFromHSV(); } }); $("#valueSlider", container).slider({ min: 0, max: 100, value: value, slide: function(event, ui) { value = ui.value; $("#valueValue", container).text(value); updateColorFromHSV(); } }); } // 创建预设颜色 if (settings.showPresets) { settings.presetColors.forEach(color => { const colorDiv = $('<div class="preset-color"></div>'); colorDiv.css('background-color', color); colorDiv.click(function() { setColorFromHex(color); }); $('#presetColors', container).append(colorDiv); }); } // HEX输入框处理 if (settings.showHex) { $('#hexInput', container).on('input', function() { const hex = $(this).val(); if (/^#[0-9A-F]{6}$/i.test(hex)) { setColorFromHex(hex); } }); } // 对比度检查器事件 if (settings.showContrast) { $('#checkContrast', container).click(function() { const bgColorHex = $('#bgColor', container).val(); const fgColorHex = $('#fgColor', container).val(); if (!/^#[0-9A-F]{6}$/i.test(bgColorHex) || !/^#[0-9A-F]{6}$/i.test(fgColorHex)) { $('#contrastResult', container).html('<span style="color: #F44336;">请输入有效的十六进制颜色值</span>'); return; } const bgColorRgb = hexToRgb(bgColorHex); const fgColorRgb = hexToRgb(fgColorHex); const ratio = getContrastRatio(bgColorRgb, fgColorRgb); const evaluation = evaluateContrast(ratio); $('#contrastResult', container).html( `对比度: <strong>${ratio.toFixed(2)}:1</strong> - ` + `<span style="color: ${evaluation.color}">${evaluation.level} (${evaluation.text})</span>` ); // 更新预览 $('#contrastPreview', container).css('background-color', bgColorHex); $('.preview-text', container).css('color', fgColorHex); }); // 背景颜色输入框事件 $('#bgColor', container).on('input', function() { const hex = $(this).val(); if (/^#[0-9A-F]{6}$/i.test(hex)) { $('#contrastPreview', container).css('background-color', hex); } }); // 前景颜色输入框事件 $('#fgColor', container).on('input', function() { const hex = $(this).val(); if (/^#[0-9A-F]{6}$/i.test(hex)) { $('.preview-text', container).css('color', hex); } }); } // 颜色方案生成器事件 if (settings.showScheme) { $('#complementaryScheme', container).click(generateComplementaryScheme); $('#triadicScheme', container).click(generateTriadicScheme); $('#analogousScheme', container).click(generateAnalogousScheme); $('#monochromaticScheme', container).click(generateMonochromaticScheme); } // 颜色转换函数 function rgbToHex(r, g, b) { return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); } function hexToRgb(hex) { const result = /^#?([a-fd]{2})([a-fd]{2})([a-fd]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } function rgbToHsv(r, g, b) { r /= 255, g /= 255, b /= 255; const max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, v = max; const d = max - min; s = max == 0 ? 0 : d / max; if (max == min) { h = 0; // 灰色 } else { switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { h: Math.round(h * 360), s: Math.round(s * 100), v: Math.round(v * 100) }; } function hsvToRgb(h, s, v) { h /= 360, s /= 100, v /= 100; let r, g, b; const i = Math.floor(h * 6); const f = h * 6 - i; const p = v * (1 - s); const q = v * (1 - f * s); const t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v, g = t, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = t; break; case 3: r = p, g = q, b = v; break; case 4: r = t, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) }; } // 对比度计算函数 function getLuminance(r, g, b) { const rsRGB = r / 255; const gsRGB = g / 255; const bsRGB = b / 255; const rLinear = (rsRGB <= 0.03928) ? rsRGB / 12.92 : Math.pow((rsRGB + 0.055) / 1.055, 2.4); const gLinear = (gsRGB <= 0.03928) ? gsRGB / 12.92 : Math.pow((gsRGB + 0.055) / 1.055, 2.4); const bLinear = (bsRGB <= 0.03928) ? bsRGB / 12.92 : Math.pow((bsRGB + 0.055) / 1.055, 2.4); return 0.2126 * rLinear + 0.7152 * gLinear + 0.0722 * bLinear; } function getContrastRatio(color1, color2) { const lum1 = getLuminance(color1.r, color1.g, color1.b); const lum2 = getLuminance(color2.r, color2.g, color2.b); const brightest = Math.max(lum1, lum2); const darkest = Math.min(lum1, lum2); return (brightest + 0.05) / (darkest + 0.05); } function evaluateContrast(ratio) { if (ratio >= 7) { return { level: "AAA", text: "极好", color: "#4CAF50" }; } else if (ratio >= 4.5) { return { level: "AA", text: "良好", color: "#8BC34A" }; } else if (ratio >= 3) { return { level: "AA Large", text: "一般(大文本)", color: "#FFC107" }; } else { return { level: "Fail", text: "不足", color: "#F44336" }; } } // 颜色方案生成函数 function adjustHSV(h, s, v, hAdjust = 0, sAdjust = 0, vAdjust = 0) { h = (h + hAdjust + 360) % 360; s = Math.max(0, Math.min(100, s + sAdjust)); v = Math.max(0, Math.min(100, v + vAdjust)); const rgb = hsvToRgb(h, s, v); return { h: h, s: s, v: v, r: rgb.r, g: rgb.g, b: rgb.b, hex: rgbToHex(rgb.r, rgb.g, rgb.b) }; } function generateComplementaryScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: (currentHsv.h + 180) % 360, s: currentHsv.s, v: currentHsv.v, name: "互补色" } ]; displayColorScheme(colors); } function generateTriadicScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: (currentHsv.h + 120) % 360, s: currentHsv.s, v: currentHsv.v, name: "第二色" }, { h: (currentHsv.h + 240) % 360, s: currentHsv.s, v: currentHsv.v, name: "第三色" } ]; displayColorScheme(colors); } function generateAnalogousScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: (currentHsv.h - 30 + 360) % 360, s: currentHsv.s, v: currentHsv.v, name: "类似色1" }, { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: (currentHsv.h + 30) % 360, s: currentHsv.s, v: currentHsv.v, name: "类似色2" } ]; displayColorScheme(colors); } function generateMonochromaticScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: currentHsv.h, s: currentHsv.s, v: Math.min(100, currentHsv.v + 40), name: "亮色" }, { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: currentHsv.h, s: currentHsv.s, v: Math.max(0, currentHsv.v - 40), name: "暗色" } ]; displayColorScheme(colors); } function displayColorScheme(colors) { const schemeContainer = $('#schemeColors', container); schemeContainer.empty(); colors.forEach(color => { const rgb = hsvToRgb(color.h, color.s, color.v); const hex = rgbToHex(rgb.r, rgb.g, rgb.b); const colorDiv = $(` <div class="scheme-color" title="${color.name}: ${hex}"> <div class="scheme-color-hex">${hex}</div> </div> `); colorDiv.css('background-color', hex); colorDiv.click(function() { setColorFromHex(hex); }); schemeContainer.append(colorDiv); }); } // 颜色历史函数 function addToColorHistory(hex) { // 检查颜色是否已在历史中 const index = colorHistory.indexOf(hex); if (index !== -1) { // 如果已存在,先移除 colorHistory.splice(index, 1); } // 添加到历史记录开头 colorHistory.unshift(hex); // 限制历史记录数量 if (colorHistory.length > settings.maxHistoryItems) { colorHistory.pop(); } updateColorHistoryDisplay(); } function updateColorHistoryDisplay() { const historyContainer = $('#historyColors', container); historyContainer.empty(); colorHistory.forEach(color => { const colorDiv = $('<div class="history-color"></div>'); colorDiv.css('background-color', color); colorDiv.attr('title', color); colorDiv.click(function() { setColorFromHex(color); }); historyContainer.append(colorDiv); }); } // 更新颜色函数 function updateColorDisplay() { const rgbColor = `rgb(${red}, ${green}, ${blue})`; $('#colorDisplay', container).css('background-color', rgbColor); const hex = rgbToHex(red, green, blue); $('#hexInput', container).val(hex); // 添加到颜色历史 if (settings.showHistory) { addToColorHistory(hex); } // 更新对比度检查器 if (settings.showContrast) { updateContrastChecker(); } // 自动生成互补色方案 if (settings.showScheme) { generateComplementaryScheme(); } // 触发onChange回调 if (typeof settings.onChange === 'function') { settings.onChange({ hex: hex, rgb: { r: red, g: green, b: blue }, hsv: { h: hue, s: saturation, v: value } }); } } function updateColorFromRGB() { updateColorDisplay(); // 更新HSV值 const hsv = rgbToHsv(red, green, blue); hue = hsv.h; saturation = hsv.s; value = hsv.v; // 更新HSV滑块 if (settings.showHSV) { $("#hueSlider", container).slider("value", hue); $("#saturationSlider", container).slider("value", saturation); $("#valueSlider", container).slider("value", value); $("#hueValue", container).text(hue); $("#saturationValue", container).text(saturation); $("#valueValue", container).text(value); } } function updateColorFromHSV() { // 更新RGB值 const rgb = hsvToRgb(hue, saturation, value); red = rgb.r; green = rgb.g; blue = rgb.b; // 更新RGB滑块 if (settings.showRGB) { $("#redSlider", container).slider("value", red); $("#greenSlider", container).slider("value", green); $("#blueSlider", container).slider("value", blue); $("#redValue", container).text(red); $("#greenValue", container).text(green); $("#blueValue", container).text(blue); } updateColorDisplay(); } function setColorFromHex(hex) { const rgb = hexToRgb(hex); if (rgb) { red = rgb.r; green = rgb.g; blue = rgb.b; // 更新RGB滑块 if (settings.showRGB) { $("#redSlider", container).slider("value", red); $("#greenSlider", container).slider("value", green); $("#blueSlider", container).slider("value", blue); $("#redValue", container).text(red); $("#greenValue", container).text(green); $("#blueValue", container).text(blue); } updateColorFromRGB(); } } function updateContrastChecker() { const currentColor = rgbToHex(red, green, blue); $('#fgColor', container).val(currentColor); $('.preview-text', container).css('color', currentColor); // 如果背景颜色未设置,则使用当前颜色的对比色 if (!$('#bgColor', container).val() || $('#bgColor', container).val() === '#FFFFFF') { const luminance = getLuminance(red, green, blue); const contrastColor = luminance > 0.5 ? '#000000' : '#FFFFFF'; $('#bgColor', container).val(contrastColor); $('#contrastPreview', container).css('background-color', contrastColor); } // 自动检查对比度 $('#checkContrast', container).click(); } // 初始化颜色显示 updateColorDisplay(); }); }; })(jQuery); 

使用这个插件:

<!-- 基本用法 --> <div id="basicColorPicker"></div> <script> $(function() { $('#basicColorPicker').colorPicker(); }); </script> <!-- 自定义选项 --> <div id="customColorPicker"></div> <script> $(function() { $('#customColorPicker').colorPicker({ showHSV: false, showContrast: false, defaultColor: '#3498db', onChange: function(color) { console.log('颜色已更改为:', color); } }); }); </script> 

性能优化

事件节流

在频繁触发的事件(如滑块拖动)中使用节流技术,避免过多的计算和DOM操作:

// 添加节流函数 function throttle(func, delay) { let lastCall = 0; return function(...args) { const now = new Date().getTime(); if (now - lastCall < delay) { return; } lastCall = now; return func(...args); }; } // 使用节流函数包装颜色更新函数 const throttledUpdateColorFromRGB = throttle(updateColorFromRGB, 50); const throttledUpdateColorFromHSV = throttle(updateColorFromHSV, 50); // 修改滑块事件处理 $("#redSlider").slider({ min: 0, max: 255, value: red, slide: function(event, ui) { red = ui.value; $("#redValue").text(red); throttledUpdateColorFromRGB(); } }); // 对其他滑块也进行相同修改 

DOM操作优化

减少DOM操作次数,使用文档片段和批量更新:

// 使用文档片段批量添加元素 function addPresetColors() { const fragment = document.createDocumentFragment(); presetColors.forEach(color => { const colorDiv = document.createElement('div'); colorDiv.className = 'preset-color'; colorDiv.style.backgroundColor = color; colorDiv.addEventListener('click', function() { setColorFromHex(color); }); fragment.appendChild(colorDiv); }); document.getElementById('presetColors').appendChild(fragment); } // 使用jQuery的批量操作 function updateColorHistoryDisplay() { const historyContainer = $('#historyColors'); // 使用detach()临时移除元素以提高性能 const historyColors = historyContainer.children().detach(); // 清空容器 historyContainer.empty(); // 批量添加新元素 const elements = colorHistory.map(color => { return $('<div class="history-color"></div>') .css('background-color', color) .attr('title', color) .click(function() { setColorFromHex(color); }); }); historyContainer.append(elements); } 

延迟加载

对于非关键功能,使用延迟加载策略:

// 延迟加载对比度检查器 let contrastCheckerLoaded = false; function loadContrastChecker() { if (contrastCheckerLoaded) return; contrastCheckerLoaded = true; // 动态加载对比度检查器HTML $.get('contrast-checker.html', function(data) { $('.color-picker-container').append(data); // 初始化对比度检查器事件 $('#checkContrast').click(function() { // 对比度检查逻辑 }); }); } // 当用户滚动到对比度检查器区域时再加载 $(window).scroll(function() { const contrastCheckerOffset = $('.contrast-checker').offset(); if (contrastCheckerOffset && $(window).scrollTop() + $(window).height() > contrastCheckerOffset.top) { loadContrastChecker(); } }); 

缓存计算结果

缓存颜色转换等计算密集型操作的结果:

// 创建颜色转换缓存 const colorConversionCache = new Map(); // 带缓存的RGB转HEX函数 function rgbToHexCached(r, g, b) { const cacheKey = `${r},${g},${b}`; if (colorConversionCache.has(cacheKey)) { return colorConversionCache.get(cacheKey); } const hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); // 限制缓存大小 if (colorConversionCache.size > 1000) { // 清除最早的缓存项 const firstKey = colorConversionCache.keys().next().value; colorConversionCache.delete(firstKey); } colorConversionCache.set(cacheKey, hex); return hex; } // 带缓存的HEX转RGB函数 function hexToRgbCached(hex) { if (colorConversionCache.has(hex)) { return colorConversionCache.get(hex); } const result = /^#?([a-fd]{2})([a-fd]{2})([a-fd]{2})$/i.exec(hex); const rgb = result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; if (rgb) { // 限制缓存大小 if (colorConversionCache.size > 1000) { // 清除最早的缓存项 const firstKey = colorConversionCache.keys().next().value; colorConversionCache.delete(firstKey); } colorConversionCache.set(hex, rgb); } return rgb; } 

实战案例:完整的调色板应用

下面是一个完整的调色板应用示例,整合了前面讨论的所有功能:

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>高级jQuery UI调色板应用</title> <link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"> <style> body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; } .app-container { max-width: 1200px; margin: 0 auto; display: flex; flex-wrap: wrap; gap: 20px; } .color-picker-panel { flex: 1; min-width: 400px; background-color: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); padding: 20px; } .preview-panel { flex: 1; min-width: 300px; background-color: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); padding: 20px; } .color-picker-container { width: 100%; } .color-display { width: 100%; height: 120px; border: 1px solid #ccc; border-radius: 5px; margin-bottom: 20px; position: relative; overflow: hidden; } .color-info { position: absolute; bottom: 0; left: 0; right: 0; background: rgba(0,0,0,0.7); color: white; padding: 8px; font-size: 14px; } .slider-container { margin-bottom: 15px; } .slider-label { display: inline-block; width: 50px; text-align: right; margin-right: 10px; } .color-value { display: inline-block; width: 60px; text-align: left; margin-left: 10px; } .preset-colors { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 20px; } .preset-color { width: 30px; height: 30px; border-radius: 3px; cursor: pointer; border: 1px solid #ddd; transition: transform 0.2s; } .preset-color:hover { transform: scale(1.1); } .hex-input { width: 100%; padding: 10px; margin-top: 10px; box-sizing: border-box; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; } .color-history { margin-top: 20px; } .history-colors { display: flex; flex-wrap: wrap; gap: 5px; } .history-color { width: 25px; height: 25px; border-radius: 3px; cursor: pointer; border: 1px solid #ddd; } .contrast-checker { margin-top: 20px; } .contrast-controls { margin-bottom: 10px; } .contrast-controls label { display: block; margin-top: 10px; font-weight: bold; } .contrast-result { margin: 10px 0; font-weight: bold; } .contrast-preview { padding: 15px; border: 1px solid #ddd; border-radius: 5px; } .preview-text { font-size: 18px; padding: 10px; } .color-scheme-generator { margin-top: 20px; } .scheme-controls { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 10px; } .scheme-controls button { flex: 1; min-width: 100px; } .scheme-colors { display: flex; flex-wrap: wrap; gap: 10px; } .scheme-color { width: 60px; height: 60px; border-radius: 5px; cursor: pointer; border: 1px solid #ddd; display: flex; flex-direction: column; align-items: center; justify-content: center; transition: transform 0.2s; } .scheme-color:hover { transform: scale(1.05); } .scheme-color-hex { font-size: 10px; margin-top: 5px; background: rgba(255, 255, 255, 0.7); padding: 2px 4px; border-radius: 2px; } .preview-container { margin-bottom: 20px; } .preview-title { font-size: 18px; font-weight: bold; margin-bottom: 10px; } .preview-box { padding: 15px; border-radius: 5px; margin-bottom: 15px; } .notification { position: fixed; bottom: 20px; right: 20px; background: #333; color: #fff; padding: 10px 15px; border-radius: 4px; z-index: 1000; opacity: 0.9; box-shadow: 0 2px 10px rgba(0,0,0,0.2); } .tabs { margin-top: 20px; } .tab-content { padding: 15px; border: 1px solid #ddd; border-top: none; border-radius: 0 0 5px 5px; } .color-format-table { width: 100%; border-collapse: collapse; margin-top: 10px; } .color-format-table th, .color-format-table td { border: 1px solid #ddd; padding: 8px; text-align: left; } .color-format-table th { background-color: #f2f2f2; } .copy-btn { background: #f0f0f0; border: 1px solid #ddd; border-radius: 3px; padding: 2px 6px; cursor: pointer; font-size: 12px; margin-left: 5px; } .copy-btn:hover { background: #e0e0e0; } .eyedropper-cursor { cursor: crosshair; } .theme-selector { margin-bottom: 15px; } .theme-selector label { margin-right: 10px; font-weight: bold; } .color-harmony-wheel { width: 200px; height: 200px; margin: 20px auto; position: relative; border-radius: 50%; background: conic-gradient( red, yellow, lime, cyan, blue, magenta, red ); } .color-harmony-pointer { position: absolute; width: 20px; height: 20px; background: white; border: 2px solid black; border-radius: 50%; top: -10px; left: 50%; transform: translateX(-50%); transform-origin: center 110px; } </style> </head> <body> <div class="app-container"> <div class="color-picker-panel"> <div class="color-picker-container"> <h2>高级jQuery UI调色板</h2> <div class="theme-selector"> <label for="themeSelect">选择主题:</label> <select id="themeSelect"> <option value="base">Base</option> <option value="black-tie">Black Tie</option> <option value="blitzer">Blitzer</option> <option value="cupertino">Cupertino</option> <option value="dark-hive">Dark Hive</option> <option value="dot-luv">Dot Luv</option> <option value="eggplant">Eggplant</option> <option value="excite-bike">Excite Bike</option> <option value="flick">Flick</option> <option value="hot-sneaks">Hot Sneaks</option> <option value="humanity">Humanity</option> <option value="le-frog">Le Frog</option> <option value="mint-choc">Mint Choc</option> <option value="overcast">Overcast</option> <option value="pepper-grinder">Pepper Grinder</option> <option value="redmond">Redmond</option> <option value="smoothness">Smoothness</option> <option value="south-street">South Street</option> <option value="start">Start</option> <option value="sunny">Sunny</option> <option value="swanky-purse">Swanky Purse</option> <option value="trontastic">Trontastic</option> <option value="ui-darkness">UI Darkness</option> <option value="ui-lightness">UI Lightness</option> <option value="vader">Vader</option> </select> </div> <div class="color-display" id="colorDisplay"> <div class="color-info" id="colorInfo">RGB(255, 0, 0) | #FF0000</div> </div> <div class="tabs"> <ul> <li><a href="#rgb-tab">RGB</a></li> <li><a href="#hsv-tab">HSV</a></li> <li><a href="#formats-tab">格式</a></li> </ul> <div id="rgb-tab" class="tab-content"> <div class="slider-container"> <span class="slider-label">R:</span> <div id="redSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="redValue">255</span> </div> <div class="slider-container"> <span class="slider-label">G:</span> <div id="greenSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="greenValue">0</span> </div> <div class="slider-container"> <span class="slider-label">B:</span> <div id="blueSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="blueValue">0</span> </div> </div> <div id="hsv-tab" class="tab-content"> <div class="slider-container"> <span class="slider-label">H:</span> <div id="hueSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="hueValue">0</span> </div> <div class="slider-container"> <span class="slider-label">S:</span> <div id="saturationSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="saturationValue">100</span> </div> <div class="slider-container"> <span class="slider-label">V:</span> <div id="valueSlider" style="display:inline-block; width:200px;"></div> <span class="color-value" id="valueValue">100</span> </div> <div class="color-harmony-wheel"> <div class="color-harmony-pointer" id="harmonyPointer"></div> </div> </div> <div id="formats-tab" class="tab-content"> <input type="text" class="hex-input" id="hexInput" placeholder="#FF0000"> <table class="color-format-table"> <tr> <th>格式</th> <th>值</th> <th>操作</th> </tr> <tr> <td>HEX</td> <td id="hexFormat">#FF0000</td> <td><button class="copy-btn" data-format="hex">复制</button></td> </tr> <tr> <td>RGB</td> <td id="rgbFormat">rgb(255, 0, 0)</td> <td><button class="copy-btn" data-format="rgb">复制</button></td> </tr> <tr> <td>HSL</td> <td id="hslFormat">hsl(0, 100%, 50%)</td> <td><button class="copy-btn" data-format="hsl">复制</button></td> </tr> <tr> <td>HSV</td> <td id="hsvFormat">hsv(0, 100%, 100%)</td> <td><button class="copy-btn" data-format="hsv">复制</button></td> </tr> </table> </div> </div> <button id="eyedropperBtn" class="ui-button ui-widget ui-corner-all" style="width: 100%; margin-top: 10px;">吸管工具</button> <div class="preset-colors" id="presetColors"></div> <div class="color-history" id="colorHistory"> <h3>颜色历史</h3> <div class="history-colors" id="historyColors"></div> </div> <div class="contrast-checker"> <h3>对比度检查器</h3> <div class="contrast-controls"> <label for="bgColor">背景颜色:</label> <input type="text" id="bgColor" class="hex-input" value="#FFFFFF"> <label for="fgColor">前景颜色:</label> <input type="text" id="fgColor" class="hex-input" value="#000000"> <button id="checkContrast" class="ui-button ui-widget ui-corner-all">检查对比度</button> </div> <div class="contrast-result" id="contrastResult"></div> <div class="contrast-preview" id="contrastPreview"> <div class="preview-text">示例文本</div> </div> </div> <div class="color-scheme-generator"> <h3>颜色方案生成器</h3> <div class="scheme-controls"> <button id="complementaryScheme" class="ui-button ui-widget ui-corner-all">互补色</button> <button id="triadicScheme" class="ui-button ui-widget ui-corner-all">三角色</button> <button id="analogousScheme" class="ui-button ui-widget ui-corner-all">类似色</button> <button id="monochromaticScheme" class="ui-button ui-widget ui-corner-all">单色</button> </div> <div class="scheme-colors" id="schemeColors"></div> </div> </div> </div> <div class="preview-panel"> <h2>颜色预览与应用</h2> <div class="preview-container"> <div class="preview-title">按钮样式</div> <div class="preview-box" id="buttonPreview"> <button class="ui-button ui-widget ui-corner-all">示例按钮</button> <button class="ui-button ui-widget ui-corner-all ui-state-highlight">高亮按钮</button> <button class="ui-button ui-widget ui-corner-all ui-state-error">错误按钮</button> </div> </div> <div class="preview-container"> <div class="preview-title">卡片样式</div> <div class="preview-box" id="cardPreview"> <h3>卡片标题</h3> <p>这是一个示例卡片,使用当前选中的颜色作为主题色。您可以看到颜色在不同UI元素上的应用效果。</p> <div style="margin-top: 10px;"> <span class="ui-icon ui-icon-circle-check" style="margin-right: 5px;"></span> <span>列表项 1</span> </div> <div> <span class="ui-icon ui-icon-circle-check" style="margin-right: 5px;"></span> <span>列表项 2</span> </div> </div> </div> <div class="preview-container"> <div class="preview-title">表单元素</div> <div class="preview-box" id="formPreview"> <div style="margin-bottom: 10px;"> <label for="sampleInput">输入框:</label> <input type="text" id="sampleInput" class="ui-widget ui-widget-content" style="width: 100%; padding: 5px; box-sizing: border-box;"> </div> <div style="margin-bottom: 10px;"> <label for="sampleSelect">下拉框:</label> <select id="sampleSelect" class="ui-widget ui-widget-content" style="width: 100%; padding: 5px;"> <option>选项 1</option> <option>选项 2</option> <option>选项 3</option> </select> </div> <div> <label for="sampleTextarea">文本域:</label> <textarea id="sampleTextarea" class="ui-widget ui-widget-content" style="width: 100%; padding: 5px; box-sizing: border-box; height: 60px;"></textarea> </div> </div> </div> <div class="preview-container"> <div class="preview-title">进度条</div> <div class="preview-box" id="progressPreview"> <div id="sampleProgressbar" style="height: 20px;"></div> <div style="margin-top: 10px;"> <button id="animateProgress" class="ui-button ui-widget ui-corner-all">动画进度</button> </div> </div> </div> <div class="preview-container"> <div class="preview-title">导出CSS</div> <div class="preview-box"> <textarea id="cssOutput" style="width: 100%; height: 100px; font-family: monospace; padding: 5px; box-sizing: border-box;" readonly></textarea> <button id="copyCss" class="ui-button ui-widget ui-corner-all" style="margin-top: 10px;">复制CSS</button> </div> </div> </div> </div> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script> <script> $(function() { // 初始化变量 let red = 255, green = 0, blue = 0; let hue = 0, saturation = 100, value = 100; let colorHistory = []; const maxHistoryItems = 10; let isEyedropperActive = false; // 预设颜色 const presetColors = [ '#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF', '#FFA500', '#800080', '#008000', '#000080', '#800000', '#008080', '#FFFFFF', '#C0C0C0', '#808080', '#000000', '#FFC0CB', '#A52A2A' ]; // 初始化标签页 $(".tabs").tabs(); // 初始化滑块 $("#redSlider").slider({ min: 0, max: 255, value: red, slide: function(event, ui) { red = ui.value; $("#redValue").text(red); updateColorFromRGB(); } }); $("#greenSlider").slider({ min: 0, max: 255, value: green, slide: function(event, ui) { green = ui.value; $("#greenValue").text(green); updateColorFromRGB(); } }); $("#blueSlider").slider({ min: 0, max: 255, value: blue, slide: function(event, ui) { blue = ui.value; $("#blueValue").text(blue); updateColorFromRGB(); } }); $("#hueSlider").slider({ min: 0, max: 360, value: hue, slide: function(event, ui) { hue = ui.value; $("#hueValue").text(hue); updateColorFromHSV(); } }); $("#saturationSlider").slider({ min: 0, max: 100, value: saturation, slide: function(event, ui) { saturation = ui.value; $("#saturationValue").text(saturation); updateColorFromHSV(); } }); $("#valueSlider").slider({ min: 0, max: 100, value: value, slide: function(event, ui) { value = ui.value; $("#valueValue").text(value); updateColorFromHSV(); } }); // 初始化进度条 $("#sampleProgressbar").progressbar({ value: 37 }); // 创建预设颜色 presetColors.forEach(color => { const colorDiv = $('<div class="preset-color"></div>'); colorDiv.css('background-color', color); colorDiv.click(function() { setColorFromHex(color); }); $('#presetColors').append(colorDiv); }); // HEX输入框处理 $('#hexInput').on('input', function() { const hex = $(this).val(); if (/^#[0-9A-F]{6}$/i.test(hex)) { setColorFromHex(hex); } }); // 主题选择器 $('#themeSelect').change(function() { const theme = $(this).val(); const themeUrl = `https://code.jquery.com/ui/1.13.2/themes/${theme}/jquery-ui.css`; // 移除旧的jQuery UI主题CSS $('link[href*="jquery-ui.css"]').not('[href*="custom"]').remove(); // 添加新的主题CSS $('<link>', { rel: 'stylesheet', type: 'text/css', href: themeUrl }).appendTo('head'); }); // 吸管工具 $('#eyedropperBtn').click(function() { isEyedropperActive = !isEyedropperActive; if (isEyedropperActive) { $(this).text('取消吸管'); $('body').addClass('eyedropper-cursor'); // 添加点击事件监听器 $(document).on('click.eyedropper', function(e) { // 获取点击位置的颜色 const x = e.clientX; const y = e.clientY; // 使用html2canvas或类似方法获取屏幕颜色 // 这里简化处理,实际应用中可能需要更复杂的实现 const element = document.elementFromPoint(x, y); if (element) { const bgColor = window.getComputedStyle(element).backgroundColor; if (bgColor && bgColor !== 'rgba(0, 0, 0, 0)' && bgColor !== 'transparent') { // 提取RGB值 const match = bgColor.match(/^rgb((d+),s*(d+),s*(d+))$/); if (match) { const r = parseInt(match[1]); const g = parseInt(match[2]); const b = parseInt(match[3]); // 更新颜色 red = r; green = g; blue = b; // 更新滑块 $("#redSlider").slider("value", red); $("#greenSlider").slider("value", green); $("#blueSlider").slider("value", blue); $("#redValue").text(red); $("#greenValue").text(green); $("#blueValue").text(blue); updateColorFromRGB(); } } } // 关闭吸管工具 isEyedropperActive = false; $('#eyedropperBtn').text('吸管工具'); $('body').removeClass('eyedropper-cursor'); $(document).off('click.eyedropper'); }); } else { $(this).text('吸管工具'); $('body').removeClass('eyedropper-cursor'); $(document).off('click.eyedropper'); } }); // 对比度检查器 $('#checkContrast').click(function() { const bgColorHex = $('#bgColor').val(); const fgColorHex = $('#fgColor').val(); if (!/^#[0-9A-F]{6}$/i.test(bgColorHex) || !/^#[0-9A-F]{6}$/i.test(fgColorHex)) { $('#contrastResult').html('<span style="color: #F44336;">请输入有效的十六进制颜色值</span>'); return; } const bgColorRgb = hexToRgb(bgColorHex); const fgColorRgb = hexToRgb(fgColorHex); const ratio = getContrastRatio(bgColorRgb, fgColorRgb); const evaluation = evaluateContrast(ratio); $('#contrastResult').html( `对比度: <strong>${ratio.toFixed(2)}:1</strong> - ` + `<span style="color: ${evaluation.color}">${evaluation.level} (${evaluation.text})</span>` ); // 更新预览 $('#contrastPreview').css('background-color', bgColorHex); $('.preview-text').css('color', fgColorHex); }); // 背景颜色输入框事件 $('#bgColor').on('input', function() { const hex = $(this).val(); if (/^#[0-9A-F]{6}$/i.test(hex)) { $('#contrastPreview').css('background-color', hex); } }); // 前景颜色输入框事件 $('#fgColor').on('input', function() { const hex = $(this).val(); if (/^#[0-9A-F]{6}$/i.test(hex)) { $('.preview-text').css('color', hex); } }); // 颜色方案生成器 $('#complementaryScheme').click(generateComplementaryScheme); $('#triadicScheme').click(generateTriadicScheme); $('#analogousScheme').click(generateAnalogousScheme); $('#monochromaticScheme').click(generateMonochromaticScheme); // 复制按钮事件 $('.copy-btn').click(function() { const format = $(this).data('format'); let textToCopy = ''; switch(format) { case 'hex': textToCopy = $('#hexFormat').text(); break; case 'rgb': textToCopy = $('#rgbFormat').text(); break; case 'hsl': textToCopy = $('#hslFormat').text(); break; case 'hsv': textToCopy = $('#hsvFormat').text(); break; } copyToClipboard(textToCopy); showNotification(`已复制 ${format.toUpperCase()} 格式`); }); // 动画进度按钮 $('#animateProgress').click(function() { let progress = 0; const interval = setInterval(function() { progress += 1; $("#sampleProgressbar").progressbar("value", progress); if (progress >= 100) { clearInterval(interval); } }, 20); }); // 复制CSS按钮 $('#copyCss').click(function() { const cssText = $('#cssOutput').val(); copyToClipboard(cssText); showNotification('已复制CSS代码'); }); // 键盘快捷键 $(document).keydown(function(e) { // Alt+C: 复制当前颜色的HEX值 if (e.altKey && e.keyCode === 67) { // C键 const hex = rgbToHex(red, green, blue); copyToClipboard(hex); showNotification(`已复制颜色: ${hex}`); } // Alt+H: 显示/隐藏颜色历史 if (e.altKey && e.keyCode === 72) { // H键 $('.color-history').toggle(); } // Alt+S: 显示/隐藏颜色方案生成器 if (e.altKey && e.keyCode === 83) { // S键 $('.color-scheme-generator').toggle(); } }); // 颜色转换函数 function rgbToHex(r, g, b) { return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); } function hexToRgb(hex) { const result = /^#?([a-fd]{2})([a-fd]{2})([a-fd]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null; } function rgbToHsv(r, g, b) { r /= 255, g /= 255, b /= 255; const max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, v = max; const d = max - min; s = max == 0 ? 0 : d / max; if (max == min) { h = 0; // 灰色 } else { switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { h: Math.round(h * 360), s: Math.round(s * 100), v: Math.round(v * 100) }; } function hsvToRgb(h, s, v) { h /= 360, s /= 100, v /= 100; let r, g, b; const i = Math.floor(h * 6); const f = h * 6 - i; const p = v * (1 - s); const q = v * (1 - f * s); const t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v, g = t, b = p; break; case 1: r = q, g = v, b = p; break; case 2: r = p, g = v, b = t; break; case 3: r = p, g = q, b = v; break; case 4: r = t, g = p, b = v; break; case 5: r = v, g = p, b = q; break; } return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) }; } function rgbToHsl(r, g, b) { r /= 255, g /= 255, b /= 255; const max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, l = (max + min) / 2; if (max == min) { h = s = 0; // 灰色 } else { const d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) }; } // 对比度计算函数 function getLuminance(r, g, b) { const rsRGB = r / 255; const gsRGB = g / 255; const bsRGB = b / 255; const rLinear = (rsRGB <= 0.03928) ? rsRGB / 12.92 : Math.pow((rsRGB + 0.055) / 1.055, 2.4); const gLinear = (gsRGB <= 0.03928) ? gsRGB / 12.92 : Math.pow((gsRGB + 0.055) / 1.055, 2.4); const bLinear = (bsRGB <= 0.03928) ? bsRGB / 12.92 : Math.pow((bsRGB + 0.055) / 1.055, 2.4); return 0.2126 * rLinear + 0.7152 * gLinear + 0.0722 * bLinear; } function getContrastRatio(color1, color2) { const lum1 = getLuminance(color1.r, color1.g, color1.b); const lum2 = getLuminance(color2.r, color2.g, color2.b); const brightest = Math.max(lum1, lum2); const darkest = Math.min(lum1, lum2); return (brightest + 0.05) / (darkest + 0.05); } function evaluateContrast(ratio) { if (ratio >= 7) { return { level: "AAA", text: "极好", color: "#4CAF50" }; } else if (ratio >= 4.5) { return { level: "AA", text: "良好", color: "#8BC34A" }; } else if (ratio >= 3) { return { level: "AA Large", text: "一般(大文本)", color: "#FFC107" }; } else { return { level: "Fail", text: "不足", color: "#F44336" }; } } // 颜色方案生成函数 function adjustHSV(h, s, v, hAdjust = 0, sAdjust = 0, vAdjust = 0) { h = (h + hAdjust + 360) % 360; s = Math.max(0, Math.min(100, s + sAdjust)); v = Math.max(0, Math.min(100, v + vAdjust)); const rgb = hsvToRgb(h, s, v); return { h: h, s: s, v: v, r: rgb.r, g: rgb.g, b: rgb.b, hex: rgbToHex(rgb.r, rgb.g, rgb.b) }; } function generateComplementaryScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: (currentHsv.h + 180) % 360, s: currentHsv.s, v: currentHsv.v, name: "互补色" } ]; displayColorScheme(colors); } function generateTriadicScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: (currentHsv.h + 120) % 360, s: currentHsv.s, v: currentHsv.v, name: "第二色" }, { h: (currentHsv.h + 240) % 360, s: currentHsv.s, v: currentHsv.v, name: "第三色" } ]; displayColorScheme(colors); } function generateAnalogousScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: (currentHsv.h - 30 + 360) % 360, s: currentHsv.s, v: currentHsv.v, name: "类似色1" }, { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: (currentHsv.h + 30) % 360, s: currentHsv.s, v: currentHsv.v, name: "类似色2" } ]; displayColorScheme(colors); } function generateMonochromaticScheme() { const currentHsv = rgbToHsv(red, green, blue); const colors = [ { h: currentHsv.h, s: currentHsv.s, v: Math.min(100, currentHsv.v + 40), name: "亮色" }, { h: currentHsv.h, s: currentHsv.s, v: currentHsv.v, name: "主色" }, { h: currentHsv.h, s: currentHsv.s, v: Math.max(0, currentHsv.v - 40), name: "暗色" } ]; displayColorScheme(colors); } function displayColorScheme(colors) { const schemeContainer = $('#schemeColors'); schemeContainer.empty(); colors.forEach(color => { const rgb = hsvToRgb(color.h, color.s, color.v); const hex = rgbToHex(rgb.r, rgb.g, rgb.b); const colorDiv = $(` <div class="scheme-color" title="${color.name}: ${hex}"> <div class="scheme-color-hex">${hex}</div> </div> `); colorDiv.css('background-color', hex); colorDiv.click(function() { setColorFromHex(hex); }); schemeContainer.append(colorDiv); }); } // 颜色历史函数 function addToColorHistory(hex) { // 检查颜色是否已在历史中 const index = colorHistory.indexOf(hex); if (index !== -1) { // 如果已存在,先移除 colorHistory.splice(index, 1); } // 添加到历史记录开头 colorHistory.unshift(hex); // 限制历史记录数量 if (colorHistory.length > maxHistoryItems) { colorHistory.pop(); } updateColorHistoryDisplay(); } function updateColorHistoryDisplay() { const historyContainer = $('#historyColors'); historyContainer.empty(); colorHistory.forEach(color => { const colorDiv = $('<div class="history-color"></div>'); colorDiv.css('background-color', color); colorDiv.attr('title', color); colorDiv.click(function() { setColorFromHex(color); }); historyContainer.append(colorDiv); }); } // 更新颜色函数 function updateColorDisplay() { const rgbColor = `rgb(${red}, ${green}, ${blue})`; const hex = rgbToHex(red, green, blue); // 更新颜色显示 $('#colorDisplay').css('background-color', rgbColor); $('#colorInfo').text(`RGB(${red}, ${green}, ${blue}) | ${hex}`); // 更新格式显示 $('#hexFormat').text(hex); $('#rgbFormat').text(rgbColor); const hsl = rgbToHsl(red, green, blue); $('#hslFormat').text(`hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`); const hsv = rgbToHsv(red, green, blue); $('#hsvFormat').text(`hsv(${hsv.h}, ${hsv.s}%, ${hsv.v}%)`); // 更新HEX输入框 $('#hexInput').val(hex); // 添加到颜色历史 addToColorHistory(hex); // 更新对比度检查器 updateContrastChecker(); // 更新预览面板 updatePreviewPanel(); // 更新颜色和谐轮 updateHarmonyWheel(); // 自动生成互补色方案 generateComplementaryScheme(); } function updateColorFromRGB() { updateColorDisplay(); // 更新HSV值 const hsv = rgbToHsv(red, green, blue); hue = hsv.h; saturation = hsv.s; value = hsv.v; // 更新HSV滑块 $("#hueSlider").slider("value", hue); $("#saturationSlider").slider("value", saturation); $("#valueSlider").slider("value", value); $("#hueValue").text(hue); $("#saturationValue").text(saturation); $("#valueValue").text(value); } function updateColorFromHSV() { // 更新RGB值 const rgb = hsvToRgb(hue, saturation, value); red = rgb.r; green = rgb.g; blue = rgb.b; // 更新RGB滑块 $("#redSlider").slider("value", red); $("#greenSlider").slider("value", green); $("#blueSlider").slider("value", blue); $("#redValue").text(red); $("#greenValue").text(green); $("#blueValue").text(blue); updateColorDisplay(); } function setColorFromHex(hex) { const rgb = hexToRgb(hex); if (rgb) { red = rgb.r; green = rgb.g; blue = rgb.b; // 更新RGB滑块 $("#redSlider").slider("value", red); $("#greenSlider").slider("value", green); $("#blueSlider").slider("value", blue); $("#redValue").text(red); $("#greenValue").text(green); $("#blueValue").text(blue); updateColorFromRGB(); } } function updateContrastChecker() { const currentColor = rgbToHex(red, green, blue); $('#fgColor').val(currentColor); $('.preview-text').css('color', currentColor); // 如果背景颜色未设置,则使用当前颜色的对比色 if (!$('#bgColor').val() || $('#bgColor').val() === '#FFFFFF') { const luminance = getLuminance(red, green, blue); const contrastColor = luminance > 0.5 ? '#000000' : '#FFFFFF'; $('#bgColor').val(contrastColor); $('#contrastPreview').css('background-color', contrastColor); } // 自动检查对比度 $('#checkContrast').click(); } function updatePreviewPanel() { const hex = rgbToHex(red, green, blue); const rgb = `rgb(${red}, ${green}, ${blue})`; // 更新按钮样式 $('#buttonPreview button').css('background-color', hex); // 更新卡片样式 $('#cardPreview').css('border-color', hex); $('#cardPreview h3').css('color', hex); // 更新表单元素样式 $('#sampleInput, #sampleSelect, #sampleTextarea').css('border-color', hex); // 更新进度条样式 $('.ui-progressbar-value').css('background-color', hex); // 生成CSS代码 const cssCode = `/* 主色调 */ :root { --primary-color: ${hex}; --primary-color-rgb: ${red}, ${green}, ${blue}; } /* 按钮样式 */ .ui-button { background-color: var(--primary-color) !important; border-color: var(--primary-color) !important; } .ui-button:hover { background-color: color-mix(in srgb, var(--primary-color) 90%, black) !important; } /* 卡片样式 */ .card { border-color: var(--primary-color) !important; } .card h3 { color: var(--primary-color) !important; } /* 表单元素 */ input, select, textarea { border-color: var(--primary-color) !important; } input:focus, select:focus, textarea:focus { box-shadow: 0 0 0 2px color-mix(in srgb, var(--primary-color) 50%, transparent) !important; } /* 进度条 */ .ui-progressbar-value { background-color: var(--primary-color) !important; }`; $('#cssOutput').val(cssCode); } function updateHarmonyWheel() { // 更新颜色和谐轮指针位置 const pointer = $('#harmonyPointer'); pointer.css('transform', `translateX(-50%) rotate(${hue}deg)`); pointer.css('background-color', rgbToHex(red, green, blue)); } // 复制到剪贴板函数 function copyToClipboard(text) { const textarea = document.createElement('textarea'); textarea.value = text; document.body.appendChild(textarea); textarea.select(); document.execCommand('copy'); document.body.removeChild(textarea); } // 显示通知函数 function showNotification(message) { const notification = $(` <div class="notification"> ${message} </div> `); $('body').append(notification); // 3秒后淡出并移除 setTimeout(function() { notification.fadeOut(300, function() { $(this).remove(); }); }, 3000); } // 初始化颜色显示 updateColorDisplay(); }); </script> </body> </html> 

总结与展望

通过本文的详细解析,我们全面了解了如何利用jQuery UI构建功能强大的调色板应用。从基础的RGB和HSV滑块控制,到高级的颜色方案生成、对比度检查等功能,我们逐步构建了一个完整的调色板应用。

主要收获

  1. jQuery UI组件的灵活应用:我们利用jQuery UI的滑块、按钮、进度条等组件,构建了一个功能完善的调色板应用。

  2. 颜色空间转换:实现了RGB、HSV、HSL和HEX之间的相互转换,为用户提供了多种颜色表示方式。

  3. 用户体验优化:通过添加颜色历史、预设颜色、键盘快捷键等功能,显著提升了用户体验。

  4. 高级功能:实现了颜色方案生成器、对比度检查器、颜色吸管等高级功能,使调色板应用更加专业和实用。

  5. 性能优化:通过事件节流、DOM操作优化、缓存计算结果等技术,确保了应用的流畅运行。

  6. 插件化封装:将调色板功能封装为可重用的jQuery插件,提高了代码的可维护性和复用性。

未来展望

随着Web技术的不断发展,调色板应用还有许多可以进一步探索和改进的方向:

  1. Canvas增强:使用Canvas API实现更高级的颜色选择界面,如二维颜色选择器、颜色渐变预览等。

  2. AI辅助配色:集成机器学习算法,为用户提供智能配色建议,基于色彩理论和美学原则。

  3. 无障碍访问:进一步增强应用的无障碍访问功能,确保所有用户都能轻松使用。

  4. 云端同步:添加云端同步功能,使用户可以在不同设备间同步他们的颜色收藏和设置。

  5. 扩展集成:开发浏览器扩展或设计软件插件,使调色板可以在更多环境中使用。

  6. 移动端优化:针对移动设备进行优化,添加触摸手势支持,提供更好的移动端体验。

通过不断的技术创新和用户体验优化,jQuery UI调色板应用将继续在设计和开发领域发挥重要作用,为用户提供更加高效、便捷的颜色选择和管理工具。