Undo/Redo
This commit is contained in:
parent
9f427204ac
commit
17a8409a68
@ -10,8 +10,15 @@ html, body {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
div#container {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
canvas {
|
||||
border: 1px solid gray;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
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>
|
||||
</header>
|
||||
|
||||
<div id='container'>
|
||||
<canvas></canvas>
|
||||
<canvas></canvas>
|
||||
</div>
|
||||
|
||||
<script src='js/libs/zepto.min.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 w = $(window).width(),
|
||||
h = $(window).height();
|
||||
$c.css({'margin-left': w * .05,
|
||||
'margin-top': h * .05
|
||||
})
|
||||
$c.attr('width', w * .9);
|
||||
$c.attr('height',h * .9 - 50);
|
||||
$c.attr('width', w);
|
||||
$c.attr('height',h - 50);
|
||||
c.clearRect(0,0, $c.width(), $c.height());
|
||||
c.putImageData(data, 0, 0);
|
||||
}
|
||||
@ -28,8 +25,10 @@ function threshold(x1, y1, x2, y2, threshold) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function line(x1, y1, x2, y2, opts) {
|
||||
function line(x1, y1, x2, y2, opts, overlay) {
|
||||
opts = opts || {};
|
||||
var c = window.c;
|
||||
if( overlay ) var c = window.o;
|
||||
c.beginPath();
|
||||
c.lineCap = opts.lineCap || settings.lineCap;
|
||||
c.lineJoin = opts.lineJoin || settings.lineJoin;
|
||||
@ -40,13 +39,47 @@ function line(x1, y1, x2, y2, opts) {
|
||||
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 ***/
|
||||
|
||||
function startPoint(x, y) {
|
||||
|
||||
// If not 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 no previous point exists, make the first one.
|
||||
if( !points.length ) points.push({x: x, y: y, type: '', start: {x: x, y: y}});
|
||||
|
||||
var old = points[points.length-1],
|
||||
start = old.start,
|
||||
@ -56,10 +89,12 @@ function startPoint(x, y) {
|
||||
start : old.start || {x: x, y: y},
|
||||
type : settings.type
|
||||
}
|
||||
// Just draws a circle
|
||||
line(x,y,x,y);
|
||||
if( old.type !== 'line' && current.type == 'line' ) {
|
||||
line(x,y,x,y, {lineWidth: 5, strokeStyle: 'red'}, true);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -70,6 +105,10 @@ function startPoint(x, y) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(current.type == 'ribbon') {
|
||||
settings.ribbonTimes = 1;
|
||||
}
|
||||
|
||||
points.push(current);
|
||||
}
|
||||
|
||||
@ -110,7 +149,26 @@ function drawPoint(x,y) {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
35
js/main.js
35
js/main.js
@ -2,46 +2,49 @@
|
||||
|
||||
$(document).ready(function() {
|
||||
window.c = $('canvas')[0].getContext('2d');
|
||||
window.o = $('canvas')[1].getContext('2d');
|
||||
|
||||
window.settings = {
|
||||
lineWidth : 0.2,
|
||||
strokeStyle : 'black',
|
||||
type: 'sketch',
|
||||
lineCap: 'round',
|
||||
lineJoin: 'round'
|
||||
lineJoin: 'round',
|
||||
ribbonEnd: 50,
|
||||
ribbonTurn : 0
|
||||
};
|
||||
window.points = [];
|
||||
window.$c = $('canvas');
|
||||
window.points.history = [{ data: c.createImageData($c.width(), $c.height()), points: []}];
|
||||
|
||||
sizeAndPos();
|
||||
$(window).resize(sizeAndPos);
|
||||
|
||||
$c.bind('mousedown', function(e) {
|
||||
$c.last().bind('mousedown touchstart', function(e) {
|
||||
e.preventDefault();
|
||||
if( e.changedTouches ) e = e.changedTouches[0];
|
||||
var xy = relative(e.pageX, e.pageY);
|
||||
startPoint(xy.x, xy.y);
|
||||
window.active = true;
|
||||
}).bind('mousemove', function(e) {
|
||||
}).bind('mousemove touchmove', function(e) {
|
||||
e.preventDefault();
|
||||
if (!window.active || settings.type == 'line') return;
|
||||
if( e.changedTouches ) e = e.changedTouches[0];
|
||||
var xy = relative(e.pageX, e.pageY);
|
||||
drawPoint(xy.x, xy.y);
|
||||
}).bind('mouseup touchend', function(e) {
|
||||
e.preventDefault();
|
||||
window.active = false;
|
||||
}).bind('touchstart', function(e) {
|
||||
e.preventDefault();
|
||||
var touch = e.changedTouches[0];
|
||||
var xy = relative(touch.pageX, touch.pageY);
|
||||
startPoint(xy.x, xy.y);
|
||||
window.active = true;
|
||||
}).bind('touchmove', function(e) {
|
||||
e.preventDefault();
|
||||
if(!window.active || settings.type =='line') return;
|
||||
var touch = e.changedTouches[0];
|
||||
var xy = relative(touch.pageX, touch.pageY);
|
||||
drawPoint(xy.x, xy.y);
|
||||
window.active = true;
|
||||
|
||||
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.slice(0)
|
||||
})
|
||||
window.points.history.last = window.points.history.length-1;
|
||||
})
|
||||
|
||||
})
|
||||
|
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