UNPKG

aico-image-editor

Version:

Combine multiple image into and create single combined image

360 lines (318 loc) 12.9 kB
// import '../../scss/main.scss'; // import '../../scss/custom.scss'; // Load your styles using style-loader //import Alpine from 'alpinejs'; import chroma from "chroma-js"; const loadColorPickerHTML = () => import(/* webpackMode: "eager" */'./colorPicker.html'); // initialize custom made styles and html loading modules// // inspired by alpine js component// import initStyles from '../../initStyles'; import initHTML from '../../initHTML'; initHTML('color-picker',loadColorPickerHTML, ['eventname']); // const container = document.getElementById('canvas-holder'); // const circle = document.getElementById('colorpicker-circle'); // const canvas = document.getElementById('colorpicker'); import { ColorUtils } from './color-utilities'; export default () => ({ get componentKey() { return this.$el.getRootNode().host.getAttribute('key') }, container: null, circle: null, canvas: null, hue: 0, saturation: 0, lightness: 0, updateOutputPosition() { document.documentElement.style.setProperty('--hue', this.hue); }, updateRGBFromHue() { this.updateOutputPosition(); let [h,s,l] = ColorUtils.rgbToHSL(this.red, this.green, this.blue); const newHue = this.hue; const [r,g,b] = ColorUtils.hslToRGB(newHue,s,l); this.red = r; this.green = g; this.blue = b; // this.saturation = s = Math.round(s); // this.lightness = l = Math.round(l); this.saturation = s; this.lightness = l; this.updateColorsInOtherModes('rgb'); //console.log('rgb updated') }, updateColorsInOtherModes(mode) { //this alternate syntax can be used in place of get/set //el._x_model.set(Math.min(255, Math.max(0, el._x_model.get()))); let self = this; if(mode === 'rgb') { const [h,s,l] = ColorUtils.rgbToHSL(this.red, this.green, this.blue); // this.hue = h = Math.round(h); // this.lightness = l = Math.round(l); // this.saturation = s = Math.round(s); this.hue = h; this.lightness = l; this.saturation = s; this.updateOutputPosition(); //console.log('hsl updated'); const [c,m,y,k] = ColorUtils.rgbToCMYK(this.red, this.green, this.blue) this.cyan = c; this.magenta = m; this.yellow = y; this.key = k; const hex = ColorUtils.rgbToHEX(this.red, this.green, this.blue) this.hex = hex; } else if (mode === 'cmyk') { const [h,s,l] = ColorUtils.cmykToHSL(this.cyan, this.magenta, this.yellow,this.key); this.hue = h; this.lightness = l; this.saturation = s; this.updateOutputPosition(); //console.log('hsl updated'); const [r,g,b] = ColorUtils.cmykToRGB(this.cyan, this.magenta, this.yellow,this.key); this.red = r; this.green = g; this.blue = b; const hex = ColorUtils.cmykToHEX(this.cyan, this.magenta, this.yellow,this.key); this.hex = hex; } else if (mode === 'hex') { if(this.isHexCode(this.hex)) { const [h,s,l] = ColorUtils.hexToHSL(this.hex); this.hue = h; this.lightness = l; this.saturation = s; this.updateOutputPosition(); //console.log('hsl updated'); const [c,m,y,k] = ColorUtils.hexToCMYK(this.hex); this.cyan = c; this.magenta = m; this.yellow = y; this.key = k; const [r,g,b] = ColorUtils.hexToRGB(this.hex); this.red = r; this.green = g; this.blue = b; } } }, _red: 0, get red() { return this._red; }, set red(val) { this._red = Math.min(255, Math.max(0, val)) }, _green: 0, get green() { return this._green; }, set green(val) { this._green = Math.min(255, Math.max(0, val)) }, _blue: 0, get blue() { return this._blue; }, set blue(val) { this._blue = Math.min(255, Math.max(0, val)) }, _cyan: 0.0000, get cyan() { return this._cyan; }, set cyan(val) { this._cyan = Math.min(100, Math.max(0, val)) }, _magenta: 0.0000, get magenta() { return this._magenta; }, set magenta(val) { this._magenta = Math.min(100, Math.max(0, val)) }, _yellow: 0.0000, get yellow() { return this._yellow; }, set yellow(val) { this._yellow = Math.min(100, Math.max(0, val)) }, _key: 1.0000, get key() { return this._key; }, set key(val) { this._key = Math.min(100, Math.max(0, val)) }, _hex: '#000000', get hex() { return this._hex; }, set hex(val) { this._hex = val; }, hexCheck() { this.hex = this.isHexCode(this.hex) ? this.hex : '#000000'; this.updateColorsInOtherModes('hex'); }, isHexCode(hexcode) { return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(hexcode) }, triggerSelectedColorEvent(initTime) { // eventName is kept to identify component (in case of multiple used) and dispatch event based on eventname attribute set while consuming component // e.g. event name will be "gradientcolor-updated-in-colorpicker" in case of gradientcolor this.$dispatch(`${this.eventName}-updated-in-colorpicker`, {colorObj: {id: 'tempcolor', color:this.selectedColor, initTime: initTime}}) }, get selectedColor() { let rgbColor = `rgb(${this.red},${this.green},${this.blue})`; //this.$store.canvas.setLabelColor(color); let color = chroma(rgbColor).hex(); //this.activeColorObj = {}; return color; }, colordatawrapper: { //get r,g and b color data from event emitted by nested elements // amd set them back to r, g and b values here for selectedcolor ['@color-selected'](event) { this.red = event.detail.r; this.green = event.detail.g; this.blue = event.detail.b; this.updateColorsInOtherModes('rgb') }, ['@color-updated-from-outer-component.window'](event) { if(this.componentKey === event.detail.componentKey) { this.hex = event.detail.hex this.updateColorsInOtherModes('hex') // update circle position this.$dispatch('color-updated',{ h: this.hue, s: this.saturation, l: this.lightness, componentKey: this.componentKey }) } } }, //spectrum data starts here isMouseDown: false, init() { initStyles(this.$el.shadowRoot); this.container = this.$refs.canvasholder; this.circle = this.$refs.colorpickercircle; this.canvas = this.$refs.colorpicker; this.initColorPicker(); }, initColorPicker() { const [width, height] = [200, 205]; [this.canvas.width, this.canvas.height] = [width, height]; this.drawColors(this.canvas); // init this event at init time when initTime is true along with event detail this.triggerSelectedColorEvent(true) // and also keep watch of selectedColor and retrigger the same event as above this.$watch('selectedColor', () => { this.triggerSelectedColorEvent(false) }) }, drawColors(canvas) { const context = canvas.getContext('2d',{ willReadFrequently: true }); const {width, height} = canvas; //Colors - horizontal gradient const gradientH = context.createLinearGradient(0, 0, width, 0); gradientH.addColorStop(0, "rgb(255, 0, 0)"); // red gradientH.addColorStop(1/6, "rgb(255, 255, 0)"); // yellow gradientH.addColorStop(2/6, "rgb(0, 255, 0)"); // green gradientH.addColorStop(3/6, "rgb(0, 255, 255)"); gradientH.addColorStop(4/6, "rgb(0, 0, 255)"); // blue gradientH.addColorStop(5/6, "rgb(255, 0, 255)"); gradientH.addColorStop(1, "rgb(255, 0, 0)"); // red context.fillStyle = gradientH; context.fillRect(0, 0, width, height); //Shades - vertical gradient const gradientV = context.createLinearGradient(0, 0, 0, height); gradientV.addColorStop(0, "rgba(255, 255, 255, 1)"); gradientV.addColorStop(0.5, "rgba(255, 255, 255, 0)"); gradientV.addColorStop(0.5, "rgba(0, 0, 0, 0)"); gradientV.addColorStop(1, "rgba(0, 0, 0, 1)"); context.fillStyle = gradientV; context.fillRect(0, 0, width, height); }, getCanvasPointCoordinates(event,canvas) { const rect = canvas.getBoundingClientRect(); let x = event.clientX - rect.left; //x position within the element. let y = event.clientY - rect.top; //y position within the element. //on clicking on last co-ordinate of canvas r,g and b are 0 and //hence incorrect data was returned so maximum is it's 1px less than width x = Math.min(canvas.width, Math.max(0,x)); y = Math.min(canvas.height, Math.max(0,y)); return {x,y}; }, setCircleBorderColor(lightness) { const txtColor = lightness < 50 ? '#FFF' : '#000'; this.circle.style.borderColor = txtColor; }, pickColor(event, canvas, circle) { const context = canvas.getContext('2d',{ willReadFrequently: true }); const {x, y} = this.getCanvasPointCoordinates(event,canvas) const imgData = context.getImageData(x, y, 1, 1); let [r, g, b] = imgData.data; const [h, s, l] = ColorUtils.rgbToHSL(r, g, b); this.setCircleBorderColor(l); canvas.dispatchEvent(new CustomEvent('color-selected', { bubbles: true, detail: {r, g, b, h, s, l} })); }, updateCirclePosition(event,canvas,circle) { const {x, y} = this.getCanvasPointCoordinates(event,canvas) circle.style.top = (y - 0) + 'px'; circle.style.left = (x - 0) + 'px'; }, getWrapperConfig() { return { ['@mousedown'](event) { this.isMouseDown = true; }, ['@mouseup'](event) { this.isMouseDown = false; this.updateCirclePosition(event, this.canvas, this.circle); this.pickColor(event, this.canvas, this.circle) }, ['@mousemove'](event) { if(this.isMouseDown) { this.updateCirclePosition(event, this.canvas, this.circle) } }, ['@mouseup.outside'](event) { if(this.isMouseDown) { this.isMouseDown = false; this.updateCirclePosition(event, this.canvas, this.circle) this.pickColor(event, this.canvas, this.circle) } }, ['@color-updated.window'](event) { if(event.detail.componentKey === this.componentKey) { const [h,s,l] = [event.detail.h,event.detail.s, event.detail.l]; const leftpx = ((h * this.canvas.width) / 360) + 'px', toppx = ((100- l) * (this.canvas.height/100)) + 'px'; this.setCircleBorderColor(l); //console.log(leftpx, toppx) this.circle.style.left = leftpx; this.circle.style.top = toppx; } }, [`@eventname-${this.componentKey}-changed.window`](event) { // eventName will be set here when attribute is first assigned when its html loads // at that time attributeChangedCallback will fire and that will dispatch // eventName like `${attr}-${key}-changed` where attr is "eventname" and key is // kept to fully isolate two components even when eventname is same because key can never be the same. // in this case eventname is observed attribute so event is "eventname-1-changed" dispatched which is received here // key must be differnt for two components e.g. 1, 2 and so on.... // and thus, eventName prop here will be set to whatever attribute is passed while consuming component (gradientcolor or textcolor) this.eventName = event.detail.eventName; } } }, eventName: '', getChromaHex(selectedColor) { return chroma(selectedColor).hex(); } })