不用框架,复刻一个VS Code的调色板

简介: 不用框架,复刻一个VS Code的调色板

image.png


前言



那天在codepen看到了别人做的color picker就突发奇想自己复刻一个VS Code的调色板,我也是刚开始学前端嘛,看见啥都想试着写一个。


说干就干,花了几个小时写了一个,bug贼多,就是一个想法,也懒得改了,菜鸡一个,大佬勿喷。


我们先来看看原版长啥样(颜色过多的话gif会失真,大概看看):


image.png

可以看到上方用来显示颜色和色值,点击可以切换三种色彩显示方式,分别是rgba,hsla和hex8;然后下方左侧一个色谱来选择颜色,右侧两个滑块选择透明度和色相。

右上角的显示原来的颜色和最下方的文字提示这次就先不写了🙈

然后看看我几个小时复刻的结果(在线预览):


image.png


HTML+CSS



HTML没啥好说的,就div套div

我大概画了一下整体布局:


image.png


透明背景


image.png


这背景的黑白格子上来就给我整蒙了,还得是万能的搜索啊,最后用线性渐变解决了:


background: linear-gradient(
                45deg, 
                rgba(0, 0, 0, 0.4) 25%, 
                transparent 25%, 
                transparent 75%, 
                rgba(0, 0, 0, 0.4) 75%, 
                rgba(0, 0, 0, 0.4)
                ),
            linear-gradient(
                45deg, 
                rgba(0, 0, 0, 0.4) 25%, 
                transparent 25%, 
                transparent 75%, 
                rgba(0, 0, 0, 0.4) 75%, 
                rgba(0, 0, 0, 0.4)
            );
background-size: 10px 10px;
background-position: 0 0, 5px 5px;
复制代码

下半部分


透明度和色相选择部分都用线性渐变解决:


// 透明度
background: linear-gradient(to bottom, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
// 色相
background: linear-gradient(to bottom,
    hsl(0, 100%, 50%),
    hsl(60, 100%, 50%),
    hsl(120, 100%, 50%),
    hsl(180, 100%, 50%),
    hsl(240, 100%, 50%),
    hsl(300, 100%, 50%),
    hsl(360, 100%, 50%)
);
复制代码

滑块左右要各超出去1px:


.slide {
    width: 27px;
    height: 5px;
    border: 1px solid #eee;
    position: absolute;
    left: -2px;
    top: 0;
}
复制代码

成果


CSS写完后就是这个样子:


image.png


JS



先把要用到的变量都定义出来:


const container = document.querySelector('.container')
const value = document.querySelector('.value')
const opacity = document.querySelector('.opacity')
const hue = document.querySelector('.hue')
const opaSlide = document.querySelector('#opa-slide')
const hueSlide = document.querySelector('#hue-slide')
const spectrum = document.querySelector('.spectrum')
const cursor = document.querySelector('.color-cursor')
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
const speRect = canvas.getBoundingClientRect()
let bg_color = {
  h: 0,
  s: "100%",
  l: "50%",
  a: 1
};
复制代码

canvas


canvas也就是色谱部分用两个黑白透明渐变覆盖画出来的:


function draw(color) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    if (!color) color = '#f00';
    ctx.fillStyle = color;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    let whiteGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
    whiteGradient.addColorStop(0, "#fff");
    whiteGradient.addColorStop(1, "transparent");
    ctx.fillStyle = whiteGradient;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    let blackGradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
    blackGradient.addColorStop(0, "transparent");
    blackGradient.addColorStop(1, "#000");
    ctx.fillStyle = blackGradient;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
}
draw();


image.png



鼠标事件


检测鼠标按下、移动、抬起事件,然后更改信息:


let isDraw = false;
container.onmousedown = () => (isDraw = true);
container.onmousemove = (e) => {
  if (!isDraw) return;
  if (检测到鼠标移动到目标区域) {
      更改显示位置;
      更改颜色;
  }
  更改全部颜色及文本信息;
};
container.onmouseup = () => (isDraw = false);
// 避免一些bug,但这样影响效果
canvas.onmouseout = () => (isDraw = false);
复制代码

移动改变透明度及色相


通过鼠标位置计算滑块位置,然后计算比例修改透明度和色相值,用到了TinyColor来解析颜色。


let bg_color = {
  h: 0,
  s: "100%",
  l: "50%",
  a: 1
};
container.onmousemove = (e) => {
  if (!isDraw) return;
  if (e.target === opacity || e.target.parentNode === opacity) {
    let y = e.pageY - opacity.getBoundingClientRect().top;
    if (y < 0) y = 0.1;
    if (y > 150) y = 145;
    opaSlide.style.top = y + "px";
    bg_color.a = 1 - y / opacity.offsetHeight;
  }
  if (e.target === hue || e.target.parentNode === hue) {
    let y = e.pageY - hue.getBoundingClientRect().top;
    if (y < 0) y = 0.1;
    if (y > 150) y = 145;
    hueSlide.style.top = y + "px";
    bg_color.h = (y / hue.offsetHeight) * 360;
    draw(tinycolor(bg_color));
  }
};
复制代码

移动改变颜色


在stackoverflow上找到了一个公式,通过x,y在画布上的比例计算颜色的亮度和饱和度:


if (e.target === spectrum || e.target.parentNode === spectrum) {
    let x = e.pageX - speRect.left - cursor.offsetWidth / 2;
    let y = e.pageY - speRect.top - cursor.offsetHeight / 2;
    let r = cursor.offsetHeight;
    if (x < 0) x = 0;
    if (x > speRect.width - r) x = speRect.width - r;
    if (y < 0) y = 0.1;
    if (y > speRect.height - r) y = speRect.height - r;
    cursor.style.left = x + "px";
    cursor.style.top = y + "px";
    // from stackoverflow
    let hsvValue = 1 - y / speRect.height;
    let hsvSaturation = x / speRect.width;
    let lightness = (hsvValue / 2) * (2 - hsvSaturation);
    let saturation =
      (hsvValue * hsvSaturation) / (1 - Math.abs(2 * lightness - 1));
    bg_color.l = lightness * 100 + "%";
    bg_color.s = saturation * 100 + "%";
}
复制代码

显示文字及背景颜色


这里就是tinycolor的用法,可以看一下官方文档。


let method = "toRgbString";
function changeBg() {
  let color = tinycolor(bg_color)[method]();
  value.style.background = color;
  value.style.color = parseInt(bg_color.l) >= 50 ? "black" : "white";
  value.innerHTML = color;
  document.body.style.background = `linear-gradient(to top, transparent, ${color})`
  cursor.style.background = color;
}
复制代码

点击上方切换颜色显示方式


let index = 0;
function changeType() {
  switch (index % 3) {
    case 0:
      method = "toRgbString";
      break;
    case 1:
      method = "toHex8String";
      break;
    case 2:
      method = "toHslString";
      break;
  }
  index++;
}
value.onclick = () => {
  changeType();
  changeBg();
};
复制代码


源代码



bug巨多无比,我还是太菜了,源码放到了codepen上,想看的话可以看看

Color Picker (codepen.io)


总结


canvas挺好用,线性渐变更好用,但我太菜了。。。

我真的是有拖延症,早就写完代码了,博客拖了几天也没写,bug也不想再改了,代码拉就拉了吧,大伙随便看看,还是有一点参考作用的

目录
相关文章
|
2天前
|
机器学习/深度学习 人工智能 自然语言处理
Manga Image Translator:开源的漫画文字翻译工具,支持多语言翻译并嵌入原图,保持漫画的原始风格和布局
Manga Image Translator 是一款开源的漫画图片文字翻译工具,支持多语言翻译并能将翻译后的文本无缝嵌入原图,保持漫画的原始风格和布局。该工具基于OCR技术和深度学习模型,提供批量处理和在线/离线翻译功能。
34 14
Manga Image Translator:开源的漫画文字翻译工具,支持多语言翻译并嵌入原图,保持漫画的原始风格和布局
|
2月前
|
算法 搜索推荐 Java
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
这篇文章介绍了如何使用Java后端技术,结合Graphics2D和Echarts等工具,生成包含个性化信息和图表的海报,并提供了详细的代码实现和GitHub项目链接。
147 0
java 后端 使用 Graphics2D 制作海报,画echarts图,带工具类,各种细节:如头像切割成圆形,文字换行算法(完美实验success),解决画上文字、图片后不清晰问题
|
7月前
|
Android开发
Android Studio入门之图像显示解析及实战(附源码 超详细必看)(包括图像视图、图像按钮、同时展示文本与图像)
Android Studio入门之图像显示解析及实战(附源码 超详细必看)(包括图像视图、图像按钮、同时展示文本与图像)
294 1
|
7月前
|
机器学习/深度学习 搜索推荐 计算机视觉
字节推出DreamTuner:只需提供一张图片,就能帮你生成与该图片主题风格一致的新图像
【2月更文挑战第17天】字节推出DreamTuner:只需提供一张图片,就能帮你生成与该图片主题风格一致的新图像
174 2
字节推出DreamTuner:只需提供一张图片,就能帮你生成与该图片主题风格一致的新图像
|
人工智能
像相机一样变焦、填充画面细节,还能自定义风格,AI作画神器Midjourney又更新了
像相机一样变焦、填充画面细节,还能自定义风格,AI作画神器Midjourney又更新了
182 1
|
前端开发
前端知识学习案例18vs code-选择方形区域
前端知识学习案例18vs code-选择方形区域
71 0
前端知识学习案例18vs code-选择方形区域
|
iOS开发 索引
iOS开发CoreGraphics核心图形框架之三——颜色与色彩空间
iOS开发CoreGraphics核心图形框架之三——颜色与色彩空间
618 0
iOS开发CoreGraphics核心图形框架之三——颜色与色彩空间
|
机器学习/深度学习 自然语言处理 计算机视觉
2022年最新文本生成图像研究 开源工作速览(Papers with code)
2022年最新文本生成图像研究 开源工作速览(Papers with code)
|
前端开发
前端要凉?微软开源Sketch2Code,草图秒变代码
用户界面设计过程涉及大量创造性的迭代工作。这个过程通常从在白板或白纸上画草图开始,设计师和工程师分享他们的想法,尽力表达出潜在的客户场景或工作流程。当他们在某个设计上达成一致之后,通过照片的形式将草图拍下来,然后手动将草图翻译成 HTML 代码。
1468 0
前端要凉?微软开源Sketch2Code,草图秒变代码
下一篇
DataWorks