MAAAJOOOOR
This commit is contained in:
parent
e7d1c2399f
commit
cfe3bb7e99
90
css/color-picker.css
Normal file
90
css/color-picker.css
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/* Purty Picker Copyright 2013 Jayden Seric (MIT license): https://github.com/jaydenseric/Purty-Picker */
|
||||||
|
/* Core: No touchy! */
|
||||||
|
.color-picker .spectrum {
|
||||||
|
position: relative;
|
||||||
|
/* To position pin, luminosity filter */
|
||||||
|
background: linear-gradient(gray, transparent), linear-gradient(90deg, red, #ff2b00, #ff5500, #ff8000, #ffaa00, #ffd500, yellow, #d4ff00, #aaff00, #80ff00, #55ff00, #2bff00, lime, #00ff2b, #00ff55, #00ff80, #00ffaa, #00ffd5, cyan, #00d4ff, #00aaff, #007fff, #0055ff, #002bff, blue, #2a00ff, #5500ff, #7f00ff, #aa00ff, #d400ff, magenta, #ff00d4, #ff00aa, #ff0080, #ff0055, #ff002b, red);
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
/* Prevent pin interaction causing content selection */
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
.color-picker .spectrum.active {
|
||||||
|
cursor: none;
|
||||||
|
}
|
||||||
|
.color-picker .spectrum.active .pin {
|
||||||
|
cursor: none;
|
||||||
|
}
|
||||||
|
.color-picker .spectrum > div {
|
||||||
|
/* Luminosity filter */
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.color-picker .spectrum .pin {
|
||||||
|
position: absolute;
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Customization: Default skin */
|
||||||
|
.color-picker {
|
||||||
|
margin: 20px;
|
||||||
|
padding: 11px;
|
||||||
|
border: 1px solid #e3e3e3;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.color-picker .color,
|
||||||
|
.color-picker .luminosity {
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.color-picker .format {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto 10px auto;
|
||||||
|
}
|
||||||
|
.color-picker .color {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 11px;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
font-family: Consolas, Monaco, 'Andale Mono', monospace;
|
||||||
|
color: rgba(0, 0, 0, 0.6);
|
||||||
|
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
.color-picker .color.dark {
|
||||||
|
color: rgba(255, 255, 255, 0.7);
|
||||||
|
}
|
||||||
|
.color-picker .spectrum {
|
||||||
|
height: 150px;
|
||||||
|
/* Arbitary but required */
|
||||||
|
overflow: hidden;
|
||||||
|
/* Prevent pin overflowing container */
|
||||||
|
border-radius: 2px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.color-picker .spectrum > div {
|
||||||
|
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
.color-picker .spectrum .pin {
|
||||||
|
margin-left: -4px;
|
||||||
|
margin-top: -4px;
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
border: 2px solid white;
|
||||||
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
|
||||||
|
border-radius: 100%;
|
||||||
|
}
|
||||||
|
.color-picker .luminosity {
|
||||||
|
margin: 0;
|
||||||
|
}
|
BIN
css/imgs/clear.png
Normal file
BIN
css/imgs/clear.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
css/imgs/redo.png
Normal file
BIN
css/imgs/redo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
css/imgs/undo.png
Normal file
BIN
css/imgs/undo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -65,7 +65,25 @@ button {
|
|||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.picker {
|
||||||
|
width: 30rem;
|
||||||
|
height: 30rem;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -15rem;
|
||||||
|
margin-left: -15rem;
|
||||||
|
|
||||||
|
#closePicker {
|
||||||
|
width: 2rem;
|
||||||
|
height: 2rem;
|
||||||
|
border: 1px solid rgb(227, 227, 227);
|
||||||
|
border-radius: 50%;
|
||||||
|
position: absolute;
|
||||||
|
top: 1rem;
|
||||||
|
left: 27rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
header {
|
header {
|
||||||
@ -117,12 +135,14 @@ header {
|
|||||||
color: white;
|
color: white;
|
||||||
font-family: 'MozTT-Light';
|
font-family: 'MozTT-Light';
|
||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
|
transition: left 0.2s ease-out;
|
||||||
|
|
||||||
&.pulled {
|
&.pulled {
|
||||||
left: 0;
|
left: 0;
|
||||||
|
transition: left 0.2s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
button[id^='set'], p {
|
button[id^='set'], p, .bottom button {
|
||||||
background: none;
|
background: none;
|
||||||
display: block;
|
display: block;
|
||||||
width: 75%;
|
width: 75%;
|
||||||
@ -132,6 +152,7 @@ header {
|
|||||||
font-family: 'MozTT-Light';
|
font-family: 'MozTT-Light';
|
||||||
font-size: 8pt;
|
font-size: 8pt;
|
||||||
padding: 0 0.6rem;
|
padding: 0 0.6rem;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
span {
|
span {
|
||||||
float: right;
|
float: right;
|
||||||
@ -150,13 +171,22 @@ header {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.icon-settings {
|
hr {
|
||||||
|
clear: both;
|
||||||
|
padding: 0.7rem 0;
|
||||||
|
margin-bottom: 0.7rem;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid rgba(255,255,255,0.3);
|
||||||
|
}
|
||||||
|
*[class^='icon'] {
|
||||||
display: block;
|
display: block;
|
||||||
margin: 1rem 0.5rem;
|
margin: 1rem 0.5rem;
|
||||||
|
|
||||||
|
&:nth-of-type(2) {
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
}
|
||||||
&:before {
|
&:before {
|
||||||
content: '';
|
content: '';
|
||||||
background: url('imgs/settings.png') center center no-repeat;
|
|
||||||
background-size: 2rem;
|
background-size: 2rem;
|
||||||
width: 2rem;
|
width: 2rem;
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
@ -166,10 +196,30 @@ header {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-settings:before {
|
||||||
|
background-image: url('imgs/settings.png');
|
||||||
|
}
|
||||||
|
.icon-clear:before {
|
||||||
|
background-image: url('imgs/clear.png');
|
||||||
|
}
|
||||||
|
.icon-undo:before {
|
||||||
|
background-image: url('imgs/undo.png');
|
||||||
|
}
|
||||||
|
.icon-redo:before {
|
||||||
|
background-image: url('imgs/redo.png');
|
||||||
|
}
|
||||||
|
|
||||||
.options {
|
.options {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
.bottom {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5rem;
|
||||||
|
button {
|
||||||
|
margin-left: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ form[role="dialog"][data-type="value-selector"] [role="listbox"] li:active label
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Checked status */
|
/* Checked status */
|
||||||
form[role="dialog"][data-type="value-selector"] [role="listbox"] li[aria-selected="true"] span {
|
form[role="dialog"][data-type="value-selector"] [role="listbox"] li[aria-selected="true"]:not([data-input]) span {
|
||||||
padding-right: 2.6rem;
|
padding-right: 2.6rem;
|
||||||
margin-right: 1.2rem;
|
margin-right: 1.2rem;
|
||||||
color: #00abcd;
|
color: #00abcd;
|
||||||
|
105
index.html
105
index.html
@ -8,6 +8,7 @@
|
|||||||
<link rel='stylesheet' href='css/switches.css'>
|
<link rel='stylesheet' href='css/switches.css'>
|
||||||
<link rel='stylesheet' href='css/value_selector.css'>
|
<link rel='stylesheet' href='css/value_selector.css'>
|
||||||
<link rel='stylesheet' href='css/seekbars.css'>
|
<link rel='stylesheet' href='css/seekbars.css'>
|
||||||
|
<link rel='stylesheet' href='css/color-picker.css'>
|
||||||
<script src='js/less-1.5.0.min.js'></script>
|
<script src='js/less-1.5.0.min.js'></script>
|
||||||
<script src='js/libs/mobilebrowsers.js'></script>
|
<script src='js/libs/mobilebrowsers.js'></script>
|
||||||
</head>
|
</head>
|
||||||
@ -36,24 +37,59 @@
|
|||||||
<button id='setlineJoin'>Line Join<span>Round</span></button>
|
<button id='setlineJoin'>Line Join<span>Round</span></button>
|
||||||
<button id='setlineCap'>Line Cap<span>Round</span></button>
|
<button id='setlineCap'>Line Cap<span>Round</span></button>
|
||||||
<p id='lineWidth'>Line Width <span>2</span></p>
|
<p id='lineWidth'>Line Width <span>2</span></p>
|
||||||
<div role="slider" aria-valuemin="0" aria-valuenow="80" aria-valuemax="100" aria-valuetext="slider description">
|
<div role="slider" class='lineWidth'>
|
||||||
<div>
|
<div>
|
||||||
<progress value="2" max="100"></progress>
|
<progress value="2" min="1" max="100"></progress>
|
||||||
<button>handler</button>
|
<button style='left: 2%'>handler</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<br />
|
||||||
|
<hr>
|
||||||
|
<div class='sketch'>
|
||||||
|
<p class='icon-settings'>Sketch</p>
|
||||||
|
<p id='connectTelorance'>Connet Telorance<span>40</span></p>
|
||||||
|
<div role="slider" class='connectTelorance'>
|
||||||
|
<div>
|
||||||
|
<progress value="40" min="1" max="100"></progress>
|
||||||
|
<button style='left: 40%'>handler</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='fur hidden'>
|
||||||
|
<p class='icon-settings'>Fur</p>
|
||||||
|
<p id='connectTelorance'>Connet Telorance<span>40</span></p>
|
||||||
|
<div role="slider" class='connectTelorance'>
|
||||||
|
<div>
|
||||||
|
<progress value="40" min="10" max="100"></progress>
|
||||||
|
<button style='left: 40%'>handler</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p id='furLength'>Fur Length<span>20</span></p>
|
||||||
|
<div role="slider" class='furLength'>
|
||||||
|
<div>
|
||||||
|
<progress value="20" min="1" max="100"></progress>
|
||||||
|
<button style='left: 20%'>handler</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='bottom'>
|
||||||
|
<button id='clear' class='icon-clear'>Clear</button>
|
||||||
|
<button id='undo' class='icon-undo'>Undo</button>
|
||||||
|
<button id='redo' class='icon-redo'>Redo</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form role='dialog' data-type='value-selector' id='type' class='hidden'>
|
<form role='dialog' data-type='value-selector' id='type' class='hidden single'>
|
||||||
<section class='scrollable'>
|
<section class='scrollable'>
|
||||||
<h1>Brush Type</h1>
|
<h1>Brush Type</h1>
|
||||||
<ol role='listbox'>
|
<ol role='listbox'>
|
||||||
<li role='option' aria-selected='true'><label role='presentation'><span>Sketch</span></label></li>
|
<li aria-selected='true'><label><span>Sketch</span></label></li>
|
||||||
<li role='option'><label role='presentation'><span>Fur</span></label></li>
|
<li><label><span>Fur</span></label></li>
|
||||||
<li role='option'><label role='presentation'><span>Pen</span></label></li>
|
<li><label><span>Pen</span></label></li>
|
||||||
<li role='option'><label role='presentation'><span>Line</span></label></li>
|
<li><label><span>Line</span></label></li>
|
||||||
</ol>
|
</ol>
|
||||||
</section>
|
</section>
|
||||||
<menu>
|
<menu>
|
||||||
@ -61,13 +97,13 @@
|
|||||||
</menu>
|
</menu>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form role='dialog' data-type='value-selector' id='lineJoin' class='hidden'>
|
<form role='dialog' data-type='value-selector' id='lineJoin' class='hidden single'>
|
||||||
<section class='scrollable'>
|
<section class='scrollable'>
|
||||||
<h1>Line Join</h1>
|
<h1>Line Join</h1>
|
||||||
<ol role='listbox'>
|
<ol role='listbox'>
|
||||||
<li role='option' aria-selected='true'><label role='presentation'><span>Round</span></label></li>
|
<li aria-selected='true'><label><span>Round</span></label></li>
|
||||||
<li role='option'><label role='presentation'><span>Bevel</span></label></li>
|
<li><label><span>Bevel</span></label></li>
|
||||||
<li role='option'><label role='presentation'><span>Miter</span></label></li>
|
<li><label><span>Miter</span></label></li>
|
||||||
</ol>
|
</ol>
|
||||||
</section>
|
</section>
|
||||||
<menu>
|
<menu>
|
||||||
@ -75,13 +111,13 @@
|
|||||||
</menu>
|
</menu>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<form role='dialog' data-type='value-selector' id='lineCap' class='hidden'>
|
<form role='dialog' data-type='value-selector' id='lineCap' class='hidden single'>
|
||||||
<section class='scrollable'>
|
<section class='scrollable'>
|
||||||
<h1>Line Cap</h1>
|
<h1>Line Cap</h1>
|
||||||
<ol role='listbox'>
|
<ol role='listbox'>
|
||||||
<li role='option' aria-selected='true'><label role='presentation'><span>Round</span></label></li>
|
<li aria-selected='true'><label><span>Round</span></label></li>
|
||||||
<li role='option'><label role='presentation'><span>Square</span></label></li>
|
<li><label><span>Square</span></label></li>
|
||||||
<li role='option'><label role='presentation'><span>Butt</span></label></li>
|
<li><label><span>Butt</span></label></li>
|
||||||
</ol>
|
</ol>
|
||||||
</section>
|
</section>
|
||||||
<menu>
|
<menu>
|
||||||
@ -89,8 +125,45 @@
|
|||||||
</menu>
|
</menu>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<form role='dialog' data-type='value-selector' id='save' class='hidden confirm'>
|
||||||
|
<section class='scrollable'>
|
||||||
|
<h1>Save</h1>
|
||||||
|
<h1>Background</h1>
|
||||||
|
<ol role='listbox'>
|
||||||
|
<li aria-selected='true'><label><span>White</span></label></li>
|
||||||
|
<li><label><span>Current Color</span></label></li>
|
||||||
|
<li><label><span>Transparent</span></label></li>
|
||||||
|
</ol>
|
||||||
|
<h1>File Name</h1>
|
||||||
|
<ol role='listbox'>
|
||||||
|
<li aria-selected='true' data-input><label><span contenteditable>My Sketch</span></label></li>
|
||||||
|
</ol>
|
||||||
|
</section>
|
||||||
|
<menu>
|
||||||
|
<button class='affirmative' type='button'>Cancel</button>
|
||||||
|
<button class='affirmative' type='button'>Save</button>
|
||||||
|
</menu>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- COLOR PICKER -->
|
||||||
|
<div class='picker overlay hidden'>
|
||||||
|
<div class='color-picker'>
|
||||||
|
<button id='closePicker'>×</button>
|
||||||
|
<input value='Hex' class='format' type='hidden' selected>
|
||||||
|
<input class='color' val='#000000'>
|
||||||
|
<div class="spectrum">
|
||||||
|
<div>
|
||||||
|
<div class="pin"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input class="luminosity" type="range" min="0" max="100" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src='js/libs/yepnope.min.js'></script>
|
<script src='js/libs/yepnope.min.js'></script>
|
||||||
<script src='js/libs/zepto.min.js'></script>
|
<script src='js/libs/zepto.min.js'></script>
|
||||||
|
<script src='js/libs/touch.js'></script>
|
||||||
<script src='js/functions.js'></script>
|
<script src='js/functions.js'></script>
|
||||||
<script src='js/main.js'></script>
|
<script src='js/main.js'></script>
|
||||||
|
|
||||||
|
145
js/events.js
145
js/events.js
@ -1,22 +1,56 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
switch(save.background) {
|
||||||
|
case 'white': {
|
||||||
|
var cache = {
|
||||||
|
color: c.color,
|
||||||
|
composite: c.globalCompositeOperation
|
||||||
|
}
|
||||||
|
c.fillStyle = 'white';
|
||||||
|
c.globalCompositeOperation = 'destination-over';
|
||||||
|
c.fillRect(0, 0, $c.width(), $c.height());
|
||||||
|
c.fillStyle = cache.fillStyle;
|
||||||
|
c.globalCompositeOperation = cache.composite;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'current color': {
|
||||||
|
var cache = {
|
||||||
|
fillStyle: c.color,
|
||||||
|
composite: c.globalCompositeOperation
|
||||||
|
}
|
||||||
|
c.fillStyle = settings.strokeStyle;
|
||||||
|
c.globalCompositeOperation = 'destination-over';
|
||||||
|
c.fillRect(0, 0, $c.width(), $c.height());
|
||||||
|
c.fillStyle = cache.fillStyle;
|
||||||
|
c.globalCompositeOperation = cache.composite;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var data = $c[0].toDataURL();
|
||||||
|
window.open(data, save['file name']);
|
||||||
|
|
||||||
|
c.putImageData(window.points.history[window.points.history.length-1].data, 0, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
$('.menu').click(function() {
|
$('.menu').click(function() {
|
||||||
$('#menu').toggleClass('pulled');
|
$('#menu').toggleClass('pulled');
|
||||||
})
|
})
|
||||||
$('.save').click(function() {
|
$('.save').click(function() {
|
||||||
var data = $c[0].toDataURL();
|
$('#save').removeClass('hidden');
|
||||||
var img = $('<img src="' + data + '" width="' + $c.width() + '" height="' + $c.height() + '" class="overlay"/>');
|
|
||||||
$('body').append(img);
|
|
||||||
})
|
})
|
||||||
$c.last().bind('mousedown', function(e) {
|
$c.last().on('mousedown', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var xy = relative(e.pageX, e.pageY);
|
var xy = relative(e.pageX, e.pageY);
|
||||||
startPoint(xy.x, xy.y);
|
startPoint(xy.x, xy.y);
|
||||||
window.active = true;
|
window.active = true;
|
||||||
}).bind('mousemove', function(e) {
|
}).on('mousemove', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!window.active || settings.type == 'line') return;
|
if (!window.active || settings.type == 'line') return;
|
||||||
var xy = relative(e.pageX, e.pageY);
|
var xy = relative(e.pageX, e.pageY);
|
||||||
drawPoint(xy.x, xy.y);
|
drawPoint(xy.x, xy.y);
|
||||||
}).bind('mouseup mouseout', function(e) {
|
}).on('mouseup', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
window.active = false;
|
window.active = false;
|
||||||
|
|
||||||
@ -33,32 +67,68 @@
|
|||||||
|
|
||||||
// Value Selector
|
// Value Selector
|
||||||
|
|
||||||
var $selector = $('form[data-type="value-selector"]');
|
// Single
|
||||||
|
|
||||||
|
var $single = $('form[data-type="value-selector"].single');
|
||||||
|
|
||||||
$selector.find('li').on('mouseup', function(e) {
|
$single.find('li').click(function(e) {
|
||||||
alert(e.type);
|
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
|
||||||
$(this).parent().find('li').removeAttr('aria-selected');
|
|
||||||
$(this).attr('aria-selected', 'true');
|
$(this).attr('aria-selected', 'true');
|
||||||
var prop = $(this).parents('form').attr('id'),
|
var key = $(this).parents('form').attr('id'),
|
||||||
key = $(this).find('label span').html().toLowerCase();
|
value = $(this).find('label span').html().toLowerCase();
|
||||||
window.settings[prop] = key;
|
window.settings[key] = value;
|
||||||
|
|
||||||
$('button[id="set' + prop + '"] span').html(key[0].toUpperCase() + key.substr(1));
|
$('button[id="set' + key + '"] span').html(value[0].toUpperCase() + value.substr(1));
|
||||||
|
$('#menu div.options > div').addClass('hidden');
|
||||||
|
$('#menu div.options > .general, #menu div.options > .'+value).removeClass('hidden');
|
||||||
|
|
||||||
$(this).parents('form').addClass('hidden');
|
$(this).parents('form').addClass('hidden');
|
||||||
})
|
})
|
||||||
|
$single.submit(function(e) {
|
||||||
$selector.submit(function(e) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$(this).addClass('hidden');
|
$(this).addClass('hidden');
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Confirm
|
||||||
|
|
||||||
|
var $confirm = $('form[data-type="value-selector"].confirm');
|
||||||
|
|
||||||
|
$confirm.find('li').click(function(e) {
|
||||||
|
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
|
||||||
|
$(this).attr('aria-selected', 'true');
|
||||||
|
})
|
||||||
|
$confirm.find('button').last().click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var v = $(this).parents('form').attr('id');
|
||||||
|
$(this).parents('form').find('h1').each(function(i) {
|
||||||
|
if( i > 0 ) {
|
||||||
|
var key = $(this).html().toLowerCase();
|
||||||
|
var value = $(this).parent().find('ol:nth-of-type('+i+') li[aria-selected] span').html();
|
||||||
|
if( key !== 'file name' ) value = key.toLowerCase();
|
||||||
|
|
||||||
|
window[v][key] = value;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$(this).parents('form').addClass('hidden');
|
||||||
|
window[v]();
|
||||||
|
})
|
||||||
|
$confirm.find('button').first().click(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$(this).parents('form').addClass('hidden');
|
||||||
|
})
|
||||||
|
|
||||||
// Value Selector Callers
|
// Value Selector Callers
|
||||||
|
|
||||||
var $btn = $('button[id^="set"]');
|
var $btn = $('button[id^="set"]');
|
||||||
$btn.each(function() {
|
$btn.each(function() {
|
||||||
var target = /set(.*)/.exec($(this).attr('id'))[1];
|
var target = /set(.*)/.exec($(this).attr('id'))[1];
|
||||||
$(this).on('mouseup', function(e) {
|
// Exception for Color
|
||||||
|
if( target == 'color' ) {
|
||||||
|
return $(this).click(function() {
|
||||||
|
$('.picker').removeClass('hidden');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
$(this).click(function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$('form[id="' + target + '"]').removeClass('hidden');
|
$('form[id="' + target + '"]').removeClass('hidden');
|
||||||
})
|
})
|
||||||
@ -66,19 +136,50 @@
|
|||||||
|
|
||||||
// Seekbar
|
// Seekbar
|
||||||
|
|
||||||
var sliderLeft = $('div[role="slider"] button').offset().left;
|
var sliderLeft;
|
||||||
$('div[role="slider"] button').on('mousedown', function() {
|
$('div[role="slider"] button').on('mousedown', function() {
|
||||||
$(this).attr('data-moving','true');
|
$(this).attr('data-moving','true');
|
||||||
|
if( !sliderLeft ) sliderLeft = $('div[role="slider"] button').offset().left;
|
||||||
}).on('mousemove', function(e) {
|
}).on('mousemove', function(e) {
|
||||||
if( $(this).attr('data-moving') ) {
|
if( $(this).attr('data-moving') ) {
|
||||||
var x = e.pageX - sliderLeft - 15;
|
var x = parseInt(e.pageX - sliderLeft - 15);
|
||||||
if( x <= 100 && x > 0 ) {
|
var progress = $(this).parent().children().first();
|
||||||
|
var max = +progress.attr('max');
|
||||||
|
var min = +progress.attr('min');
|
||||||
|
if( x <= max && x >= min ) {
|
||||||
$(this).css('left', x+'%');
|
$(this).css('left', x+'%');
|
||||||
$(this).parent().find('progress').attr('value', x);
|
$(this).parent().find('progress').attr('value', x);
|
||||||
settings.lineWidth = x / 10;
|
var key = $(this).parents('div[role="slider"]').attr('class');
|
||||||
$('#lineWidth span').html(x);
|
settings[key] = x;
|
||||||
|
$('#'+ key +' span').html(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).on('mouseup mouseleave', function() {
|
}).on('mouseup mouseleave', function() {
|
||||||
$(this).removeAttr('data-moving');
|
$(this).removeAttr('data-moving');
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// Color Picker
|
||||||
|
|
||||||
|
$('#closePicker').click(function() {
|
||||||
|
$('.picker').addClass('hidden');
|
||||||
|
})
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
|
||||||
|
$('#clear').click(function() {
|
||||||
|
c.clearRect(0, 0, $c.width(), $c.height());
|
||||||
|
if(window.points.history.last < window.points.history.length-1) {
|
||||||
|
window.points.history.splice(window.points.history.last+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.points.history.push({
|
||||||
|
data: c.getImageData(0, 0, $c.width(), $c.height()),
|
||||||
|
points: []
|
||||||
|
})
|
||||||
|
window.points.history.last = window.points.history.length-1;
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#undo').click(undo);
|
||||||
|
$('#redo').click(redo);
|
||||||
|
|
||||||
|
@ -6,16 +6,20 @@ function sizeAndPos() {
|
|||||||
var data = c.getImageData(0,0, $c.width(), $c.height());
|
var data = c.getImageData(0,0, $c.width(), $c.height());
|
||||||
var w = $(window).width(),
|
var w = $(window).width(),
|
||||||
h = $(window).height();
|
h = $(window).height();
|
||||||
$c.attr('width', w);
|
$c.attr('width', w * window.devicePixelRatio);
|
||||||
$c.attr('height',h - 53);
|
$c.attr('height',h * window.devicePixelRatio - 53 * window.devicePixelRatio);
|
||||||
|
$c.css({
|
||||||
|
'width' : w,
|
||||||
|
'height' : h - 53
|
||||||
|
});
|
||||||
c.clearRect(0,0, $c.width(), $c.height());
|
c.clearRect(0,0, $c.width(), $c.height());
|
||||||
c.putImageData(data, 0, 0);
|
c.putImageData(data, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function relative(x,y) {
|
function relative(x,y) {
|
||||||
return {
|
return {
|
||||||
x : x - $c.offset().left,
|
x : x*window.devicePixelRatio,
|
||||||
y : y - $c.offset().top
|
y : y*window.devicePixelRatio - 53 * window.devicePixelRatio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,11 +36,13 @@ function line(x1, y1, x2, y2, opts, overlay) {
|
|||||||
c.beginPath();
|
c.beginPath();
|
||||||
c.lineCap = opts.lineCap || settings.lineCap;
|
c.lineCap = opts.lineCap || settings.lineCap;
|
||||||
c.lineJoin = opts.lineJoin || settings.lineJoin;
|
c.lineJoin = opts.lineJoin || settings.lineJoin;
|
||||||
c.strokeStyle = opts.strokeStyle || settings.strokeStyle;
|
c.strokeStyle = opts.color || settings.color;
|
||||||
c.lineWidth = opts.lineWidth || settings.lineWidth;
|
c.fillStyle = opts.color || settings.color;
|
||||||
|
c.lineWidth = ( opts.lineWidth || settings.lineWidth ) / 10;
|
||||||
c.moveTo(x1, y1);
|
c.moveTo(x1, y1);
|
||||||
c.lineTo(x2, y2);
|
c.lineTo(x2, y2);
|
||||||
c.stroke();
|
if( !opts.noStroke ) c.stroke();
|
||||||
|
if( opts.fill ) c.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
function erase(x1, y1, x2, y2, overlay) {
|
function erase(x1, y1, x2, y2, overlay) {
|
||||||
@ -73,6 +79,13 @@ function redo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dataToBlob(data) {
|
||||||
|
var binary = atob(data.split(',')[1]), array = [];
|
||||||
|
var type = data.split(',')[0].split(':')[1].split(';')[0];
|
||||||
|
for(var i = 0; i < binary.length; i++) array.push(binary.charCodeAt(i));
|
||||||
|
return new Blob([new Uint8Array(array)], {type: type});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*** END ***/
|
/*** END ***/
|
||||||
|
|
||||||
@ -90,7 +103,10 @@ function startPoint(x, y) {
|
|||||||
type : settings.type
|
type : settings.type
|
||||||
}
|
}
|
||||||
if( old.type !== 'line' && current.type == 'line' ) {
|
if( old.type !== 'line' && current.type == 'line' ) {
|
||||||
line(x,y,x,y, {lineWidth: 5, strokeStyle: 'red'}, true);
|
window.o.beginPath();
|
||||||
|
window.o.fillStyle = 'red';
|
||||||
|
window.o.arc(x,y, 3, 0, 2*Math.PI);
|
||||||
|
window.o.fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( old.type == 'line' ) {
|
if( old.type == 'line' ) {
|
||||||
@ -135,11 +151,11 @@ function drawPoint(x,y) {
|
|||||||
points.push(current);
|
points.push(current);
|
||||||
|
|
||||||
for( var i = 0, len = points.length-1; i < len; i++ ) {
|
for( var i = 0, len = points.length-1; i < len; i++ ) {
|
||||||
if(threshold(points[i].x, points[i].y, current.x, current.y, 40)) {
|
if(threshold(points[i].x, points[i].y, current.x, current.y, settings.connectTelorance)) {
|
||||||
var x = points[i].x - current.x,
|
var x = points[i].x - current.x,
|
||||||
y = points[i].y - current.y;
|
y = points[i].y - current.y;
|
||||||
|
|
||||||
line(points[i].x - x*0.2, points[i].y - y*0.2, current.x + x*0.2, current.y + y*0.2, {strokeStyle: 'rgba(0,0,0,0.4)', lineWidth: settings.lineWidth/2})
|
line(points[i].x - x*0.2, points[i].y - y*0.2, current.x + x*0.2, current.y + y*0.2, {strokeStyle: 'rgba(0,0,0,0.4)', lineWidth: settings.lineWidth/20})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -155,10 +171,10 @@ function drawPoint(x,y) {
|
|||||||
points.push(current);
|
points.push(current);
|
||||||
|
|
||||||
for( var i = 0, len = points.length-1; i < len; i++ ) {
|
for( var i = 0, len = points.length-1; i < len; i++ ) {
|
||||||
if(threshold(points[i].x, points[i].y, current.x, current.y, settings.lineWidth*20)) {
|
if(threshold(points[i].x, points[i].y, current.x, current.y, settings.connectTelorance)) {
|
||||||
var x = points[i].x - current.x,
|
var x = points[i].x - current.x,
|
||||||
y = points[i].y - current.y;
|
y = points[i].y - current.y;
|
||||||
var l = settings.furLength || 0.2;
|
var l = settings.furLength / 100 || 0.2;
|
||||||
line(points[i].x + x*l, points[i].y + y*l, current.x - x*l, current.y - y*l, {strokeStyle: 'rgba(0,0,0,0.4)', lineWidth: settings.lineWidth/2})
|
line(points[i].x + x*l, points[i].y + y*l, current.x - x*l, current.y - y*l, {strokeStyle: 'rgba(0,0,0,0.4)', lineWidth: settings.lineWidth/2})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
290
js/libs/color-picker-touch.js
Normal file
290
js/libs/color-picker-touch.js
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Purty Picker Copyright 2013 Jayden Seric (MIT license).
|
||||||
|
|
||||||
|
A super lightweight visual HSL, RGB and hex color picker with a responsive, touch-friendly and customizable UI.
|
||||||
|
|
||||||
|
Requires jQuery or Zepto with core and event modules.
|
||||||
|
|
||||||
|
https://github.com/jaydenseric/Purty-Picker
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// DOM ready
|
||||||
|
$(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
//-------------------------------------------- Color conversions
|
||||||
|
|
||||||
|
//---------------------- Convert HSL to RGB
|
||||||
|
|
||||||
|
// Source: http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
|
||||||
|
|
||||||
|
function HSLToRGB(h, s, l) {
|
||||||
|
h /= 360;
|
||||||
|
s /= 100;
|
||||||
|
l /= 100;
|
||||||
|
var r, g, b;
|
||||||
|
if(s == 0) {
|
||||||
|
r = g = b = l; // Achromatic
|
||||||
|
} else {
|
||||||
|
var hueToRGB = function(p, q, t) {
|
||||||
|
if(t < 0) t += 1;
|
||||||
|
if(t > 1) t -= 1;
|
||||||
|
if(t < 1/6) return p + (q - p) * 6 * t;
|
||||||
|
if(t < 1/2) return q;
|
||||||
|
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
var q = l < 0.5 ? l * (1 + s) : l + s - l * s,
|
||||||
|
p = 2 * l - q;
|
||||||
|
r = hueToRGB(p, q, h + 1/3);
|
||||||
|
g = hueToRGB(p, q, h);
|
||||||
|
b = hueToRGB(p, q, h - 1/3);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
red: Math.round(r * 255),
|
||||||
|
green: Math.round(g * 255),
|
||||||
|
blue: Math.round(b * 255)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Convert RGB to HSL
|
||||||
|
|
||||||
|
// Source: http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
|
||||||
|
|
||||||
|
function RGBToHSL(r, g, b) {
|
||||||
|
r /= 255,
|
||||||
|
g /= 255,
|
||||||
|
b /= 255;
|
||||||
|
var max = Math.max(r, g, b),
|
||||||
|
min = Math.min(r, g, b);
|
||||||
|
var h, s, l = (max + min) / 2;
|
||||||
|
if (max == min) {
|
||||||
|
h = s = 0; // Achromatic
|
||||||
|
} else {
|
||||||
|
var d = max - min;
|
||||||
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||||
|
switch(max) {
|
||||||
|
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||||
|
case g: h = (b - r) / d + 2; break;
|
||||||
|
case b: h = (r - g) / d + 4; break;
|
||||||
|
}
|
||||||
|
h /= 6;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
hue: Math.round(h * 360),
|
||||||
|
saturation: Math.round(s * 100),
|
||||||
|
luminosity: Math.round(l * 100)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Convert RGB to Hex
|
||||||
|
|
||||||
|
// Source: http://stackoverflow.com/a/5624139
|
||||||
|
|
||||||
|
function RGBToHex(r, g, b) {
|
||||||
|
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Convert hex to RGB
|
||||||
|
|
||||||
|
// Source: http://stackoverflow.com/a/11508164
|
||||||
|
|
||||||
|
function hexToRGB(hex) {
|
||||||
|
var bigInt = parseInt(hex.replace('#', ''), 16),
|
||||||
|
r = (bigInt >> 16) & 255,
|
||||||
|
g = (bigInt >> 8) & 255,
|
||||||
|
b = bigInt & 255;
|
||||||
|
return {
|
||||||
|
red: r,
|
||||||
|
green: g,
|
||||||
|
blue: b
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Convert hex to HSL
|
||||||
|
|
||||||
|
function hexToHSL(hex) {
|
||||||
|
var RGB = hexToRGB(hex);
|
||||||
|
return RGBToHSL(RGB.red, RGB.green, RGB.blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Convert HSL to hex
|
||||||
|
|
||||||
|
function HSLToHex(h, s, l) {
|
||||||
|
var RGB = HSLToRGB(h, s, l);
|
||||||
|
return RGBToHex(RGB.red, RGB.green, RGB.blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------- Setup each color picker
|
||||||
|
|
||||||
|
$.each($('.color-picker'), function() {
|
||||||
|
|
||||||
|
//---------------------- Find componenets
|
||||||
|
|
||||||
|
var picker = $(this),
|
||||||
|
formatInput = picker.find('.format'),
|
||||||
|
colorInput = picker.find('.color'),
|
||||||
|
luminosityInput = picker.find('input[type=range]'),
|
||||||
|
spectrum = picker.find('.spectrum'),
|
||||||
|
pin = picker.find('.pin');
|
||||||
|
|
||||||
|
//---------------------- Get current color in HSL
|
||||||
|
|
||||||
|
function getHSL() {
|
||||||
|
var position = picker.find('.pin').position(),
|
||||||
|
width = spectrum.width(),
|
||||||
|
height = spectrum.height();
|
||||||
|
return {
|
||||||
|
hue: Math.round(position.left / width * 360),
|
||||||
|
saturation: Math.round(position.top / height * 100),
|
||||||
|
luminosity: luminosityInput.val()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Output color in desired format
|
||||||
|
|
||||||
|
function updateColorInput() {
|
||||||
|
var HSL = getHSL();
|
||||||
|
switch (formatInput.val()) {
|
||||||
|
case 'HSL':
|
||||||
|
colorInput.val('hsl(' + HSL.hue + ', ' + HSL.saturation + '%, ' + HSL.luminosity + '%)');
|
||||||
|
break;
|
||||||
|
case 'RGB':
|
||||||
|
var RGB = HSLToRGB(HSL.hue, HSL.saturation, HSL.luminosity);
|
||||||
|
colorInput.val('rgb(' + RGB.red + ', ' + RGB.green + ', ' + RGB.blue + ')');
|
||||||
|
break;
|
||||||
|
case 'Hex':
|
||||||
|
colorInput.val(HSLToHex(HSL.hue, HSL.saturation, HSL.luminosity));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Trigger color picker change event for custom callbacks
|
||||||
|
picker.trigger('change');
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Set color format
|
||||||
|
|
||||||
|
formatInput.on('change', function() {
|
||||||
|
updateColorInput();
|
||||||
|
});
|
||||||
|
|
||||||
|
//---------------------- Set color
|
||||||
|
|
||||||
|
colorInput.on('change', function() {
|
||||||
|
// Get the color values in HSL format
|
||||||
|
var HSL;
|
||||||
|
switch (formatInput.val()) {
|
||||||
|
case 'HSL':
|
||||||
|
var values = $(this).val().match(/\d+/g);
|
||||||
|
HSL = {
|
||||||
|
hue: values[0],
|
||||||
|
saturation: values[1],
|
||||||
|
luminosity: values[2]
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 'RGB':
|
||||||
|
var values = $(this).val().match(/\d+/g);
|
||||||
|
HSL = RGBToHSL(values[0], values[1], values[2]);
|
||||||
|
break;
|
||||||
|
case 'Hex':
|
||||||
|
HSL = hexToHSL($(this).val());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Set the luminosity
|
||||||
|
luminosityInput.val(HSL.luminosity);
|
||||||
|
setLuminosity(HSL.luminosity);
|
||||||
|
// Place the pin
|
||||||
|
pin.css({
|
||||||
|
left: HSL.hue / 360 * 100 + '%',
|
||||||
|
top: HSL.saturation + '%'
|
||||||
|
});
|
||||||
|
// Trigger color picker change event for custom callbacks
|
||||||
|
picker.trigger('change');
|
||||||
|
});
|
||||||
|
|
||||||
|
//---------------------- Set luminosity
|
||||||
|
|
||||||
|
//---------- Set the luminosity spectrum overlay
|
||||||
|
|
||||||
|
function setLuminosity(luminosity) {
|
||||||
|
var color,
|
||||||
|
alpha;
|
||||||
|
if (luminosity <= 50) {
|
||||||
|
color = '0, 0, 0';
|
||||||
|
alpha = 1 - luminosity / 100 * 2;
|
||||||
|
} else {
|
||||||
|
color = '255, 255, 255';
|
||||||
|
alpha = luminosity / 100 * 2 - 1;
|
||||||
|
}
|
||||||
|
// Apply luminosity to the spectrum
|
||||||
|
spectrum.children().css('background-color', 'rgba(' + color + ', ' + alpha + ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------- Luminosity input interaction
|
||||||
|
|
||||||
|
luminosityInput.on('change', function() {
|
||||||
|
setLuminosity($(this).val());
|
||||||
|
updateColorInput();
|
||||||
|
});
|
||||||
|
|
||||||
|
//---------------------- Set hue, saturation via pin
|
||||||
|
|
||||||
|
//---------- Move the pin
|
||||||
|
|
||||||
|
var movePin = function(event) {
|
||||||
|
var offset = spectrum.offset(),
|
||||||
|
width = spectrum.width(),
|
||||||
|
height = spectrum.height(),
|
||||||
|
x = event.changedTouches[0].clientX - offset.left,
|
||||||
|
y = event.changedTouches[0].clientY - offset.top;
|
||||||
|
// Account for pin being dragged outside the spectrum area
|
||||||
|
// Sanatize x
|
||||||
|
if (x < 0) {
|
||||||
|
x = 0;
|
||||||
|
} else if (x >= width) {
|
||||||
|
x = width;
|
||||||
|
}
|
||||||
|
// Sanatize y
|
||||||
|
if (y < 0) {
|
||||||
|
y = 0;
|
||||||
|
} else if (y >= height) {
|
||||||
|
y = height;
|
||||||
|
}
|
||||||
|
// Place the pin
|
||||||
|
pin.css({
|
||||||
|
left: x / width * 100 + '%',
|
||||||
|
top: y / height * 100 + '%'
|
||||||
|
});
|
||||||
|
// Output new color value
|
||||||
|
updateColorInput();
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------- Pin interaction
|
||||||
|
|
||||||
|
spectrum.on('touchstart', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
movePin(event);
|
||||||
|
spectrum.addClass('active');
|
||||||
|
$(document).on('touchmove', movePin);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('touchend', function() {
|
||||||
|
spectrum.removeClass('active');
|
||||||
|
$(document).off('touchmove', movePin);
|
||||||
|
});
|
||||||
|
|
||||||
|
spectrum.on('touchmove touchstart', movePin);
|
||||||
|
|
||||||
|
//---------------------- Output color preview
|
||||||
|
|
||||||
|
picker.on('change', function() {
|
||||||
|
colorInput.css('background-color', colorInput.val()).toggleClass('dark', luminosityInput.val() <= 50);
|
||||||
|
});
|
||||||
|
|
||||||
|
//---------------------- Initialize this color picker
|
||||||
|
|
||||||
|
colorInput.trigger('change');
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
289
js/libs/color-picker.js
Normal file
289
js/libs/color-picker.js
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Purty Picker Copyright 2013 Jayden Seric (MIT license).
|
||||||
|
|
||||||
|
A super lightweight visual HSL, RGB and hex color picker with a responsive, touch-friendly and customizable UI.
|
||||||
|
|
||||||
|
Requires jQuery or Zepto with core and event modules.
|
||||||
|
|
||||||
|
https://github.com/jaydenseric/Purty-Picker
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// DOM ready
|
||||||
|
$(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
//-------------------------------------------- Color conversions
|
||||||
|
|
||||||
|
//---------------------- Convert HSL to RGB
|
||||||
|
|
||||||
|
// Source: http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
|
||||||
|
|
||||||
|
function HSLToRGB(h, s, l) {
|
||||||
|
h /= 360;
|
||||||
|
s /= 100;
|
||||||
|
l /= 100;
|
||||||
|
var r, g, b;
|
||||||
|
if(s == 0) {
|
||||||
|
r = g = b = l; // Achromatic
|
||||||
|
} else {
|
||||||
|
var hueToRGB = function(p, q, t) {
|
||||||
|
if(t < 0) t += 1;
|
||||||
|
if(t > 1) t -= 1;
|
||||||
|
if(t < 1/6) return p + (q - p) * 6 * t;
|
||||||
|
if(t < 1/2) return q;
|
||||||
|
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
var q = l < 0.5 ? l * (1 + s) : l + s - l * s,
|
||||||
|
p = 2 * l - q;
|
||||||
|
r = hueToRGB(p, q, h + 1/3);
|
||||||
|
g = hueToRGB(p, q, h);
|
||||||
|
b = hueToRGB(p, q, h - 1/3);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
red: Math.round(r * 255),
|
||||||
|
green: Math.round(g * 255),
|
||||||
|
blue: Math.round(b * 255)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Convert RGB to HSL
|
||||||
|
|
||||||
|
// Source: http://axonflux.com/handy-rgb-to-hsl-and-rgb-to-hsv-color-model-c
|
||||||
|
|
||||||
|
function RGBToHSL(r, g, b) {
|
||||||
|
r /= 255,
|
||||||
|
g /= 255,
|
||||||
|
b /= 255;
|
||||||
|
var max = Math.max(r, g, b),
|
||||||
|
min = Math.min(r, g, b);
|
||||||
|
var h, s, l = (max + min) / 2;
|
||||||
|
if (max == min) {
|
||||||
|
h = s = 0; // Achromatic
|
||||||
|
} else {
|
||||||
|
var d = max - min;
|
||||||
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||||
|
switch(max) {
|
||||||
|
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||||
|
case g: h = (b - r) / d + 2; break;
|
||||||
|
case b: h = (r - g) / d + 4; break;
|
||||||
|
}
|
||||||
|
h /= 6;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
hue: Math.round(h * 360),
|
||||||
|
saturation: Math.round(s * 100),
|
||||||
|
luminosity: Math.round(l * 100)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Convert RGB to Hex
|
||||||
|
|
||||||
|
// Source: http://stackoverflow.com/a/5624139
|
||||||
|
|
||||||
|
function RGBToHex(r, g, b) {
|
||||||
|
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Convert hex to RGB
|
||||||
|
|
||||||
|
// Source: http://stackoverflow.com/a/11508164
|
||||||
|
|
||||||
|
function hexToRGB(hex) {
|
||||||
|
var bigInt = parseInt(hex.replace('#', ''), 16),
|
||||||
|
r = (bigInt >> 16) & 255,
|
||||||
|
g = (bigInt >> 8) & 255,
|
||||||
|
b = bigInt & 255;
|
||||||
|
return {
|
||||||
|
red: r,
|
||||||
|
green: g,
|
||||||
|
blue: b
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Convert hex to HSL
|
||||||
|
|
||||||
|
function hexToHSL(hex) {
|
||||||
|
var RGB = hexToRGB(hex);
|
||||||
|
return RGBToHSL(RGB.red, RGB.green, RGB.blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Convert HSL to hex
|
||||||
|
|
||||||
|
function HSLToHex(h, s, l) {
|
||||||
|
var RGB = HSLToRGB(h, s, l);
|
||||||
|
return RGBToHex(RGB.red, RGB.green, RGB.blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------- Setup each color picker
|
||||||
|
|
||||||
|
$.each($('.color-picker'), function() {
|
||||||
|
|
||||||
|
//---------------------- Find componenets
|
||||||
|
|
||||||
|
var picker = $(this),
|
||||||
|
formatInput = picker.find('.format'),
|
||||||
|
colorInput = picker.find('.color'),
|
||||||
|
luminosityInput = picker.find('input[type=range]'),
|
||||||
|
spectrum = picker.find('.spectrum'),
|
||||||
|
pin = picker.find('.pin');
|
||||||
|
|
||||||
|
//---------------------- Get current color in HSL
|
||||||
|
|
||||||
|
function getHSL() {
|
||||||
|
var position = picker.find('.pin').position(),
|
||||||
|
width = spectrum.width(),
|
||||||
|
height = spectrum.height();
|
||||||
|
return {
|
||||||
|
hue: Math.round(position.left / width * 360),
|
||||||
|
saturation: Math.round(position.top / height * 100),
|
||||||
|
luminosity: luminosityInput.val()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Output color in desired format
|
||||||
|
|
||||||
|
function updateColorInput() {
|
||||||
|
var HSL = getHSL();
|
||||||
|
switch (formatInput.val()) {
|
||||||
|
case 'HSL':
|
||||||
|
colorInput.val('hsl(' + HSL.hue + ', ' + HSL.saturation + '%, ' + HSL.luminosity + '%)');
|
||||||
|
break;
|
||||||
|
case 'RGB':
|
||||||
|
var RGB = HSLToRGB(HSL.hue, HSL.saturation, HSL.luminosity);
|
||||||
|
colorInput.val('rgb(' + RGB.red + ', ' + RGB.green + ', ' + RGB.blue + ')');
|
||||||
|
break;
|
||||||
|
case 'Hex':
|
||||||
|
colorInput.val(HSLToHex(HSL.hue, HSL.saturation, HSL.luminosity));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Trigger color picker change event for custom callbacks
|
||||||
|
picker.trigger('change');
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------- Set color format
|
||||||
|
|
||||||
|
formatInput.on('change', function() {
|
||||||
|
updateColorInput();
|
||||||
|
});
|
||||||
|
|
||||||
|
//---------------------- Set color
|
||||||
|
|
||||||
|
colorInput.on('change', function() {
|
||||||
|
// Get the color values in HSL format
|
||||||
|
var HSL;
|
||||||
|
switch (formatInput.val()) {
|
||||||
|
case 'HSL':
|
||||||
|
var values = $(this).val().match(/\d+/g);
|
||||||
|
HSL = {
|
||||||
|
hue: values[0],
|
||||||
|
saturation: values[1],
|
||||||
|
luminosity: values[2]
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 'RGB':
|
||||||
|
var values = $(this).val().match(/\d+/g);
|
||||||
|
HSL = RGBToHSL(values[0], values[1], values[2]);
|
||||||
|
break;
|
||||||
|
case 'Hex':
|
||||||
|
HSL = hexToHSL($(this).val());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Set the luminosity
|
||||||
|
luminosityInput.val(HSL.luminosity);
|
||||||
|
setLuminosity(HSL.luminosity);
|
||||||
|
// Place the pin
|
||||||
|
pin.css({
|
||||||
|
left: HSL.hue / 360 * 100 + '%',
|
||||||
|
top: HSL.saturation + '%'
|
||||||
|
});
|
||||||
|
// Trigger color picker change event for custom callbacks
|
||||||
|
picker.trigger('change');
|
||||||
|
});
|
||||||
|
|
||||||
|
//---------------------- Set luminosity
|
||||||
|
|
||||||
|
//---------- Set the luminosity spectrum overlay
|
||||||
|
|
||||||
|
function setLuminosity(luminosity) {
|
||||||
|
var color,
|
||||||
|
alpha;
|
||||||
|
if (luminosity <= 50) {
|
||||||
|
color = '0, 0, 0';
|
||||||
|
alpha = 1 - luminosity / 100 * 2;
|
||||||
|
} else {
|
||||||
|
color = '255, 255, 255';
|
||||||
|
alpha = luminosity / 100 * 2 - 1;
|
||||||
|
}
|
||||||
|
// Apply luminosity to the spectrum
|
||||||
|
spectrum.children().css('background-color', 'rgba(' + color + ', ' + alpha + ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------- Luminosity input interaction
|
||||||
|
|
||||||
|
luminosityInput.on('change', function() {
|
||||||
|
setLuminosity($(this).val());
|
||||||
|
updateColorInput();
|
||||||
|
});
|
||||||
|
|
||||||
|
//---------------------- Set hue, saturation via pin
|
||||||
|
|
||||||
|
//---------- Move the pin
|
||||||
|
|
||||||
|
var movePin = function(event) {
|
||||||
|
var offset = spectrum.offset(),
|
||||||
|
width = spectrum.width(),
|
||||||
|
height = spectrum.height(),
|
||||||
|
x = event.clientX - offset.left,
|
||||||
|
y = event.clientY - offset.top;
|
||||||
|
// Account for pin being dragged outside the spectrum area
|
||||||
|
// Sanatize x
|
||||||
|
if (x < 0) {
|
||||||
|
x = 0;
|
||||||
|
} else if (x >= width) {
|
||||||
|
x = width;
|
||||||
|
}
|
||||||
|
// Sanatize y
|
||||||
|
if (y < 0) {
|
||||||
|
y = 0;
|
||||||
|
} else if (y >= height) {
|
||||||
|
y = height;
|
||||||
|
}
|
||||||
|
// Place the pin
|
||||||
|
pin.css({
|
||||||
|
left: x / width * 100 + '%',
|
||||||
|
top: y / height * 100 + '%'
|
||||||
|
});
|
||||||
|
// Output new color value
|
||||||
|
updateColorInput();
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------- Pin interaction
|
||||||
|
|
||||||
|
spectrum.on('mousedown', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
movePin(event);
|
||||||
|
spectrum.addClass('active');
|
||||||
|
$(document).on('mousemove', movePin);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on('mouseup', function() {
|
||||||
|
spectrum.removeClass('active');
|
||||||
|
$(document).off('mousemove', movePin);
|
||||||
|
});
|
||||||
|
|
||||||
|
spectrum.on('touchmove touchstart', movePin);
|
||||||
|
|
||||||
|
//---------------------- Output color preview
|
||||||
|
|
||||||
|
picker.on('change', function() {
|
||||||
|
colorInput.css('background-color', colorInput.val()).toggleClass('dark', luminosityInput.val() <= 50);
|
||||||
|
});
|
||||||
|
|
||||||
|
//---------------------- Initialize this color picker
|
||||||
|
|
||||||
|
colorInput.trigger('change');
|
||||||
|
});
|
||||||
|
});
|
22
js/libs/stack.js
Normal file
22
js/libs/stack.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Zepto.js
|
||||||
|
// (c) 2010-2014 Thomas Fuchs
|
||||||
|
// Zepto.js may be freely distributed under the MIT license.
|
||||||
|
|
||||||
|
;(function($){
|
||||||
|
$.fn.end = function(){
|
||||||
|
return this.prevObject || $()
|
||||||
|
}
|
||||||
|
|
||||||
|
$.fn.andSelf = function(){
|
||||||
|
return this.add(this.prevObject || $())
|
||||||
|
}
|
||||||
|
|
||||||
|
'filter,add,not,eq,first,last,find,closest,parents,parent,children,siblings'.split(',').forEach(function(property){
|
||||||
|
var fn = $.fn[property]
|
||||||
|
$.fn[property] = function(){
|
||||||
|
var ret = fn.apply(this, arguments)
|
||||||
|
ret.prevObject = this
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})(Zepto)
|
165
js/libs/touch.js
Normal file
165
js/libs/touch.js
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
// Zepto.js
|
||||||
|
// (c) 2010-2014 Thomas Fuchs
|
||||||
|
// Zepto.js may be freely distributed under the MIT license.
|
||||||
|
|
||||||
|
;(function($){
|
||||||
|
var touch = {},
|
||||||
|
touchTimeout, tapTimeout, swipeTimeout, longTapTimeout,
|
||||||
|
longTapDelay = 750,
|
||||||
|
gesture
|
||||||
|
|
||||||
|
function swipeDirection(x1, x2, y1, y2) {
|
||||||
|
return Math.abs(x1 - x2) >=
|
||||||
|
Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')
|
||||||
|
}
|
||||||
|
|
||||||
|
function longTap() {
|
||||||
|
longTapTimeout = null
|
||||||
|
if (touch.last) {
|
||||||
|
touch.el.trigger('longTap')
|
||||||
|
touch = {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelLongTap() {
|
||||||
|
if (longTapTimeout) clearTimeout(longTapTimeout)
|
||||||
|
longTapTimeout = null
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancelAll() {
|
||||||
|
if (touchTimeout) clearTimeout(touchTimeout)
|
||||||
|
if (tapTimeout) clearTimeout(tapTimeout)
|
||||||
|
if (swipeTimeout) clearTimeout(swipeTimeout)
|
||||||
|
if (longTapTimeout) clearTimeout(longTapTimeout)
|
||||||
|
touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null
|
||||||
|
touch = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPrimaryTouch(event){
|
||||||
|
return (event.pointerType == 'touch' ||
|
||||||
|
event.pointerType == event.MSPOINTER_TYPE_TOUCH)
|
||||||
|
&& event.isPrimary
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPointerEventType(e, type){
|
||||||
|
return (e.type == 'pointer'+type ||
|
||||||
|
e.type.toLowerCase() == 'mspointer'+type)
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
var now, delta, deltaX = 0, deltaY = 0, firstTouch, _isPointerType
|
||||||
|
|
||||||
|
if ('MSGesture' in window) {
|
||||||
|
gesture = new MSGesture()
|
||||||
|
gesture.target = document.body
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.bind('MSGestureEnd', function(e){
|
||||||
|
var swipeDirectionFromVelocity =
|
||||||
|
e.velocityX > 1 ? 'Right' : e.velocityX < -1 ? 'Left' : e.velocityY > 1 ? 'Down' : e.velocityY < -1 ? 'Up' : null;
|
||||||
|
if (swipeDirectionFromVelocity) {
|
||||||
|
touch.el.trigger('swipe')
|
||||||
|
touch.el.trigger('swipe'+ swipeDirectionFromVelocity)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('touchstart MSPointerDown pointerdown', function(e){
|
||||||
|
if((_isPointerType = isPointerEventType(e, 'down')) &&
|
||||||
|
!isPrimaryTouch(e)) return
|
||||||
|
firstTouch = _isPointerType ? e : e.touches[0]
|
||||||
|
if (e.touches && e.touches.length === 1 && touch.x2) {
|
||||||
|
// Clear out touch movement data if we have it sticking around
|
||||||
|
// This can occur if touchcancel doesn't fire due to preventDefault, etc.
|
||||||
|
touch.x2 = undefined
|
||||||
|
touch.y2 = undefined
|
||||||
|
}
|
||||||
|
now = Date.now()
|
||||||
|
delta = now - (touch.last || now)
|
||||||
|
touch.el = $('tagName' in firstTouch.target ?
|
||||||
|
firstTouch.target : firstTouch.target.parentNode)
|
||||||
|
touchTimeout && clearTimeout(touchTimeout)
|
||||||
|
touch.x1 = firstTouch.pageX
|
||||||
|
touch.y1 = firstTouch.pageY
|
||||||
|
if (delta > 0 && delta <= 250) touch.isDoubleTap = true
|
||||||
|
touch.last = now
|
||||||
|
longTapTimeout = setTimeout(longTap, longTapDelay)
|
||||||
|
// adds the current touch contact for IE gesture recognition
|
||||||
|
if (gesture && _isPointerType) gesture.addPointer(e.pointerId);
|
||||||
|
})
|
||||||
|
.on('touchmove MSPointerMove pointermove', function(e){
|
||||||
|
if((_isPointerType = isPointerEventType(e, 'move')) &&
|
||||||
|
!isPrimaryTouch(e)) return
|
||||||
|
firstTouch = _isPointerType ? e : e.touches[0]
|
||||||
|
cancelLongTap()
|
||||||
|
touch.x2 = firstTouch.pageX
|
||||||
|
touch.y2 = firstTouch.pageY
|
||||||
|
|
||||||
|
deltaX += Math.abs(touch.x1 - touch.x2)
|
||||||
|
deltaY += Math.abs(touch.y1 - touch.y2)
|
||||||
|
})
|
||||||
|
.on('touchend MSPointerUp pointerup', function(e){
|
||||||
|
if((_isPointerType = isPointerEventType(e, 'up')) &&
|
||||||
|
!isPrimaryTouch(e)) return
|
||||||
|
cancelLongTap()
|
||||||
|
|
||||||
|
// swipe
|
||||||
|
if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||
|
||||||
|
(touch.y2 && Math.abs(touch.y1 - touch.y2) > 30))
|
||||||
|
|
||||||
|
swipeTimeout = setTimeout(function() {
|
||||||
|
touch.el.trigger('swipe')
|
||||||
|
touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))
|
||||||
|
touch = {}
|
||||||
|
}, 0)
|
||||||
|
|
||||||
|
// normal tap
|
||||||
|
else if ('last' in touch)
|
||||||
|
// don't fire tap when delta position changed by more than 30 pixels,
|
||||||
|
// for instance when moving to a point and back to origin
|
||||||
|
if (deltaX < 30 && deltaY < 30) {
|
||||||
|
// delay by one tick so we can cancel the 'tap' event if 'scroll' fires
|
||||||
|
// ('tap' fires before 'scroll')
|
||||||
|
tapTimeout = setTimeout(function() {
|
||||||
|
|
||||||
|
// trigger universal 'tap' with the option to cancelTouch()
|
||||||
|
// (cancelTouch cancels processing of single vs double taps for faster 'tap' response)
|
||||||
|
var event = $.Event('tap')
|
||||||
|
event.cancelTouch = cancelAll
|
||||||
|
touch.el.trigger(event)
|
||||||
|
|
||||||
|
// trigger double tap immediately
|
||||||
|
if (touch.isDoubleTap) {
|
||||||
|
if (touch.el) touch.el.trigger('doubleTap')
|
||||||
|
touch = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// trigger single tap after 250ms of inactivity
|
||||||
|
else {
|
||||||
|
touchTimeout = setTimeout(function(){
|
||||||
|
touchTimeout = null
|
||||||
|
if (touch.el) touch.el.trigger('singleTap')
|
||||||
|
touch = {}
|
||||||
|
}, 250)
|
||||||
|
}
|
||||||
|
}, 0)
|
||||||
|
} else {
|
||||||
|
touch = {}
|
||||||
|
}
|
||||||
|
deltaX = deltaY = 0
|
||||||
|
|
||||||
|
})
|
||||||
|
// when the browser window loses focus,
|
||||||
|
// for example when a modal dialog is shown,
|
||||||
|
// cancel all ongoing events
|
||||||
|
.on('touchcancel MSPointerCancel pointercancel', cancelAll)
|
||||||
|
|
||||||
|
// scrolling the window indicates intention of the user
|
||||||
|
// to scroll, not tap or swipe, so cancel all ongoing events
|
||||||
|
$(window).on('scroll', cancelAll)
|
||||||
|
})
|
||||||
|
|
||||||
|
;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown',
|
||||||
|
'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(eventName){
|
||||||
|
$.fn[eventName] = function(callback){ return this.on(eventName, callback) }
|
||||||
|
})
|
||||||
|
})(Zepto)
|
4
js/libs/zepto.min.js
vendored
4
js/libs/zepto.min.js
vendored
File diff suppressed because one or more lines are too long
26
js/main.js
26
js/main.js
@ -1,22 +1,17 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
yepnope({
|
|
||||||
test: window.mobile,
|
|
||||||
yep : 'js/mobile-events.js',
|
|
||||||
nope: 'js/events.js'
|
|
||||||
})
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
window.c = $('canvas')[0].getContext('2d');
|
window.c = $('canvas')[0].getContext('2d');
|
||||||
window.o = $('canvas')[1].getContext('2d');
|
window.o = $('canvas')[1].getContext('2d');
|
||||||
|
|
||||||
window.settings = {
|
window.settings = {
|
||||||
lineWidth : 0.2,
|
lineWidth : 2,
|
||||||
strokeStyle : 'black',
|
color : 'black',
|
||||||
type: 'sketch',
|
type: 'sketch',
|
||||||
lineCap: 'round',
|
lineCap: 'round',
|
||||||
lineJoin: 'round',
|
lineJoin: 'round',
|
||||||
furLength: 5
|
furLength: 5,
|
||||||
|
connectTelorance: 40
|
||||||
};
|
};
|
||||||
window.points = [];
|
window.points = [];
|
||||||
window.$c = $('canvas');
|
window.$c = $('canvas');
|
||||||
@ -25,4 +20,17 @@ $(document).ready(function() {
|
|||||||
sizeAndPos();
|
sizeAndPos();
|
||||||
$(window).resize(sizeAndPos);
|
$(window).resize(sizeAndPos);
|
||||||
|
|
||||||
|
$('.color-picker').change(function() {
|
||||||
|
var c = $(this).find('.color').val();
|
||||||
|
settings.color = c;
|
||||||
|
$('#setcolor span').html(c);
|
||||||
|
})
|
||||||
|
$('.color').val('#000000');
|
||||||
|
|
||||||
|
yepnope({
|
||||||
|
test: window.mobile,
|
||||||
|
yep : ['js/mobile-events.js', 'js/libs/color-picker-touch.js'],
|
||||||
|
nope: ['js/events.js', 'js/libs/color-picker.js']
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -1,28 +1,63 @@
|
|||||||
$('.menu').bind('touchend', function() {
|
"use strict";
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
switch(save.background) {
|
||||||
|
case 'white': {
|
||||||
|
var cache = {
|
||||||
|
fillStyle: c.color,
|
||||||
|
composite: c.globalCompositeOperation
|
||||||
|
}
|
||||||
|
c.fillStyle = 'white';
|
||||||
|
c.globalCompositeOperation = 'destination-over';
|
||||||
|
c.fillRect(0, 0, $c.width(), $c.height());
|
||||||
|
c.fillStyle = cache.fillStyle;
|
||||||
|
c.globalCompositeOperation = cache.composite;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'current color': {
|
||||||
|
var cache = {
|
||||||
|
fillStyle: c.color,
|
||||||
|
composite: c.globalCompositeOperation
|
||||||
|
}
|
||||||
|
c.fillStyle = settings.strokeStyle;
|
||||||
|
c.globalCompositeOperation = 'destination-over';
|
||||||
|
c.fillRect(0, 0, $c.width(), $c.height());
|
||||||
|
c.fillStyle = cache.fillStyle;
|
||||||
|
c.globalCompositeOperation = cache.composite;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var data = $c[0].toDataURL();
|
||||||
|
var file = dataToBlob($c[0].toDataURL());
|
||||||
|
var pics = navigator.getDeviceStorage('pictures');
|
||||||
|
var r = pics.addNamed(file, save['file name'] + '.png');
|
||||||
|
r.onsuccess = function() {
|
||||||
|
alert('Your sketch was successfuly saved to pictures/' + this.result.name);
|
||||||
|
}
|
||||||
|
r.onerror = function() {
|
||||||
|
alert('Something bad happened when we tried to save your file\n Possible problems: \n Duplicate name \n Permission problems')
|
||||||
|
console.warn(this.error);
|
||||||
|
}
|
||||||
|
c.putImageData(window.points.history[window.points.history.length-1].data, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.menu').on('tap', function() {
|
||||||
$('#menu').toggleClass('pulled');
|
$('#menu').toggleClass('pulled');
|
||||||
})
|
})
|
||||||
$('.save').bind('touchend', function() {
|
$('.save').on('tap', function() {
|
||||||
var data = $c[0].toDataURL();
|
$('#save').removeClass('hidden');
|
||||||
var img = $('<img src="' + data + '" width="' + $c.width() + '" height="' + $c.height() + '" class="overlay"/>');
|
|
||||||
$('body').append(img);
|
|
||||||
var share = new MozActivity({
|
|
||||||
name: 'share',
|
|
||||||
data: {
|
|
||||||
type: 'image/*'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
$c.last().bind('touchstart', function(e) {
|
$c.last().on('touchstart', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
|
var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
|
||||||
startPoint(xy.x, xy.y);
|
startPoint(xy.x, xy.y);
|
||||||
window.active = true;
|
window.active = true;
|
||||||
}).bind('touchmove', function(e) {
|
}).on('touchmove', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!window.active || settings.type == 'line') return;
|
if (!window.active || settings.type == 'line') return;
|
||||||
var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
|
var xy = relative(e.changedTouches[0].pageX, e.changedTouches[0].pageY);
|
||||||
drawPoint(xy.x, xy.y);
|
drawPoint(xy.x, xy.y);
|
||||||
}).bind('touchend', function(e) {
|
}).on('touchend', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
window.active = false;
|
window.active = false;
|
||||||
|
|
||||||
@ -39,31 +74,67 @@
|
|||||||
|
|
||||||
// Value Selector
|
// Value Selector
|
||||||
|
|
||||||
var $selector = $('form[data-type="value-selector"]');
|
var $single = $('form[data-type="value-selector"].single');
|
||||||
|
|
||||||
$selector.find('li').on('touchend', function(e) {
|
$single.find('li').on('tap', function(e) {
|
||||||
$(this).parent().find('li').removeAttr('aria-selected');
|
e.preventDefault();
|
||||||
|
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
|
||||||
$(this).attr('aria-selected', 'true');
|
$(this).attr('aria-selected', 'true');
|
||||||
var prop = $(this).parents('form').attr('id'),
|
var key = $(this).parents('form').attr('id'),
|
||||||
key = $(this).find('label span').html().toLowerCase();
|
value = $(this).find('label span').html().toLowerCase();
|
||||||
window.settings[prop] = key;
|
window.settings[key] = value;
|
||||||
|
|
||||||
$('button[id="set' + prop + '"] span').html(key[0].toUpperCase() + key.substr(1));
|
$('button[id="set' + key + '"] span').html(value[0].toUpperCase() + value.substr(1));
|
||||||
|
$('#menu div.options > div').addClass('hidden');
|
||||||
|
$('#menu div.options > .general, #menu div.options > .'+value).removeClass('hidden');
|
||||||
|
|
||||||
$(this).parents('form').addClass('hidden');
|
$(this).parents('form').addClass('hidden');
|
||||||
})
|
})
|
||||||
|
|
||||||
$selector.submit(function(e) {
|
$single.submit(function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$(this).addClass('hidden');
|
$(this).addClass('hidden');
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Confirm
|
||||||
|
|
||||||
|
var $confirm = $('form[data-type="value-selector"].confirm');
|
||||||
|
|
||||||
|
$confirm.find('li').on('tap', function(e) {
|
||||||
|
$(this).parent().find('li[aria-selected]').removeAttr('aria-selected');
|
||||||
|
$(this).attr('aria-selected', 'true');
|
||||||
|
})
|
||||||
|
$confirm.find('button').last().on('tap', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var v = $(this).parents('form').attr('id');
|
||||||
|
$(this).parents('form').find('h1').each(function(i) {
|
||||||
|
if( i > 0 ) {
|
||||||
|
var key = $(this).html().toLowerCase();
|
||||||
|
var value = $(this).parent().find('ol:nth-of-type('+i+') li[aria-selected] span').html();
|
||||||
|
if( key !== 'file name' ) value = key.toLowerCase();
|
||||||
|
|
||||||
|
window[v][key] = value;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
$(this).parents('form').addClass('hidden');
|
||||||
|
window[v]();
|
||||||
|
})
|
||||||
|
$confirm.find('button').first().on('tap', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$(this).parents('form').addClass('hidden');
|
||||||
|
})
|
||||||
|
|
||||||
// Value Selector Callers
|
// Value Selector Callers
|
||||||
|
|
||||||
var $btn = $('button[id^="set"]');
|
var $btn = $('button[id^="set"]');
|
||||||
$btn.each(function() {
|
$btn.each(function() {
|
||||||
var target = /set(.*)/.exec($(this).attr('id'))[1];
|
var target = /set(.*)/.exec($(this).attr('id'))[1];
|
||||||
$(this).on('touchend', function(e) {
|
if( target == 'color' ) {
|
||||||
|
return $(this).on('tap', function() {
|
||||||
|
$('.picker').removeClass('hidden');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
$(this).on('tap', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$('form[id="' + target + '"]').removeClass('hidden');
|
$('form[id="' + target + '"]').removeClass('hidden');
|
||||||
})
|
})
|
||||||
@ -71,19 +142,49 @@
|
|||||||
|
|
||||||
// Seekbar
|
// Seekbar
|
||||||
|
|
||||||
var sliderLeft = $('div[role="slider"] button').offset().left;
|
var sliderLeft;
|
||||||
$('div[role="slider"] button').on('touchstart', function() {
|
$('div[role="slider"] button').on('touchstart', function() {
|
||||||
$(this).attr('data-moving','true');
|
$(this).attr('data-moving','true');
|
||||||
|
if( !sliderLeft ) sliderLeft = $('div[role="slider"] button').offset().left;
|
||||||
}).on('touchmove', function(e) {
|
}).on('touchmove', function(e) {
|
||||||
if( $(this).attr('data-moving') ) {
|
if( $(this).attr('data-moving') ) {
|
||||||
var x = e.changedTouches[0].pageX - sliderLeft - 15;
|
var x = parseInt(e.changedTouches[0].pageX - sliderLeft - 15);
|
||||||
if( x <= 100 && x > 0 ) {
|
var progress = $(this).parent().children().first();
|
||||||
|
var max = +progress.attr('max');
|
||||||
|
var min = +progress.attr('min');
|
||||||
|
if( x <= max && x >= min ) {
|
||||||
$(this).css('left', x+'%');
|
$(this).css('left', x+'%');
|
||||||
$(this).parent().find('progress').attr('value', x);
|
$(this).parent().find('progress').attr('value', x);
|
||||||
settings.lineWidth = x / 10;
|
var key = $(this).parents('div[role="slider"]').attr('class');
|
||||||
$('#lineWidth span').html(x);
|
settings[key] = x;
|
||||||
|
$('#'+ key +' span').html(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).on('touchend', function() {
|
}).on('touchend', function() {
|
||||||
$(this).removeAttr('data-moving');
|
$(this).removeAttr('data-moving');
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Color Picker
|
||||||
|
|
||||||
|
$('#closePicker').on('tap', function() {
|
||||||
|
$('.picker').addClass('hidden');
|
||||||
|
})
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
|
||||||
|
$('#clear').on('tap', function() {
|
||||||
|
c.clearRect(0, 0, $c.width(), $c.height());
|
||||||
|
if(window.points.history.last < window.points.history.length-1) {
|
||||||
|
window.points.history.splice(window.points.history.last+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.points.history.push({
|
||||||
|
data: c.getImageData(0, 0, $c.width(), $c.height()),
|
||||||
|
points: []
|
||||||
|
})
|
||||||
|
window.points.history.last = window.points.history.length-1;
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#undo').on('tap', undo);
|
||||||
|
$('#redo').on('tap', redo);
|
||||||
|
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
"name": "Sketchy",
|
"name": "Sketchy",
|
||||||
"description": "Free Sketch/Paint app",
|
"description": "Free Sketch/Paint app",
|
||||||
"version": 1,
|
"version": 1,
|
||||||
|
"fullscreen": true,
|
||||||
|
"type": "privileged",
|
||||||
"launch_path": "/index.html",
|
"launch_path": "/index.html",
|
||||||
"icons": {
|
"icons": {
|
||||||
"16": "/img/icons/icon16.png",
|
"16": "/img/icons/icon16.png",
|
||||||
@ -22,5 +24,11 @@
|
|||||||
"name": "Sketchy",
|
"name": "Sketchy",
|
||||||
"description": "برنامهی رایگان طراحی/نقاشی"
|
"description": "برنامهی رایگان طراحی/نقاشی"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"permissions": {
|
||||||
|
"device-storage:pictures": {
|
||||||
|
"description": "Required to save sketched pics",
|
||||||
|
"access": "readwrite"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user