From 1d4c41ff5a5c117afecd99ee11cf6d06f5ff0273 Mon Sep 17 00:00:00 2001 From: cpsdqs Date: Sun, 1 Oct 2017 09:31:14 +0200 Subject: [PATCH] =?UTF-8?q?Add=202x=20to=20color=20triangle,=20and=20use?= =?UTF-8?q?=20camelCase=20&=20=CF=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/lib/color_utils.js | 48 ++++----- js/lib/colortriangle.js | 210 ++++++++++++++++++---------------------- js/term/themes.js | 6 +- 3 files changed, 116 insertions(+), 148 deletions(-) diff --git a/js/lib/color_utils.js b/js/lib/color_utils.js index 1ed5a65..c3f490a 100644 --- a/js/lib/color_utils.js +++ b/js/lib/color_utils.js @@ -29,9 +29,9 @@ *******************/ const M = Math -const PI = M.PI +const TAU = 2 * M.PI -exports.hue_to_rgb = function (v1, v2, h) { +exports.hue2rgb = function (v1, v2, h) { if (h < 0) h += 1 if (h > 1) h -= 1 @@ -41,8 +41,8 @@ exports.hue_to_rgb = function (v1, v2, h) { return v1 } -exports.hsl_to_rgb = function (h, s, l) { - h /= 2 * PI +exports.hsl2rgb = function (h, s, l) { + h /= TAU let r, g, b if (s === 0) { @@ -55,14 +55,14 @@ exports.hsl_to_rgb = function (h, s, l) { var_1 = 2 * l - var_2 - r = exports.hue_to_rgb(var_1, var_2, h + (1 / 3)) - g = exports.hue_to_rgb(var_1, var_2, h) - b = exports.hue_to_rgb(var_1, var_2, h - (1 / 3)) + r = exports.hue2rgb(var_1, var_2, h + (1 / 3)) + g = exports.hue2rgb(var_1, var_2, h) + b = exports.hue2rgb(var_1, var_2, h - (1 / 3)) } return [r, g, b] } -exports.rgb_to_hsl = function (r, g, b) { +exports.rgb2hsl = function (r, g, b) { const min = M.min(r, g, b) const max = M.max(r, g, b) const d = max - min // delta @@ -90,39 +90,29 @@ exports.rgb_to_hsl = function (r, g, b) { if (h < 0) h += 1 else if (h > 1) h -= 1 } - h *= 2 * PI + h *= TAU return [h, s, l] } -exports.hex_to_rgb = function (hex) { - const groups = hex.match(/^#([A-Fa-f0-9]+)$/) - if (groups && groups[1].length % 3 === 0) { +exports.hex2rgb = function (hex) { + const groups = hex.match(/^#([\da-f]{3,6})$/i) + if (groups) { hex = groups[1] const bytes = hex.length / 3 - const max = Math.pow(16, bytes) - 1 - const r = parseInt(hex.slice(0 * bytes, 1 * bytes), 16) / max - const g = parseInt(hex.slice(1 * bytes, 2 * bytes), 16) / max - const b = parseInt(hex.slice(2 * bytes, 3 * bytes), 16) / max - return [r, g, b] + const max = (16 ** bytes) - 1 + return [0, 1, 2].map(x => parseInt(hex.slice(x * bytes, (x + 1) * bytes), 16) / max) } return [0, 0, 0] } function pad (n) { - if (n.length === 1) n = '0' + n - return n + return `00${n}`.substr(-2) } -exports.rgb255_to_hex = function (r, g, b) { - r = r.toString(16) - g = g.toString(16) - b = b.toString(16) - return `#${pad(r)}${pad(g)}${pad(b)}` +exports.rgb255ToHex = function (r, g, b) { + return '#' + [r, g, b].map(x => pad(x.toString(16))).join('') } -exports.rgb_to_hex = function (r, g, b) { - r = Math.round(r * 255).toString(16) - g = Math.round(g * 255).toString(16) - b = Math.round(b * 255).toString(16) - return `#${pad(r)}${pad(g)}${pad(b)}` +exports.rgb2hex = function (r, g, b) { + return '#' + [r, g, b].map(x => pad(Math.round(x * 255).toString(16))).join('') } diff --git a/js/lib/colortriangle.js b/js/lib/colortriangle.js index 8523be7..699f351 100644 --- a/js/lib/colortriangle.js +++ b/js/lib/colortriangle.js @@ -21,18 +21,20 @@ */ // NOTE: Converted to ES6 by MightyPork (2017) +// Modified for ESPTerm +const EventEmitter = require('events') const { - rgb_to_hex, - hex_to_rgb, - hsl_to_rgb, - rgb_to_hsl + rgb2hex, + hex2rgb, + hsl2rgb, + rgb2hsl } = require('./color_utils') const win = window const doc = document const M = Math -const PI = M.PI +const TAU = 2 * M.PI function times (i, fn) { for (let j = 0; j < i; j++) { @@ -54,13 +56,15 @@ function each (obj, fn) { } } -module.exports = class ColorTriangle { +module.exports = class ColorTriangle extends EventEmitter { /**************** * ColorTriangle * ****************/ // Constructor function: constructor (color, options) { + super() + this.options = { size: 150, padding: 8, @@ -74,15 +78,17 @@ module.exports = class ColorTriangle { background: 'transparent' } - this._setOptions(options) - this._calculateProperties() + this.pixelRatio = window.devicePixelRatio + + this.setOptions(options) + this.calculateProperties() - this._createContainer() - this._createTriangle() - this._createWheel() - this._createWheelPointer() - this._createTrianglePointer() - this._attachEvents() + this.createContainer() + this.createTriangle() + this.createWheel() + this.createWheelPointer() + this.createTrianglePointer() + this.attachEvents() color = color || '#f00' if (typeof color == 'string') { @@ -90,7 +96,7 @@ module.exports = class ColorTriangle { } } - _calculateProperties () { + calculateProperties () { let opts = this.options this.padding = opts.padding @@ -104,10 +110,10 @@ module.exports = class ColorTriangle { this.triangleSideLength = M.sqrt(3) * this.triangleRadius } - _calculatePositions () { + calculatePositions () { const r = this.triangleRadius const hue = this.hue - const third = (2 / 3) * PI + const third = TAU / 3 const s = this.saturation const l = this.lightness @@ -128,7 +134,7 @@ module.exports = class ColorTriangle { this.y = sy + (vy - sy) * l + (hy - my) * a } - _createContainer () { + createContainer () { let c = this.container = doc.createElement('div') c.className = 'color-triangle' @@ -141,38 +147,41 @@ module.exports = class ColorTriangle { c.style.background = this.options.background } - _createWheel () { + createWheel () { let c = this.wheel = doc.createElement('canvas') - c.width = c.height = this.innerSize + c.width = c.height = this.innerSize * this.pixelRatio + c.style.width = c.style.height = `${this.innerSize}px` c.style.position = 'absolute' c.style.margin = c.style.padding = '0' c.style.left = c.style.top = `${this.padding}px` - this._drawWheel(c.getContext('2d')) + this.drawWheel(c.getContext('2d')) this.container.appendChild(c) } - _drawWheel (ctx) { + drawWheel (ctx) { let s, i ctx.save() + ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0) ctx.translate(this.wheelRadius, this.wheelRadius) s = this.wheelRadius - this.triangleRadius // Draw a circle for every color for (i = 0; i < 360; i++) { - ctx.rotate(PI / -180) // rotate one degree + ctx.rotate(TAU / -360) // rotate one degree ctx.beginPath() ctx.fillStyle = 'hsl(' + i + ', 100%, 50%)' - ctx.arc(this.wheelRadius - (s / 2), 0, s / 2, 0, PI * 2, true) + ctx.arc(this.wheelRadius - (s / 2), 0, s / 2, 0, TAU, true) ctx.fill() } ctx.restore() } - _createTriangle () { + createTriangle () { let c = this.triangle = doc.createElement('canvas') - c.width = c.height = this.innerSize + c.width = c.height = this.innerSize * this.pixelRatio + c.style.width = c.style.height = `${this.innerSize}px` c.style.position = 'absolute' c.style.margin = c.style.padding = '0' c.style.left = c.style.top = this.padding + 'px' @@ -182,7 +191,7 @@ module.exports = class ColorTriangle { this.container.appendChild(c) } - _drawTriangle () { + drawTriangle () { const hx = this.hx const hy = this.hy const sx = this.sx @@ -194,9 +203,10 @@ module.exports = class ColorTriangle { let ctx = this.triangleCtx // clear - ctx.clearRect(0, 0, size, size) + ctx.clearRect(0, 0, size * this.pixelRatio, size * this.pixelRatio) ctx.save() + ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0) ctx.translate(this.wheelRadius, this.wheelRadius) // make a triangle @@ -213,7 +223,7 @@ module.exports = class ColorTriangle { // create gradient from hsl(hue, 1, 1) to transparent let grad0 = ctx.createLinearGradient(hx, hy, (sx + vx) / 2, (sy + vy) / 2) - const hsla = 'hsla(' + M.round(this.hue * (180 / PI)) + ', 100%, 50%, ' + const hsla = 'hsla(' + M.round(this.hue * (360 / TAU)) + ', 100%, 50%, ' grad0.addColorStop(0, hsla + '1)') grad0.addColorStop(1, hsla + '0)') ctx.fillStyle = grad0 @@ -233,57 +243,60 @@ module.exports = class ColorTriangle { } // The two pointers - _createWheelPointer () { + createWheelPointer () { let c = this.wheelPointer = doc.createElement('canvas') const size = this.wheelPointerSize - c.width = c.height = size + c.width = c.height = size * this.pixelRatio + c.style.width = c.style.height = `${size}px` c.style.position = 'absolute' c.style.margin = c.style.padding = '0' - this._drawPointer(c.getContext('2d'), size / 2, this.options.wheelPointerColor1, this.options.wheelPointerColor2) + this.drawPointer(c.getContext('2d'), size / 2, this.options.wheelPointerColor1, this.options.wheelPointerColor2) this.container.appendChild(c) } - _moveWheelPointer () { + moveWheelPointer () { const r = this.wheelPointerSize / 2 const s = this.wheelPointer.style s.top = this.padding + this.wheelRadius - M.sin(this.hue) * (this.triangleRadius + this.wheelThickness / 2) - r + 'px' s.left = this.padding + this.wheelRadius + M.cos(this.hue) * (this.triangleRadius + this.wheelThickness / 2) - r + 'px' } - _createTrianglePointer () { // create pointer in the triangle + createTrianglePointer () { // create pointer in the triangle let c = this.trianglePointer = doc.createElement('canvas') const size = this.options.trianglePointerSize - c.width = c.height = size + c.width = c.height = size * this.pixelRatio + c.style.width = c.style.height = `${size}px` c.style.position = 'absolute' c.style.margin = c.style.padding = '0' - this._drawPointer(c.getContext('2d'), size / 2, this.options.trianglePointerColor1, this.options.trianglePointerColor2) + this.drawPointer(c.getContext('2d'), size / 2, this.options.trianglePointerColor1, this.options.trianglePointerColor2) this.container.appendChild(c) } - _moveTrianglePointer (x, y) { + moveTrianglePointer (x, y) { const s = this.trianglePointer.style const r = this.options.trianglePointerSize / 2 s.top = (this.y + this.wheelRadius + this.padding - r) + 'px' s.left = (this.x + this.wheelRadius + this.padding - r) + 'px' } - _drawPointer (ctx, r, color1, color2) { + drawPointer (ctx, r, color1, color2) { + ctx.setTransform(this.pixelRatio, 0, 0, this.pixelRatio, 0, 0) ctx.fillStyle = color2 ctx.beginPath() - ctx.arc(r, r, r, 0, PI * 2, true) + ctx.arc(r, r, r, 0, TAU, true) ctx.fill() // => black circle ctx.fillStyle = color1 ctx.beginPath() - ctx.arc(r, r, r - 2, 0, PI * 2, true) + ctx.arc(r, r, r - 2, 0, TAU, true) ctx.fill() // => white circle with 1px black border ctx.fillStyle = color2 ctx.beginPath() - ctx.arc(r, r, r / 4 + 2, 0, PI * 2, true) + ctx.arc(r, r, r / 4 + 2, 0, TAU, true) ctx.fill() // => black circle with big white border and a small black border ctx.globalCompositeOperation = 'destination-out' ctx.beginPath() - ctx.arc(r, r, r / 4, 0, PI * 2, true) + ctx.arc(r, r, r / 4, 0, TAU, true) ctx.fill() // => transparent center } @@ -292,7 +305,7 @@ module.exports = class ColorTriangle { parent.appendChild(this.container) } - _getRelativeCoordinates (evt) { + getRelativeCoordinates (evt) { let elem = this.triangle let rect = elem.getBoundingClientRect() @@ -315,7 +328,7 @@ module.exports = class ColorTriangle { // Color accessors getCSS () { - const h = Math.round(this.hue * (180 / PI)) + const h = Math.round(this.hue * (360 / TAU)) const s = Math.round(this.saturation * 100) const l = Math.round(this.lightness * 100) @@ -323,19 +336,19 @@ module.exports = class ColorTriangle { } getHEX () { - return rgb_to_hex(...this.getRGB()) + return rgb2hex(...this.getRGB()) } setHEX (hex) { - this.setRGB(...hex_to_rgb(hex)) + this.setRGB(...hex2rgb(hex)) } getRGB () { - return hsl_to_rgb(...this.getHSL()) + return hsl2rgb(...this.getHSL()) } setRGB (r, g, b) { - this.setHSL(...rgb_to_hsl(r, g, b)) + this.setHSL(...rgb2hsl(r, g, b)) } getHSL () { @@ -347,18 +360,18 @@ module.exports = class ColorTriangle { this.saturation = s this.lightness = l - this._initColor() + this.initColor() } - _initColor () { - this._calculatePositions() - this._moveWheelPointer() - this._drawTriangle() - this._moveTrianglePointer() + initColor () { + this.calculatePositions() + this.moveWheelPointer() + this.drawTriangle() + this.moveTrianglePointer() } // Mouse event handling - _attachEvents () { + attachEvents () { this.down = null let mousedown = (evt) => { @@ -368,19 +381,19 @@ module.exports = class ColorTriangle { doc.body.addEventListener('mousemove', mousemove, false) doc.body.addEventListener('mouseup', mouseup, false) - let xy = this._getRelativeCoordinates(evt) - this._map(xy.x, xy.y) + let xy = this.getRelativeCoordinates(evt) + this.map(xy.x, xy.y) } let mousemove = (evt) => { - let xy = this._getRelativeCoordinates(evt) - this._move(xy.x, xy.y) + let xy = this.getRelativeCoordinates(evt) + this.move(xy.x, xy.y) } let mouseup = (evt) => { if (this.down) { this.down = null - this._fireEvent('dragend') + this.emit('dragend') } doc.body.removeEventListener('mousemove', mousemove, false) doc.body.removeEventListener('mouseup', mouseup, false) @@ -390,7 +403,7 @@ module.exports = class ColorTriangle { this.container.addEventListener('mousemove', mousemove, false) } - _map (x, y) { + map (x, y) { let x0 = x let y0 = y x -= this.wheelRadius @@ -400,17 +413,17 @@ module.exports = class ColorTriangle { if (r > this.triangleRadius && r < this.wheelRadius) { // Wheel this.down = 'wheel' - this._fireEvent('dragstart') - this._move(x0, y0) + this.emit('dragstart') + this.move(x0, y0) } else if (r < this.triangleRadius) { // Inner circle this.down = 'triangle' - this._fireEvent('dragstart') - this._move(x0, y0) + this.emit('dragstart') + this.move(x0, y0) } } - _move (x, y) { + move (x, y) { if (!this.down) { return } @@ -420,17 +433,17 @@ module.exports = class ColorTriangle { let rad = M.atan2(-y, x) if (rad < 0) { - rad += 2 * PI + rad += TAU } if (this.down === 'wheel') { this.hue = rad - this._initColor() - this._fireEvent('drag') + this.initColor() + this.emit('drag') } else if (this.down === 'triangle') { // get radius and max radius - let rad0 = (rad + 2 * PI - this.hue) % (2 * PI) - let rad1 = rad0 % ((2 / 3) * PI) - (PI / 3) + let rad0 = (rad + TAU - this.hue) % TAU + let rad1 = rad0 % (TAU / 3) - (TAU / 6) let a = 0.5 * this.triangleRadius let b = M.tan(rad1) * a let r = M.sqrt(x * x + y * y) // Pythagoras @@ -439,15 +452,15 @@ module.exports = class ColorTriangle { if (r > maxR) { const dx = M.tan(rad1) * r let rad2 = M.atan(dx / maxR) - if (rad2 > PI / 3) { - rad2 = PI / 3 - } else if (rad2 < -PI / 3) { - rad2 = -PI / 3 + if (rad2 > TAU / 6) { + rad2 = TAU / 6 + } else if (rad2 < -TAU / 6) { + rad2 = -TAU / 6 } rad += rad2 - rad1 - rad0 = (rad + 2 * PI - this.hue) % (2 * PI) - rad1 = rad0 % ((2 / 3) * PI) - (PI / 3) + rad0 = (rad + TAU - this.hue) % TAU + rad1 = rad0 % (TAU / 3) - (TAU / 6) b = M.tan(rad1) * a r = maxR = M.sqrt(a * a + b * b) // Pythagoras } @@ -467,9 +480,9 @@ module.exports = class ColorTriangle { this.x = x this.y = y - this._moveTrianglePointer() + this.moveTrianglePointer() - this._fireEvent('drag') + this.emit('drag') } } @@ -491,7 +504,7 @@ module.exports = class ColorTriangle { options.event = options.event || 'dragend' ct = new ColorTriangle(hex, options) - ct.addEventListener(options.event, () => { + ct.on(options.event, () => { const hex = ct.getHEX() input.value = options.uppercase ? hex.toUpperCase() : hex fireChangeEvent() @@ -545,7 +558,7 @@ module.exports = class ColorTriangle { * Helper functions * *******************/ - _setOptions (opts) { + setOptions (opts) { opts = opts || {} let dflt = this.options let options = this.options = {} @@ -556,39 +569,4 @@ module.exports = class ColorTriangle { : val }) } - - addEventListener (type, fn) { - if (!this.events) { - this.events = {} - } - if (!this.events[type]) { - this.events[type] = [] - } - this.events[type].push(fn) - } - - removeEventListener (type, fn) { - if (this.events) { - let fns = this.events[type] - const l = fns.length - for (let i = 0; i < l; i += 1) { - if (fns[i] === fn) { - fns.splice(i, 1) - break - } - } - } - } - - _fireEvent (type) { - if (this.events) { - let evts = this.events[type] - if (evts) { - const args = Array.prototype.slice.call(arguments, 1) - each(evts, function (evt) { - evt(...args) - }) - } - } - } } diff --git a/js/term/themes.js b/js/term/themes.js index a1b84ee..8fb47ac 100644 --- a/js/term/themes.js +++ b/js/term/themes.js @@ -1,5 +1,5 @@ const $ = require('../lib/chibi') -const { rgb255_to_hex } = require('../lib/color_utils') +const { rgb255ToHex } = require('../lib/color_utils') const themes = exports.themes = [ [ // 0 - Tango - terminator @@ -84,14 +84,14 @@ exports.buildColorTable = function () { let redValue = red * 40 + (red ? 55 : 0) let greenValue = green * 40 + (green ? 55 : 0) let blueValue = blue * 40 + (blue ? 55 : 0) - colorTable256.push(rgb255_to_hex(redValue, greenValue, blueValue)) + colorTable256.push(rgb255ToHex(redValue, greenValue, blueValue)) } } } // colors 232-255 are a grayscale ramp, sans black and white for (let gray = 0; gray < 24; gray++) { let value = gray * 10 + 8 - colorTable256.push(rgb255_to_hex(value, value, value)) + colorTable256.push(rgb255ToHex(value, value, value)) } return colorTable256