mirror of
https://github.com/piskelapp/piskel.git
synced 2023-08-10 21:12:52 +03:00
Extracted ColorPicker code to dedicated widget package (noooooooo) ; Added basic palette creation mechanism (list colors + add color)
This commit is contained in:
parent
7d9f8a8ccf
commit
e8db80a0ec
96
src/css/color-picker-slider.css
Normal file
96
src/css/color-picker-slider.css
Normal file
@ -0,0 +1,96 @@
|
||||
.color-picker-slider * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.color-picker-slider input[type="range"] {
|
||||
-webkit-appearance: none;
|
||||
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
|
||||
width: 100%;
|
||||
border: none;
|
||||
padding: 1px 2px;
|
||||
border-radius: 3px;
|
||||
background-image: linear-gradient(to right, hsl(0, 30%, 70%) 0, hsl(359, 30%, 70%) 100%);
|
||||
box-shadow: inset 0 1px 0 0 #0d0e0f, inset 0 -1px 0 0 #3a3d42;
|
||||
outline: none; /* no focus outline */
|
||||
}
|
||||
|
||||
/* thumb */
|
||||
|
||||
.color-picker-slider input[type="range"]::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
cursor:pointer;
|
||||
width: 7px;
|
||||
height: 18px;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #529de1), color-stop(100%, #245e8f)); /* android <= 2.2 */
|
||||
background-image: -webkit-linear-gradient(top , #529de1 0, #245e8f 100%); /* older mobile safari and android > 2.2 */;
|
||||
background-image: linear-gradient(to bottom, #529de1 0, #245e8f 100%); /* W3C */
|
||||
}
|
||||
.color-picker-slider input[type="range"]::-moz-range-thumb {
|
||||
width: 7px;
|
||||
height: 18px;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
background-image: linear-gradient(to bottom, #529de1 0, #245e8f 100%); /* W3C */
|
||||
}
|
||||
|
||||
.color-picker-slider input[type="range"]::-ms-thumb {
|
||||
width: 7px;
|
||||
height: 18px;
|
||||
border-radius: 2px;
|
||||
border: 0;
|
||||
background-image: linear-gradient(to bottom, #529de1 0, #245e8f 100%); /* W3C */
|
||||
}
|
||||
|
||||
/*CROSS BROWSER RESET*/
|
||||
|
||||
|
||||
.color-picker-slider input[type="range"]::-moz-range-track {
|
||||
border: inherit;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.color-picker-slider input[type="range"]::-ms-track {
|
||||
border: inherit;
|
||||
color: transparent; /* don't drawn vertical reference line */
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.color-picker-slider input[type="range"]::-ms-fill-lower,
|
||||
.color-picker-slider input[type="range"]::-ms-fill-upper {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.color-picker-slider input[type="range"]::-ms-tooltip {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.color-picker-slider {
|
||||
padding: 0 10px;
|
||||
height : 25px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.color-picker-slider span{
|
||||
line-height : 25px;
|
||||
width : 10px;
|
||||
float:left;
|
||||
}
|
||||
|
||||
.color-picker-slider input[type="range"]{
|
||||
float:left;
|
||||
height : 10px;
|
||||
width : 100px;
|
||||
margin: 7px 5px;
|
||||
}
|
||||
|
||||
.color-picker-slider input[type="text"]{
|
||||
float:left;
|
||||
width : 47px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.color-picker-slider input[type="range"][data-dimension="h"] {
|
||||
background-image:linear-gradient(to right, #ff0000 0%, #ffff00 17%, #00ff00 33%, #00ffff 50%, #0000ff 67%, #ff00ff 83%, #ff0000 100%);
|
||||
}
|
21
src/css/dialogs-create-palette-method.css
Normal file
21
src/css/dialogs-create-palette-method.css
Normal file
@ -0,0 +1,21 @@
|
||||
#dialog-container.create-palette-method {
|
||||
width: 500px;
|
||||
height: 200px;
|
||||
top : 50%;
|
||||
left : 50%;
|
||||
position : absolute;
|
||||
margin-left: -250px;
|
||||
}
|
||||
|
||||
.show #dialog-container.create-palette-method {
|
||||
margin-top: -100px;
|
||||
}
|
||||
|
||||
.create-palette-method-item {
|
||||
line-height : 24px;
|
||||
}
|
||||
|
||||
.create-palette-method-item label{
|
||||
margin-top: 3px;
|
||||
margin-left: 5px;
|
||||
}
|
@ -4,6 +4,8 @@
|
||||
ns.CreatePaletteController = function (piskelController) {
|
||||
this.tinyColor = null;
|
||||
this.hsvColor = {h:0,s:0,v:0};
|
||||
this.palette = [];
|
||||
this.selectedIndex = -1;
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.CreatePaletteController, ns.AbstractDialogController);
|
||||
@ -11,138 +13,58 @@
|
||||
ns.CreatePaletteController.prototype.init = function () {
|
||||
this.superclass.init.call(this);
|
||||
|
||||
$(".color-picker-spectrum").spectrum({
|
||||
flat: true,
|
||||
showInput: true,
|
||||
showButtons: false,
|
||||
change : this.setColor.bind(this)
|
||||
});
|
||||
|
||||
this.tinyColorPickerContainer = document.querySelector('.color-picker-container');
|
||||
this.tinyColorPickerContainer.addEventListener('input', this.onPickerInput_.bind(this));
|
||||
|
||||
this.colorsList = document.querySelector('.colors-list');
|
||||
this.colorPickerContainer = document.querySelector('.color-picker-container');
|
||||
this.colorPreviewEl = document.querySelector('.color-preview');
|
||||
|
||||
this.setColor("#000000");
|
||||
};
|
||||
this.colorsList.addEventListener('click', this.onColorContainerClick_.bind(this));
|
||||
|
||||
ns.CreatePaletteController.prototype.onPickerInput_ = function (evt) {
|
||||
var target = evt.target;
|
||||
this.hslRgbColorPicker = new pskl.controller.widgets.HslRgbColorPicker(this.colorPickerContainer, this.onColorUpdated_.bind(this));
|
||||
this.hslRgbColorPicker.init();
|
||||
|
||||
var model = target.dataset.model;
|
||||
var dimension = target.dataset.dimension;
|
||||
var value = parseInt(target.value, 10);
|
||||
|
||||
if (dimension === 'v' || dimension === 's') {
|
||||
value = value/100;
|
||||
}
|
||||
|
||||
var color;
|
||||
if (model === 'rgb') {
|
||||
color = this.tinyColor.toRgb();
|
||||
} else if (model === 'hsv') {
|
||||
color = this.hsvColor;
|
||||
}
|
||||
|
||||
if (isNaN(value)) {
|
||||
value = color[dimension];
|
||||
} else {
|
||||
color[dimension] = value;
|
||||
}
|
||||
|
||||
this.setColor(color);
|
||||
};
|
||||
|
||||
ns.CreatePaletteController.prototype.setColor = function (inputColor) {
|
||||
if (!this.unplugged) {
|
||||
this.unplugged = true;
|
||||
|
||||
this.hsvColor = this.toHsvColor_(inputColor);
|
||||
this.tinyColor = this.toTinyColor_(inputColor);
|
||||
|
||||
this.updateInputs();
|
||||
$(".color-picker-spectrum").spectrum("set", this.tinyColor);
|
||||
|
||||
this.onColorUpdated_(this.tinyColor);
|
||||
|
||||
this.unplugged = false;
|
||||
}
|
||||
};
|
||||
|
||||
ns.CreatePaletteController.prototype.toTinyColor_ = function (color) {
|
||||
if (typeof color == "object" && color.hasOwnProperty("_tc_id")) {
|
||||
return color;
|
||||
} else {
|
||||
return window.tinycolor(JSON.parse(JSON.stringify(color)));
|
||||
}
|
||||
};
|
||||
|
||||
ns.CreatePaletteController.prototype.toHsvColor_ = function (color) {
|
||||
var isHsvColor = ['h','s','v'].every(color.hasOwnProperty.bind(color));
|
||||
if (isHsvColor) {
|
||||
return {
|
||||
h : Math.max(0, Math.min(255, color.h)),
|
||||
s : Math.max(0, Math.min(1, color.s)),
|
||||
v : Math.max(0, Math.min(1, color.v))
|
||||
};
|
||||
} else {
|
||||
return this.toTinyColor_(color).toHsv();
|
||||
}
|
||||
};
|
||||
|
||||
ns.CreatePaletteController.prototype.updateInputs = function () {
|
||||
var inputs = this.tinyColorPickerContainer.querySelectorAll('input');
|
||||
var rgb = this.tinyColor.toRgb();
|
||||
|
||||
|
||||
for (var i = 0 ; i < inputs.length ; i++) {
|
||||
var input = inputs[i];
|
||||
var dimension = input.dataset.dimension;
|
||||
var model = input.dataset.model;
|
||||
|
||||
if (model === 'rgb') {
|
||||
input.value = rgb[dimension];
|
||||
} else if (model === 'hsv') {
|
||||
var value = this.hsvColor[dimension];
|
||||
if (dimension === 'v' || dimension === 's') {
|
||||
value = 100 * value;
|
||||
}
|
||||
input.value = Math.round(value);
|
||||
}
|
||||
|
||||
if (input.getAttribute('type') === 'range') {
|
||||
this.updateSliderBackground(input);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.CreatePaletteController.prototype.updateSliderBackground = function (slider) {
|
||||
var dimension = slider.dataset.dimension;
|
||||
var model = slider.dataset.model;
|
||||
|
||||
var start, end;
|
||||
var isHueSlider = dimension === 'h';
|
||||
if (!isHueSlider) {
|
||||
if (model === 'hsv') {
|
||||
start = JSON.parse(JSON.stringify(this.hsvColor));
|
||||
start[dimension] = 0;
|
||||
|
||||
end = JSON.parse(JSON.stringify(this.hsvColor));
|
||||
end[dimension] = 1;
|
||||
} else {
|
||||
start = this.tinyColor.toRgb();
|
||||
start[dimension] = 0;
|
||||
|
||||
end = this.tinyColor.toRgb();
|
||||
end[dimension] = 255;
|
||||
}
|
||||
var colorStart = window.tinycolor(start).toRgbString();
|
||||
var colorEnd = window.tinycolor(end).toRgbString();
|
||||
slider.style.backgroundImage = "linear-gradient(to right, " + colorStart + " 0, " + colorEnd + " 100%)";
|
||||
}
|
||||
this.refresh_();
|
||||
};
|
||||
|
||||
ns.CreatePaletteController.prototype.onColorUpdated_ = function (color) {
|
||||
this.colorPreviewEl.style.background = color.toRgbString();
|
||||
this.palette[this.selectedIndex] = color.toRgbString();
|
||||
this.refresh_();
|
||||
};
|
||||
|
||||
ns.CreatePaletteController.prototype.onColorContainerClick_ = function (evt) {
|
||||
var target = evt.target;
|
||||
if (target.dataset.paletteIndex) {
|
||||
this.selectColor_(target.dataset.paletteIndex);
|
||||
} else if (target.classList.contains('add-color-button')) {
|
||||
this.palette.push(this.palette[this.selectedIndex] || "#000000");
|
||||
this.refresh_();
|
||||
this.selectColor_(this.palette.length-1);
|
||||
}
|
||||
};
|
||||
|
||||
ns.CreatePaletteController.prototype.selectColor_ = function (index) {
|
||||
this.selectedIndex = index;
|
||||
|
||||
var previous = this.colorsList.querySelector('.selectedColor');
|
||||
if (previous) {
|
||||
previous.classList.remove('selected');
|
||||
}
|
||||
|
||||
var next = this.colorsList.querySelector('[data-palette-index="'+index+'"]');
|
||||
next.classList.add('selected');
|
||||
|
||||
this.hslRgbColorPicker.setColor(this.palette[index]);
|
||||
};
|
||||
|
||||
ns.CreatePaletteController.prototype.refresh_ = function () {
|
||||
var html = "";
|
||||
var tpl = '<div data-palette-index="{{index}}" data-palette-color="{{color}}" style="height:40px;width:40px;float:left; margin:10px;background:{{color}}"></div>';
|
||||
this.palette.forEach(function (color, index) {
|
||||
html += pskl.utils.Template.replace(tpl, {color:color, index:index});
|
||||
});
|
||||
|
||||
html += '<div class=add-color-button style="height:40px;width:40px;margin:10px;float:left; background:gold">ADD</div>';
|
||||
|
||||
this.colorsList.innerHTML = html;
|
||||
};
|
||||
})();
|
63
src/js/controller/dialogs/CreatePaletteMethodController.js
Normal file
63
src/js/controller/dialogs/CreatePaletteMethodController.js
Normal file
@ -0,0 +1,63 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller.dialogs');
|
||||
|
||||
ns.CreatePaletteMethodController = function (piskelController) {
|
||||
};
|
||||
|
||||
pskl.utils.inherit(ns.CreatePaletteMethodController, ns.AbstractDialogController);
|
||||
|
||||
ns.CreatePaletteMethodController.prototype.init = function () {
|
||||
this.superclass.init.call(this);
|
||||
|
||||
this.createButton = document.querySelector('.create-palette-method-continue');
|
||||
this.cancelButton = document.querySelector('.create-palette-method-cancel');
|
||||
|
||||
this.createButton.addEventListener('click', this.onCreateButtonClick_.bind(this));
|
||||
|
||||
this.cancelButton.addEventListener('click', function () {
|
||||
$.publish(Events.DIALOG_HIDE);
|
||||
});
|
||||
};
|
||||
|
||||
ns.CreatePaletteMethodController.prototype.onCreateButtonClick_ = function (evt) {
|
||||
var method = this.getSelectedMethod_();
|
||||
|
||||
var initArgs = {
|
||||
method : method
|
||||
};
|
||||
|
||||
if (method === 'palette') {
|
||||
initArgs.paletteId = this.getSelectedPaletteId_();
|
||||
}
|
||||
|
||||
this.closeDialog();
|
||||
|
||||
window.setTimeout(function () {
|
||||
$.publish(Events.DIALOG_DISPLAY, {
|
||||
dialogId : 'create-palette',
|
||||
initArgs : initArgs
|
||||
});
|
||||
},500);
|
||||
};
|
||||
|
||||
ns.CreatePaletteMethodController.prototype.getSelectedMethod_ = function (evt) {
|
||||
var options = document.querySelectorAll('.create-palette-method-list input[type="radio"]');
|
||||
|
||||
var method;
|
||||
for (var i = 0 ; i < options.length ; i++) {
|
||||
console.log(options[i]);
|
||||
if (options[i].checked) {
|
||||
method = options[i].value;
|
||||
}
|
||||
}
|
||||
|
||||
return method;
|
||||
};
|
||||
|
||||
ns.CreatePaletteMethodController.prototype.getSelectedPaletteId_ = function (evt) {
|
||||
var select = document.querySelector('.palettes-list-select');
|
||||
return select.value;
|
||||
};
|
||||
|
||||
|
||||
})();
|
141
src/js/controller/widgets/HslRgbColorPicker.js
Normal file
141
src/js/controller/widgets/HslRgbColorPicker.js
Normal file
@ -0,0 +1,141 @@
|
||||
(function () {
|
||||
var ns = $.namespace('pskl.controller.widgets');
|
||||
|
||||
ns.HslRgbColorPicker = function (container, colorUpdatedCallback) {
|
||||
this.container = container;
|
||||
this.colorUpdatedCallback = colorUpdatedCallback;
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.init = function () {
|
||||
this.container.addEventListener('input', this.onPickerInput_.bind(this));
|
||||
|
||||
this.spectrumEl = this.container.querySelector('.color-picker-spectrum');
|
||||
|
||||
$(this.spectrumEl).spectrum({
|
||||
flat: true,
|
||||
showInput: true,
|
||||
showButtons: false,
|
||||
move : this.setColor.bind(this),
|
||||
change : this.setColor.bind(this)
|
||||
});
|
||||
|
||||
this.setColor("#000000");
|
||||
};
|
||||
|
||||
|
||||
ns.HslRgbColorPicker.prototype.onPickerInput_ = function (evt) {
|
||||
var target = evt.target;
|
||||
|
||||
var model = target.dataset.model;
|
||||
var dimension = target.dataset.dimension;
|
||||
|
||||
var value = parseInt(target.value, 10);
|
||||
if (dimension === 'v' || dimension === 's') {
|
||||
value = value/100;
|
||||
}
|
||||
|
||||
var color;
|
||||
if (model === 'rgb') {
|
||||
color = this.tinyColor.toRgb();
|
||||
} else if (model === 'hsv') {
|
||||
color = this.hsvColor;
|
||||
}
|
||||
|
||||
if (isNaN(value)) {
|
||||
value = color[dimension];
|
||||
} else {
|
||||
color[dimension] = value;
|
||||
}
|
||||
|
||||
this.setColor(color);
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.setColor = function (inputColor) {
|
||||
if (!this.unplugged) {
|
||||
this.unplugged = true;
|
||||
|
||||
this.hsvColor = this.toHsvColor_(inputColor);
|
||||
this.tinyColor = this.toTinyColor_(inputColor);
|
||||
|
||||
this.updateInputs();
|
||||
$(".color-picker-spectrum").spectrum("set", this.tinyColor);
|
||||
|
||||
this.colorUpdatedCallback(this.tinyColor);
|
||||
|
||||
this.unplugged = false;
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.toTinyColor_ = function (color) {
|
||||
if (typeof color == "object" && color.hasOwnProperty("_tc_id")) {
|
||||
return color;
|
||||
} else {
|
||||
return window.tinycolor(JSON.parse(JSON.stringify(color)));
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.toHsvColor_ = function (color) {
|
||||
var isHsvColor = ['h','s','v'].every(color.hasOwnProperty.bind(color));
|
||||
if (isHsvColor) {
|
||||
return {
|
||||
h : Math.max(0, Math.min(255, color.h)),
|
||||
s : Math.max(0, Math.min(1, color.s)),
|
||||
v : Math.max(0, Math.min(1, color.v))
|
||||
};
|
||||
} else {
|
||||
return this.toTinyColor_(color).toHsv();
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.updateInputs = function () {
|
||||
var inputs = this.container.querySelectorAll('input');
|
||||
var rgb = this.tinyColor.toRgb();
|
||||
|
||||
|
||||
for (var i = 0 ; i < inputs.length ; i++) {
|
||||
var input = inputs[i];
|
||||
var dimension = input.dataset.dimension;
|
||||
var model = input.dataset.model;
|
||||
|
||||
if (model === 'rgb') {
|
||||
input.value = rgb[dimension];
|
||||
} else if (model === 'hsv') {
|
||||
var value = this.hsvColor[dimension];
|
||||
if (dimension === 'v' || dimension === 's') {
|
||||
value = 100 * value;
|
||||
}
|
||||
input.value = Math.round(value);
|
||||
}
|
||||
|
||||
if (input.getAttribute('type') === 'range') {
|
||||
this.updateSliderBackground(input);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ns.HslRgbColorPicker.prototype.updateSliderBackground = function (slider) {
|
||||
var dimension = slider.dataset.dimension;
|
||||
var model = slider.dataset.model;
|
||||
|
||||
var start, end;
|
||||
var isHueSlider = dimension === 'h';
|
||||
if (!isHueSlider) {
|
||||
if (model === 'hsv') {
|
||||
start = JSON.parse(JSON.stringify(this.hsvColor));
|
||||
start[dimension] = 0;
|
||||
|
||||
end = JSON.parse(JSON.stringify(this.hsvColor));
|
||||
end[dimension] = 1;
|
||||
} else {
|
||||
start = this.tinyColor.toRgb();
|
||||
start[dimension] = 0;
|
||||
|
||||
end = this.tinyColor.toRgb();
|
||||
end[dimension] = 255;
|
||||
}
|
||||
var colorStart = window.tinycolor(start).toRgbString();
|
||||
var colorEnd = window.tinycolor(end).toRgbString();
|
||||
slider.style.backgroundImage = "linear-gradient(to right, " + colorStart + " 0, " + colorEnd + " 100%)";
|
||||
}
|
||||
};
|
||||
})();
|
@ -109,6 +109,9 @@
|
||||
// Dialogs controller
|
||||
"js/controller/dialogs/DialogsController.js",
|
||||
|
||||
// Widget controller
|
||||
"js/controller/widgets/HslRgbColorPicker.js",
|
||||
|
||||
// Services
|
||||
"js/service/LocalStorageService.js",
|
||||
"js/service/GithubStorageService.js",
|
||||
|
28
src/templates/dialogs/create-palette-method.html
Normal file
28
src/templates/dialogs/create-palette-method.html
Normal file
@ -0,0 +1,28 @@
|
||||
<div class="dialog-wrapper">
|
||||
<h3 class="dialog-head">
|
||||
Create palette
|
||||
<span class="palette-manager-close dialog-close">X</span>
|
||||
</h3>
|
||||
<div style="padding:10px 20px; font-size:1.3em">
|
||||
Select your creation method :
|
||||
<ul style="margin:10px 0" class="create-palette-method-list">
|
||||
<li class="create-palette-method-item">
|
||||
<input type="radio" name="palette-creation-mode" id="palette-creation-mode-manual" value="manual" checked="checked">
|
||||
<label for="palette-creation-mode-manual">Manual</label>
|
||||
</li>
|
||||
<li class="create-palette-method-item">
|
||||
<input type="radio" name="palette-creation-mode" id="palette-creation-mode-import" value="import">
|
||||
<label for="palette-creation-mode-import">Import from existing file or image</label><br>
|
||||
</li>
|
||||
<li class="create-palette-method-item">
|
||||
<input type="radio" name="palette-creation-mode" id="palette-creation-mode-palette" value="palette">
|
||||
<label for="palette-creation-mode-palette">Clone existing palette</label>
|
||||
<select class="palettes-list-select" style="margin:3px 0;">
|
||||
<option value="current-colors">Current colors</option>
|
||||
</select>
|
||||
</li>
|
||||
</ul>
|
||||
<button class="button button-primary create-palette-method-continue" style="float:right">Continue</button>
|
||||
<button class="button create-palette-method-cancel" style="float:right">Cancel</button>
|
||||
</div>
|
||||
</div>
|
@ -9,6 +9,7 @@
|
||||
<span class="dialog-create-palette-name">Name :</span><input type="text" class="textfield" name="palette-name" placeholder="New palette"/>
|
||||
</div>
|
||||
<div class="colors-container">
|
||||
<div class="colors-list"></div>
|
||||
<div class="color-picker-container">
|
||||
<div class="color-picker-spectrum"></div>
|
||||
<div class="color-picker-slider">
|
||||
|
Loading…
Reference in New Issue
Block a user