js颜色调试器
- 2022 年 5 月 28 日
- 筆記
- CSS, HTML, javascript, 其它
1 /* ColorTestViewer 颜色调试器 2 3 attribute: 4 onchange: Function; //颜色改变回调; 默认null 5 6 //以下属性不建议直接修改 7 rgb: RGBColor; //rgb模式颜色 8 hsv: Object{h,s,v}; //hsv模式颜色 9 alpha: Number; //透明度 10 11 method: 12 update(): undefined; //更新控件视图 (通常控件被唤出时调用此方法, 前提是在唤出前控件颜色发生了改变) 13 setValue(r, g, b, a): this; //设置控件的颜色 14 15 demo: 16 const ctv = new ColorTestViewer({width: 200}) 17 .setValue(0, 0, 255, 1).update(false) 18 .pos(100, 100).render(); 19 20 ctv.onchange = v => console.log(v); 21 22 */ 23 class ColorTestViewer extends CanvasAnimateRender{ 24 25 get value(){ 26 return this.rgb.getRGBA(Math.floor(this.alpha * 1000) / 1000); 27 } 28 29 constructor(option = {}){ 30 super(option); 31 32 this.rgb = new RGBColor(255); 33 this.hsv = this.rgb.getHSV(); 34 this.alpha = 1; 35 this.cae = null; 36 this.onchange = null; 37 38 this.viewSVColor = null; 39 this.viewSVsv = null; 40 this.viewSVCursor = null; 41 42 this.viewHValueBG = null; 43 this.viewHValue = null; 44 this.viewHScroll = null; 45 this.viewHCursor = null; 46 47 this.viewAScroll = null; 48 this.viewACursor = null; 49 50 this.viewColorInfo = null; 51 52 //默认样式 53 if(option.canvas === undefined){ 54 const width = option.width || 200, height = option.height || (width * 0.8), margin = 2, 55 h5 = height * 0.5, h1 = height * 0.1, h3 = height * 0.3; 56 57 this.size(width + margin * 2, height + margin * 5); 58 59 this.initViewSVColor(width, h5); 60 this.initViewHScroll(width, h1); 61 this.initViewAScroll(width, h1); 62 this.initViewHValue(h3, h3); 63 this.initViewColorInfo(width - h3, h3); 64 65 this.setViewSVPos(margin, margin); 66 this.setViewHScrollPos(margin, h5 + margin * 2); 67 this.setViewAScrollPos(margin, h5 + h1 + margin * 3); 68 this.setViewHValuePos(margin, h5 + h1 * 2 + margin * 4); 69 this.viewColorInfo.pos(this.viewHValue.box.maxX(), this.viewHValue.box.y); 70 71 this.initList(); 72 this.initEvent(); 73 74 } 75 76 } 77 78 update(u){ 79 if(this.viewSVColor !== null){ 80 this.updateViewSVCursor(); 81 this.updateViewSVColor(); 82 this.updateViewHValue(); 83 this.updateViewHCursor(); 84 this.updateViewACursor(); 85 this.updateViewColorInfo(); 86 if(u === true) this.redraw(); 87 } 88 89 return this; 90 } 91 92 setValue(r, g, b, a){ 93 this.rgb.r = r; 94 this.rgb.g = g; 95 this.rgb.b = b; 96 this.alpha = a; 97 this.rgb.getHSV(this.hsv); 98 99 return this; 100 } 101 102 setValueString(color){ 103 if(typeof color !== "string") return this; 104 var _color = this.getColor(color); 105 106 if(_color[0] === "#"){ 107 const len = _color.length; 108 if(len === 4){ 109 _color = _color.slice(1); 110 this.rgb.setFormHex(parseInt("0x"+_color + "" + _color)); 111 } 112 else if(len === 7) this.rgb.setFormHex(parseInt("0x"+_color.slice(1))); 113 this.alpha = 1; 114 this.rgb.getHSV(this.hsv); 115 116 } 117 118 else if(_color[0] === "r" && _color[1] === "g" && _color[2] === "b"){ 119 const arr = []; 120 for(let k = 0, len = _color.length, v = "", is = false; k < len; k++){ 121 122 if(is === true){ 123 if(_color[k] === "," || _color[k] === ")"){ 124 arr.push(parseFloat(v)); 125 v = ""; 126 } 127 else v += _color[k]; 128 129 } 130 131 else if(_color[k] === "(") is = true; 132 133 } 134 135 this.setValue(arr[0], arr[1], arr[2], arr[3] === undefined ? 1 : arr[3]); 136 137 } 138 139 return this; 140 } 141 142 getColor(str){ //检测 str 是否是颜色类型(16进制, rgb, rgba, 英文); 如果是则返回去除掉空格后的字符串颜色(英文则返回对应16进制颜色) 143 var _color = ""; 144 for(let k = 0, len = str.length; k < len; k++){ 145 if(str[k] === " ") continue; 146 _color += str[k]; 147 } 148 149 if(_color[0] === "#" || (_color[0] === "r" && _color[1] === "g" && _color[2] === "b")) return _color; 150 else{ 151 for(let k = 0, len = ColorRefTable.length; k < len; k++){ 152 str = ColorRefTable[k]; 153 if(str[0] === _color) return str[1]; 154 } 155 } 156 157 return ""; 158 } 159 160 exit(){ 161 if(this.cae){ 162 this.onUpSV(); 163 this.onUpH(); 164 this.onUpA(); 165 } 166 167 if(this.domElement.parentElement) this.domElement.parentElement.removeChild(this.domElement); 168 169 } 170 171 172 //event 173 initEvent(){ 174 175 const cae = new CanvasAnimateEvent(this); 176 177 //SV 178 const setSV = (pageX, pageY) => { 179 pageX = (pageX - this.domElementRect.x - this.viewSVColor.box.x) / this.viewSVColor.box.w * 100; 180 pageY = (1 - (pageY - this.domElementRect.y - this.viewSVColor.box.y) / this.viewSVColor.box.h) * 100; 181 if(pageX < 0) pageX = 0; 182 else if(pageX > 100) pageX = 100; 183 if(pageY < 0) pageY = 0; 184 else if(pageY > 100) pageY = 100; 185 if(this.hsv.s !== pageX || this.hsv.v !== pageY){ 186 this.hsv.s = pageX; 187 this.hsv.v = pageY; 188 this.rgb.setFormHSV(this.hsv.h, this.hsv.s, this.hsv.v); 189 if(typeof this.onchange === "function") this.onchange(this.value); 190 this.updateViewHValue(); 191 this.updateViewColorInfo(); 192 this.updateViewSVCursor(); 193 this.redraw(); 194 } 195 196 }, 197 198 onMoveSV = event => { 199 setSV(event.pageX, event.pageY); 200 }, 201 202 onUpSV = () => { 203 document.body.removeEventListener("pointerup", onUpSV); 204 document.body.removeEventListener("pointermove", onMoveSV); 205 cae.remove(this.viewSVCursor, 'up', onUpSV); 206 cae.remove(this.viewSVCursor, 'move', onMoveSV); 207 208 }, 209 210 onDownSV = event => { 211 setSV(event.pageX, event.pageY); 212 cae.add(this.viewSVCursor, "up", onUpSV); 213 cae.add(this.viewSVCursor, "move", onMoveSV); 214 document.body.addEventListener("pointerup", onUpSV); 215 document.body.addEventListener("pointermove", onMoveSV); 216 217 } 218 219 cae.add(this.viewSVColor, "down", onDownSV); 220 cae.add(this.viewSVCursor, "down", onDownSV); 221 this.onUpSV = onUpSV; 222 223 224 //H 225 const setH = (pageX) => { 226 pageX = (pageX - this.domElementRect.x - this.viewHScroll.box.x) / this.viewHScroll.box.w * 360; 227 if(pageX < 0) pageX = 0; 228 else if(pageX > 360) pageX = 360; 229 if(this.hsv.h !== pageX){ 230 this.hsv.h = pageX; 231 this.rgb.setFormHSV(this.hsv.h, this.hsv.s, this.hsv.v); 232 if(typeof this.onchange === "function") this.onchange(this.value); 233 this.updateViewHValue(); 234 this.updateViewColorInfo(); 235 this.updateViewSVColor(); 236 this.updateViewHCursor(); 237 this.redraw(); 238 } 239 240 }, 241 242 onMoveH = event => { 243 setH(event.pageX); 244 }, 245 246 onUpH = () => { 247 document.body.removeEventListener("pointerup", onUpH); 248 document.body.removeEventListener("pointermove", onMoveH); 249 cae.remove(this.viewHCursor, 'up', onUpH); 250 cae.remove(this.viewHCursor, 'move', onMoveH); 251 252 }, 253 254 onDownH = event => { 255 setH(event.pageX); 256 cae.add(this.viewHCursor, "up", onUpH); 257 cae.add(this.viewHCursor, "move", onMoveH); 258 document.body.addEventListener("pointerup", onUpH); 259 document.body.addEventListener("pointermove", onMoveH); 260 261 } 262 263 cae.add(this.viewHScroll, "down", onDownH); 264 cae.add(this.viewHCursor, "down", onDownH); 265 this.onUpH = onUpH; 266 267 268 269 //A 270 const setA = (pageX) => { 271 pageX = (pageX - this.domElementRect.x - this.viewAScroll.box.x) / this.viewAScroll.box.w; 272 if(pageX < 0) pageX = 0; 273 else if(pageX > 1) pageX = 1; 274 if(this.alpha !== pageX){ 275 this.alpha = pageX; 276 if(typeof this.onchange === "function") this.onchange(this.value); 277 this.updateViewColorInfo(); 278 this.updateViewHValue(); 279 this.updateViewACursor(); 280 this.redraw(); 281 } 282 283 }, 284 285 onMoveA = event => { 286 setA(event.pageX); 287 }, 288 289 onUpA = () => { 290 document.body.removeEventListener("pointerup", onUpA); 291 document.body.removeEventListener("pointermove", onMoveA); 292 cae.remove(this.viewACursor, 'up', onUpA); 293 cae.remove(this.viewACursor, 'move', onMoveA); 294 295 }, 296 297 onDownA = event => { 298 setA(event.pageX); 299 cae.add(this.viewACursor, "up", onUpA); 300 cae.add(this.viewACursor, "move", onMoveA); 301 document.body.addEventListener("pointerup", onUpA); 302 document.body.addEventListener("pointermove", onMoveA); 303 304 } 305 306 cae.add(this.viewAScroll, "down", onDownA); 307 cae.add(this.viewACursor, "down", onDownA); 308 this.onUpA = onUpA; 309 310 this.cae = cae; 311 312 } 313 314 315 //SV 明度 与 灰度 316 updateViewSVCursor(){ 317 this.viewSVCursor.pos(this.hsv.s / 100 * this.viewSVColor.box.w + this.viewSVColor.box.x - this.viewSVCursor.circle.r, (1 - this.hsv.v / 100) * this.viewSVColor.box.h + this.viewSVColor.box.y - this.viewSVCursor.circle.r); 318 } 319 320 updateViewSVColor(){ 321 this.viewSVColor.clear().fill(ColorTestViewer.emptyColor.setFormHSV(this.hsv.h, 100, 100).getHexString()); 322 323 } 324 325 setViewSVPos(x, y){ 326 this.viewSVColor.pos(x, y); 327 this.viewSVsv.pos(x, y); 328 this.updateViewSVCursor(); 329 } 330 331 initViewSVColor(width, height){ //*3 332 this.viewSVColor = new CanvasAnimateCustom().size(width, height).rect(); 333 334 this.viewSVsv = new CanvasAnimateCustom().size(width, height); 335 const gradientS = this.viewSVsv.linearGradient(0, height, width, height, ColorTestViewer.colorS, true), 336 gradientV = this.viewSVsv.linearGradient(width, height, width, 0, ColorTestViewer.colorV, true); 337 this.viewSVsv.rect().fill(gradientS).fill(gradientV); 338 339 this.viewSVCursor = new CanvasAnimateCustom().size(10, 10); 340 this.viewSVCursor.computeCircle(); 341 this.viewSVCursor.arc().stroke("#fff"); 342 343 this.list.push(this.viewSVColor, this.viewSVsv, this.viewSVCursor); 344 345 this.setViewSVPos(0, 0); 346 this.updateViewSVColor(); 347 348 } 349 350 351 //H 颜色 352 updateViewHValue(){ 353 this.viewHValue.clear().fill(this.rgb.getRGBA(this.alpha)); 354 355 } 356 357 setViewHValuePos(x, y){ 358 this.viewHValueBG.pos(x, y); 359 this.viewHValue.pos(x, y); 360 361 } 362 363 initViewHValue(width, height){ //*2 364 this.viewHValueBG = new CanvasAnimateCustom().size(width, height) 365 .drawTransparentBG(5, 0, 0, width, height); 366 367 this.viewHValue = new CanvasAnimateCustom().size(width, height) 368 .rect(); 369 370 this.list.push(this.viewHValueBG, this.viewHValue); 371 this.updateViewHValue(); 372 373 } 374 375 updateViewHCursor(){ 376 this.viewHCursor.pos(this.hsv.h / 360 * this.viewHScroll.box.w + this.viewHScroll.box.x - this.viewHCursor.circle.r, this.viewHScroll.box.y); 377 378 } 379 380 setViewHScrollPos(x, y){ 381 this.viewHScroll.pos(x, y); 382 this.updateViewHCursor(); 383 } 384 385 initViewHScroll(width, height){ //*2 386 this.viewHScroll = new CanvasAnimateCustom().size(width, height).rect(); 387 this.viewHScroll.fill(this.viewHScroll.linearGradient(0, height, width, height, ColorTestViewer.colorH, true)); 388 389 const size = Math.min(width, height); 390 this.viewHCursor = new CanvasAnimateCustom().size(size, size); 391 this.viewHCursor.computeCircle(); 392 this.viewHCursor.arc().stroke("#fff"); 393 394 this.list.push(this.viewHScroll, this.viewHCursor); 395 this.setViewHScrollPos(0, 0); 396 397 } 398 399 400 //A 透明度 401 updateViewACursor(){ 402 this.viewACursor.pos(this.alpha * this.viewAScroll.box.w + this.viewAScroll.box.x - this.viewACursor.circle.r, this.viewAScroll.box.y); 403 404 } 405 406 setViewAScrollPos(x, y){ 407 this.viewAScroll.pos(x, y); 408 this.updateViewACursor(); 409 } 410 411 initViewAScroll(width, height){ //*2 412 this.viewAScroll = new CanvasAnimateCustom().size(width, height) 413 .drawTransparentBG(5, 0, 0, width, height).rect(); 414 this.viewAScroll.fill(this.viewAScroll.linearGradient(0, height, width, height, ColorTestViewer.colorA)); 415 416 const size = Math.min(width, height); 417 this.viewACursor = new CanvasAnimateCustom().size(size, size); 418 this.viewACursor.computeCircle(); 419 this.viewACursor.arc().stroke("rgb(0,160,255)"); 420 421 this.list.push(this.viewAScroll, this.viewACursor); 422 this.setViewAScrollPos(0, 0); 423 424 } 425 426 427 //color text 428 updateViewColorInfo(){ 429 430 this.viewColorInfo.clear().text(this.value, "#000000", 12, "center", "center"); 431 432 } 433 434 initViewColorInfo(width, height){ //*1 435 this.viewColorInfo = new CanvasAnimateCustom().size(width, height); 436 this.list.push(this.viewColorInfo); 437 this.updateViewColorInfo(); 438 } 439 440 441 442 static emptyColor = new RGBColor(); 443 444 static colorH = function (){ //颜色渐变 445 const result = [], color = ColorTestViewer.emptyColor; 446 for(let h = 0; h < 6; h++){ 447 color.setFormHSV(h/6*360, 100, 100); 448 result.push(color.getHexString()); 449 } 450 451 return result; 452 }(); 453 454 static colorS = function (){ //饱和度的渐变 455 const result = []; 456 for(let s = 0; s < 100; s++) result.push('rgba(255,255,255,' + (1 - s / 100) + ")"); 457 return result; 458 }(); 459 460 static colorV = function (){ //明度渐变 461 const result = []; 462 for(let s = 0; s < 100; s++) result.push('rgba(0,0,0,' + (1 - s / 100) + ")"); 463 return result; 464 }(); 465 466 static colorA = function (){ //透明度渐变 467 const result = []; 468 for(let a = 0; a <= 10; a++) result.push('rgba(0,0,0,' + (a / 10) + ")"); 469 return result; 470 }(); 471 472 }
部分代码
类API说明
attribute:
onchange: Function(color); //颜色改变回调; 默认null
//以下属性不建议直接修改
rgb: RGBColor; //rgb模式颜色
hsv: Object{h,s,v}; //hsv模式颜色
alpha: Number; //透明度
method:
update(): undefined; //更新控件视图 (通常控件被唤出时调用此方法, 前提是在唤出前控件颜色发生了改变)
setValue(r, g, b, a): this; //设置控件的颜色
demo:
1 const ctv = new ColorTestViewer({width: 200}) 2 3 //设置调试器的颜色 4 .setValue(0, 0, 255, 1) 5 6 //更新调试器 7 .update(false) 8 9 //设置元素位置, 渲染画布, 添加到body 10 .pos(100, 100).render(); 11 12 //监听调试器的变动 13 ctv.onchange = v => console.log(v);
提取地址: //pan.baidu.com/s/1TV1j5BeZ7ZhidCq7aQXePA
提取码: 1111