图立得-html纯前端图片拾色器V202507
全棧开发,前端网页设计,图片设计工作制开源(绿色)好工具。
RGB 颜色、HEX 颜色、CMYK 颜色、HSL 颜色、坐标位置快速获取带色预览。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图立得前端图片拾色器,纯前端 chalide.cn</title>
<meta name="author" content="yujianyue, 15058593138@qq.com">
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
body {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
color: #333;
}
h1 {
text-align: center;
margin-bottom: 20px;
color: #2c3e50;
}
.container {
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.upload-area {
border: 2px dashed #ccc;
border-radius: 8px;
padding: 15px;
text-align: center;
margin-bottom: 20px;
transition: all 0.3s;
cursor: pointer;
background-color: #fafafa;
}
.upload-area:hover {
border-color: #3498db;
background-color: #f0f8ff;
}
.upload-area.drag-over {
border-color: #2ecc71;
background-color: #e8f8f0;
}
.upload-area i {
font-size: 48px;
color: #3498db;
margin-bottom: 10px;
}
.upload-area p {
margin-bottom: 10px;
color: #7f8c8d;
}
input[type="file"] {
display: none;
}
.preview-container {
position: relative;
margin-top: 20px;
overflow: hidden;
text-align: center;
}
#imagePreview {
max-width: 100%;
min-height: 70vh;
display: inline-block;
cursor: crosshair;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.color-info {
position: sticky;
top: 0; /* 当滚动到顶部时固定 */
z-index: 100; /* 确保它在其他内容之上 */
margin-top: 0px;
padding: 5px;
background-color: #f8f9fa;
border-radius: 8px;
display: flex;
flex-wrap: wrap;
gap: 5px;
justify-content: center;
}
.color-info-item {
min-width: 180px;
text-align: left;
}
.color-info-item h3 {
margin-bottom: 2px;
color: #2c3e50;
font-size: 16px;
}
.color-value {
font-family: monospace;
font-size: 14px;
padding: 4px;
background-color: white;
border-radius: 4px;
border: 1px solid #ddd;
margin-bottom: 2px;
}
.color-preview {
width: 60px;
height: 20px;
border-radius: 4px;
border: 1px solid #ddd;
margin: 0 auto;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.coordinates {
margin-top: 2px;
font-size: 14px;
color: #7f8c8d;
}
.error {
color: #e74c3c;
margin-top: 10px;
text-align: center;
padding: 10px;
background-color: #fde8e8;
border-radius: 4px;
display: none;
}
.error.show {
display: block;
}
.image-info {
margin-top: 10px;
font-size: 14px;
color: #7f8c8d;
text-align: center;
}
.magnifier {
position: absolute;
width: 120px;
height: 120px;
border: 3px solid #fff;
border-radius: 50%;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
pointer-events: none;
display: none;
overflow: hidden;
z-index: 100;
}
.magnifier-content {
width: 100%;
height: 100%;
transform: scale(2.5);
transform-origin: 0 0;
background-repeat: no-repeat;
}
.zoom-lens {
position: absolute;
width: 20px;
height: 20px;
border: 2px solid #fff;
border-radius: 50%;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.8);
pointer-events: none;
display: none;
z-index: 99;
}
.no-image {
text-align: center;
padding: 40px;
color: #7f8c8d;
font-size: 18px;
}
</style>
</head>
<body>
<div class="container">
<h1>图立得 - 前端图片拾色器</h1>
<div class="upload-area" id="uploadArea">
<p>拖放图片到此处或点击选择文件</p>
<p>支持格式: JPG, PNG, GIF, WEBP</p>
<input type="file" id="fileInput" accept="image/jpeg,image/png,image/gif,image/webp">
</div>
<div class="color-info" id="colorInfo" style="display: none;">
<div class="color-info-item">
<h3>RGB 颜色</h3>
<div class="color-value" id="rgbValue">RGB(0, 0, 0)</div>
<div class="color-preview" id="rgbPreview"></div>
</div>
<div class="color-info-item">
<h3>HEX 颜色</h3>
<div class="color-value" id="hexValue">#000000</div>
<div class="color-preview" id="hexPreview"></div>
</div>
<div class="color-info-item">
<h3>CMYK 颜色</h3>
<div class="color-value" id="cmykValue">CMYK(0%, 0%, 0%, 100%)</div>
<div class="color-preview" id="cmykPreview"></div>
</div>
<div class="color-info-item">
<h3>HSL 颜色</h3>
<div class="color-value" id="hslValue">HSL(0, 0%, 0%)</div>
<div class="color-preview" id="hslPreview"></div>
</div>
<div class="color-info-item">
<h3>坐标位置</h3>
<div class="color-value" id="coordValue">X: 0, Y: 0</div>
<div class="coordinates" id="pixelInfo">像素: RGBA(0, 0, 0, 0)</div>
</div>
</div>
<div class="error" id="error"></div>
<div class="preview-container" id="previewContainer">
<div class="no-image" id="noImage">请选择或拖放图片到上方区域,选图后色号等显示在图片下方</div>
<img id="imagePreview" style="display: none;">
<div class="magnifier" id="magnifier">
<div class="magnifier-content" id="magnifierContent"></div>
</div>
<div class="zoom-lens" id="zoomLens"></div>
</div>
<div class="image-info" id="imageInfo"></div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const uploadArea = document.getElementById('uploadArea');
const fileInput = document.getElementById('fileInput');
const previewContainer = document.getElementById('previewContainer');
const noImage = document.getElementById('noImage');
const imagePreview = document.getElementById('imagePreview');
const imageInfo = document.getElementById('imageInfo');
const colorInfo = document.getElementById('colorInfo');
const error = document.getElementById('error');
const rgbValue = document.getElementById('rgbValue');
const hexValue = document.getElementById('hexValue');
const cmykValue = document.getElementById('cmykValue');
const hslValue = document.getElementById('hslValue');
const coordValue = document.getElementById('coordValue');
const pixelInfo = document.getElementById('pixelInfo');
const rgbPreview = document.getElementById('rgbPreview');
const hexPreview = document.getElementById('hexPreview');
const cmykPreview = document.getElementById('cmykPreview');
const hslPreview = document.getElementById('hslPreview');
const magnifier = document.getElementById('magnifier');
const magnifierContent = document.getElementById('magnifierContent');
const zoomLens = document.getElementById('zoomLens');
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d', { willReadFrequently: true });
let currentImageData = null;
let naturalWidth = 0;
let naturalHeight = 0;
// 点击上传区域
uploadArea.addEventListener('click', function() {
fileInput.click();
});
// 拖放功能
uploadArea.addEventListener('dragover', function(e) {
e.preventDefault();
this.classList.add('drag-over');
});
uploadArea.addEventListener('dragleave', function() {
this.classList.remove('drag-over');
});
uploadArea.addEventListener('drop', function(e) {
e.preventDefault();
this.classList.remove('drag-over');
if (e.dataTransfer.files.length) {
handleFile(e.dataTransfer.files[0]);
}
});
// 文件选择
fileInput.addEventListener('change', function() {
if (this.files.length) {
handleFile(this.files[0]);
}
});
// 图片鼠标移动事件
imagePreview.addEventListener('mousemove', function(e) {
if (!currentImageData) return;
const rect = this.getBoundingClientRect();
const scaleX = this.naturalWidth / this.width;
const scaleY = this.naturalHeight / this.height;
let x = Math.round((e.clientX - rect.left) * scaleX);
let y = Math.round((e.clientY - rect.top) * scaleY);
// 确保坐标在图片范围内
x = Math.max(0, Math.min(x, this.naturalWidth - 1));
y = Math.max(0, Math.min(y, this.naturalHeight - 1));
// 显示放大镜
magnifier.style.display = 'block';
magnifier.style.left = (e.clientX + 20) + 'px';
magnifier.style.top = (e.clientY + 20) + 'px';
// 更新放大镜内容
magnifierContent.style.backgroundImage = `url(${imagePreview.src})`;
magnifierContent.style.backgroundPosition = `-${x-24}px -${y-24}px`;
// 显示缩放镜头
zoomLens.style.display = 'block';
zoomLens.style.left = (e.clientX - 10) + 'px';
zoomLens.style.top = (e.clientY - 10) + 'px';
// 获取像素颜色
const pixel = ctx.getImageData(x, y, 1, 1).data;
const r = pixel[0];
const g = pixel[1];
const b = pixel[2];
const a = pixel[3] / 255;
// 更新坐标显示
coordValue.textContent = `X: ${x}, Y: ${y}`;
pixelInfo.textContent = `像素: RGBA(${r}, ${g}, ${b}, ${a.toFixed(2)})`;
// 更新RGB显示
rgbValue.textContent = `RGB(${r}, ${g}, ${b})`;
rgbPreview.style.backgroundColor = `rgb(${r}, ${g}, ${b})`;
// 更新HEX显示
const hex = rgbToHex(r, g, b);
hexValue.textContent = `#${hex}`;
hexPreview.style.backgroundColor = `#${hex}`;
// 更新CMYK显示
const cmyk = rgbToCmyk(r, g, b);
cmykValue.textContent = `CMYK(${cmyk.c}%, ${cmyk.m}%, ${cmyk.y}%, ${cmyk.k}%)`;
cmykPreview.style.backgroundColor = `rgb(${r}, ${g}, ${b})`;
// 更新HSL显示
const hsl = rgbToHsl(r, g, b);
hslValue.textContent = `HSL(${Math.round(hsl.h)}, ${Math.round(hsl.s)}%, ${Math.round(hsl.l)}%)`;
hslPreview.style.backgroundColor = `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;
});
imagePreview.addEventListener('mouseout', function() {
magnifier.style.display = 'none';
zoomLens.style.display = 'none';
});
// 处理选择的文件
function handleFile(file) {
// 验证文件类型
const validTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
if (!validTypes.includes(file.type)) {
showError('不支持的文件类型');
return;
}
error.classList.remove('show');
const reader = new FileReader();
reader.onload = function(e) {
imagePreview.onload = function() {
// 保存原始尺寸
naturalWidth = this.naturalWidth;
naturalHeight = this.naturalHeight;
// 设置canvas尺寸
canvas.width = naturalWidth;
canvas.height = naturalHeight;
// 绘制图像到canvas
ctx.drawImage(this, 0, 0);
// 获取图像数据
currentImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// 显示预览
noImage.style.display = 'none';
imagePreview.style.display = 'inline-block';
colorInfo.style.display = 'flex';
imageInfo.textContent = `${file.name} (${formatFileSize(file.size)}) - ${naturalWidth}×${naturalHeight}像素`;
};
imagePreview.src = e.target.result;
};
reader.onerror = function() {
showError('读取文件失败');
};
reader.readAsDataURL(file);
}
// RGB转HEX
function rgbToHex(r, g, b) {
return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
}
// RGB转CMYK
function rgbToCmyk(r, g, b) {
if (r === 0 && g === 0 && b === 0) {
return { c: 0, m: 0, y: 0, k: 100 };
}
let c = 1 - (r / 255);
let m = 1 - (g / 255);
let y = 1 - (b / 255);
const minCMY = Math.min(c, m, y);
c = (c - minCMY) / (1 - minCMY);
m = (m - minCMY) / (1 - minCMY);
y = (y - minCMY) / (1 - minCMY);
const k = minCMY;
return {
c: Math.round(c * 100),
m: Math.round(m * 100),
y: Math.round(y * 100),
k: Math.round(k * 100)
};
}
// RGB转HSL
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; // achromatic
} 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: h * 360,
s: s * 100,
l: l * 100
};
}
// 显示错误
function showError(message) {
error.textContent = message;
error.classList.add('show');
noImage.style.display = 'block';
imagePreview.style.display = 'none';
colorInfo.style.display = 'none';
}
// 格式化文件大小
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
});
</script>
</body>
</html>