Undo/Redo
This commit is contained in:
parent
9f427204ac
commit
17a8409a68
@ -10,8 +10,15 @@ html, body {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div#container {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
canvas {
|
canvas {
|
||||||
border: 1px solid gray;
|
border: 1px solid gray;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
|
BIN
img/icons/1.png
Normal file
BIN
img/icons/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
BIN
img/icons/demo1.png
Normal file
BIN
img/icons/demo1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
@ -14,7 +14,10 @@
|
|||||||
<button id='menu'></button>
|
<button id='menu'></button>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<canvas></canvas>
|
<div id='container'>
|
||||||
|
<canvas></canvas>
|
||||||
|
<canvas></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src='js/libs/zepto.min.js'></script>
|
<script src='js/libs/zepto.min.js'></script>
|
||||||
<script src='js/functions.js'></script>
|
<script src='js/functions.js'></script>
|
||||||
|
@ -6,11 +6,8 @@ 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.css({'margin-left': w * .05,
|
$c.attr('width', w);
|
||||||
'margin-top': h * .05
|
$c.attr('height',h - 50);
|
||||||
})
|
|
||||||
$c.attr('width', w * .9);
|
|
||||||
$c.attr('height',h * .9 - 50);
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -28,8 +25,10 @@ function threshold(x1, y1, x2, y2, threshold) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function line(x1, y1, x2, y2, opts) {
|
function line(x1, y1, x2, y2, opts, overlay) {
|
||||||
opts = opts || {};
|
opts = opts || {};
|
||||||
|
var c = window.c;
|
||||||
|
if( overlay ) var c = window.o;
|
||||||
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;
|
||||||
@ -40,13 +39,47 @@ function line(x1, y1, x2, y2, opts) {
|
|||||||
c.stroke();
|
c.stroke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function erase(x1, y1, x2, y2, overlay) {
|
||||||
|
var c = window.c;
|
||||||
|
if( overlay ) var c = window.o;
|
||||||
|
c.clearRect(x1, y1, x2 - x1, y2 - y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function undo() {
|
||||||
|
var history = window.points.history;
|
||||||
|
if( history.last > 1 ) {
|
||||||
|
var step = history[history.last-1];
|
||||||
|
c.putImageData(step.data, 0, 0);
|
||||||
|
window.points = step.points.slice(0);
|
||||||
|
window.points.history = history;
|
||||||
|
window.points.history.last = history.last-1;
|
||||||
|
} else {
|
||||||
|
c.clearRect(0,0, $c.width(), $c.height());
|
||||||
|
window.points = [];
|
||||||
|
window.points.history = history;
|
||||||
|
window.points.history.last = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function redo() {
|
||||||
|
var history = window.points.history;
|
||||||
|
if( history.last < history.length-1 ) {
|
||||||
|
var step = history[history.last+1];
|
||||||
|
c.putImageData(step.data, 0, 0);
|
||||||
|
window.points = step.points.slice(0);
|
||||||
|
window.points.history = history;
|
||||||
|
window.points.history.last = history.last+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*** END ***/
|
/*** END ***/
|
||||||
|
|
||||||
function startPoint(x, y) {
|
function startPoint(x, y) {
|
||||||
|
|
||||||
// If not previous point exists, make the first one.
|
// If no previous point exists, make the first one.
|
||||||
if( !points.length ) points.push({x: x, y: y, type: settings.type, start: {x: x, y: y}});
|
if( !points.length ) points.push({x: x, y: y, type: '', start: {x: x, y: y}});
|
||||||
|
|
||||||
var old = points[points.length-1],
|
var old = points[points.length-1],
|
||||||
start = old.start,
|
start = old.start,
|
||||||
@ -56,10 +89,12 @@ function startPoint(x, y) {
|
|||||||
start : old.start || {x: x, y: y},
|
start : old.start || {x: x, y: y},
|
||||||
type : settings.type
|
type : settings.type
|
||||||
}
|
}
|
||||||
// Just draws a circle
|
if( old.type !== 'line' && current.type == 'line' ) {
|
||||||
line(x,y,x,y);
|
line(x,y,x,y, {lineWidth: 5, strokeStyle: 'red'}, true);
|
||||||
|
}
|
||||||
|
|
||||||
if( old.type == 'line' ) {
|
if( old.type == 'line' ) {
|
||||||
|
if( points[points.indexOf(old)-1].type !== 'line' ) erase(old.x-5, old.y-5, old.x+5, old.y+5, true);
|
||||||
line(old.x, old.y, x, y);
|
line(old.x, old.y, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +105,10 @@ function startPoint(x, y) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(current.type == 'ribbon') {
|
||||||
|
settings.ribbonTimes = 1;
|
||||||
|
}
|
||||||
|
|
||||||
points.push(current);
|
points.push(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +140,7 @@ 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, 40)) {
|
||||||
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;
|
||||||
|
|
||||||
@ -110,7 +149,26 @@ function drawPoint(x,y) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'fur': {
|
||||||
|
line(capture.x, capture.y, x, y);
|
||||||
|
var current = {
|
||||||
|
x : x,
|
||||||
|
y : y,
|
||||||
|
start : capture.start,
|
||||||
|
type : capture.type
|
||||||
|
}
|
||||||
|
points.push(current);
|
||||||
|
|
||||||
|
for( var i = 0, len = points.length-1; i < len; i++ ) {
|
||||||
|
if(threshold(points[i].x, points[i].y, current.x, current.y, 40)) {
|
||||||
|
var x = points[i].x - current.x,
|
||||||
|
y = points[i].y - current.y;
|
||||||
|
var l = settings.furLength || 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})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
37
js/main.js
37
js/main.js
@ -1,47 +1,50 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
$(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.settings = {
|
window.settings = {
|
||||||
lineWidth : 0.2,
|
lineWidth : 0.2,
|
||||||
strokeStyle : 'black',
|
strokeStyle : 'black',
|
||||||
type: 'sketch',
|
type: 'sketch',
|
||||||
lineCap: 'round',
|
lineCap: 'round',
|
||||||
lineJoin: 'round'
|
lineJoin: 'round',
|
||||||
|
ribbonEnd: 50,
|
||||||
|
ribbonTurn : 0
|
||||||
};
|
};
|
||||||
window.points = [];
|
window.points = [];
|
||||||
window.$c = $('canvas');
|
window.$c = $('canvas');
|
||||||
|
window.points.history = [{ data: c.createImageData($c.width(), $c.height()), points: []}];
|
||||||
|
|
||||||
sizeAndPos();
|
sizeAndPos();
|
||||||
$(window).resize(sizeAndPos);
|
$(window).resize(sizeAndPos);
|
||||||
|
|
||||||
$c.bind('mousedown', function(e) {
|
$c.last().bind('mousedown touchstart', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if( e.changedTouches ) e = e.changedTouches[0];
|
||||||
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) {
|
}).bind('mousemove touchmove', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (!window.active || settings.type == 'line') return;
|
if (!window.active || settings.type == 'line') return;
|
||||||
|
if( e.changedTouches ) e = e.changedTouches[0];
|
||||||
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 touchend', function(e) {
|
}).bind('mouseup touchend', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
window.active = false;
|
window.active = false;
|
||||||
}).bind('touchstart', function(e) {
|
|
||||||
e.preventDefault();
|
if(window.points.history.last < window.points.history.length-1) {
|
||||||
var touch = e.changedTouches[0];
|
window.points.history.splice(window.points.history.last+1);
|
||||||
var xy = relative(touch.pageX, touch.pageY);
|
}
|
||||||
startPoint(xy.x, xy.y);
|
|
||||||
window.active = true;
|
window.points.history.push({
|
||||||
}).bind('touchmove', function(e) {
|
data: c.getImageData(0, 0, $c.width(), $c.height()),
|
||||||
e.preventDefault();
|
points: window.points.slice(0)
|
||||||
if(!window.active || settings.type =='line') return;
|
})
|
||||||
var touch = e.changedTouches[0];
|
window.points.history.last = window.points.history.length-1;
|
||||||
var xy = relative(touch.pageX, touch.pageY);
|
|
||||||
drawPoint(xy.x, xy.y);
|
|
||||||
window.active = true;
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
26
manifest.webapp
Normal file
26
manifest.webapp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "Sketchy",
|
||||||
|
"description": "Free Sketch/Paint app",
|
||||||
|
"version": 1,
|
||||||
|
"launch_path": "/index.html",
|
||||||
|
"icons": {
|
||||||
|
"16": "/images/logo16.png",
|
||||||
|
"32": "/images/logo32.png",
|
||||||
|
"48": "/images/logo48.png",
|
||||||
|
"60": "/images/logo60.png",
|
||||||
|
"64": "/images/logo64.png",
|
||||||
|
"90": "/images/logo90.png",
|
||||||
|
"120": "/images/logo120.png",
|
||||||
|
"128": "/images/logo128.png"
|
||||||
|
},
|
||||||
|
"developer": {
|
||||||
|
"name": "Mahdi Dibaiee",
|
||||||
|
"url": "https://twitter.com/mdibaiee"
|
||||||
|
},
|
||||||
|
"locales": {
|
||||||
|
"fa": {
|
||||||
|
"name": "Sketchy",
|
||||||
|
"description": "برنامهی رایگان طراحی/نقاشی"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user