diff --git a/css/style.css b/css/style.css index 33cf7319..7008f476 100644 --- a/css/style.css +++ b/css/style.css @@ -24,6 +24,7 @@ ul, li { top : 0; bottom : 0; width : 200px; + overflow-y: scroll; background : #000; padding : 10px; } @@ -32,7 +33,7 @@ ul, li { position:absolute; top : 0; bottom : 0; - left : 200px; + left : 220px; right : 0; background : #ccc; } @@ -49,7 +50,7 @@ ul, li { box-shadow : 0px 0px 2px rgba(0,0,0,0.2); } -.preview-container canvas{ +.preview-container canvas { border : 0px Solid transparent; border-radius:5px 0px 0px 5px; } @@ -71,13 +72,43 @@ ul, li { display : inline-block; } -#preview-list li{ - margin : 10px 0; - width : 128px; - height : 128px; +#preview-list { + list-style-type: none; } -#preview-list li.selected{ - margin : 8px -2px; - border : 2px Solid red; +#preview-list .preview-tile { + padding : 10px; + overflow: hidden; +} + +.preview-tile .tile-view { + float: left; +} + +.preview-tile .tile-action { + display: none; + float: right; +} + +.preview-tile:hover .tile-action { + display: block; +} + +.preview-tile:hover { + background-color: lightgray; +} + +#preview-list .preview-tile.selected { + background-color: gray; +} + +::-webkit-scrollbar { + -webkit-appearance: none; + width: 7px; +} + +::-webkit-scrollbar-thumb { + border-radius: 4px; + background-color: rgba(180,180,180,.7); + -webkit-box-shadow: 0 0 1px rgba(255,255,255,.5); } \ No newline at end of file diff --git a/index.html b/index.html index f8f0d7c9..bd5efe8b 100644 --- a/index.html +++ b/index.html @@ -17,10 +17,10 @@ onmousedown="piskel.onCanvasMousedown(arguments[0])" onmouseup="piskel.onCanvasMouseup(arguments[0])">
- Add a Frame - +
@@ -28,6 +28,9 @@
+
+ +
diff --git a/js/piskel.js b/js/piskel.js index 62c719e5..f35d0629 100644 --- a/js/piskel.js +++ b/js/piskel.js @@ -5,8 +5,40 @@ var piskel = { init : function () { this.addFrame(); + this.initPreview(); + }, - setInterval(this.refreshAnimatedPreview, 500); + initPreview : function() { + var scope = this; + + var animFPSTuner = document.getElementById("preview-fps"); + var animPreviewFPS = parseInt(animFPSTuner.value, 10); + var startPreviewRefresh = function() { + return setInterval(scope.refreshAnimatedPreview, 1000/animPreviewFPS); + }; + var refreshUpdater = startPreviewRefresh(); + + animFPSTuner.addEventListener('keyup', function(evt) { + window.clearInterval(refreshUpdater); + animPreviewFPS = parseInt(animFPSTuner.value, 10); + if(isNaN(animPreviewFPS)) { + animPreviewFPS = 1; + } + if(evt.keyCode == 38) { + animPreviewFPS++; + } + else if (evt.keyCode == 40) { + animPreviewFPS--; + } + if(animPreviewFPS < 1) { + animPreviewFPS = 1; + } + if(animPreviewFPS > 100) { + animPreviewFPS = 100; + } + animFPSTuner.value = animPreviewFPS; + refreshUpdater = startPreviewRefresh(); + }); }, getCurrentCanvas : function () { @@ -22,29 +54,50 @@ }, createPreviews : function () { - var container = $('preview-list'); + var container = $('preview-list'), previewTile; container.innerHTML = ""; for (var i = 0 ; i < frames.length ; i++) { - var preview = document.createElement("li"); - if (index == i) { - preview.className = "selected"; - } - var canvasPreview = document.createElement("canvas"); - - canvasPreview.setAttribute('width', '128'); - canvasPreview.setAttribute('height', '128'); - - canvasPreview.setAttribute('onclick', 'piskel.setFrame('+i+')'); - - canvasPreview.getContext('2d').drawImage(frames[i], 0, 0, 320, 320, 0, 0 , 128, 128); - preview.appendChild(canvasPreview); - - - container.appendChild(preview); - + previewTile = this.createPreviewTile(i); + container.appendChild(previewTile); } }, + createPreviewTile: function(tileNumber) { + var preview = document.createElement("li"); + var classname = "preview-tile"; + + if (index == tileNumber) { + classname += " selected"; + } + preview.className = classname; + + var canvasPreview = document.createElement("canvas"); + canvasPreview.className = "tile-view" + + canvasPreview.setAttribute('width', '128'); + canvasPreview.setAttribute('height', '128'); + canvasPreview.setAttribute('onclick', 'piskel.setFrame('+ tileNumber +')'); + + var canvasPreviewDuplicateAction = document.createElement("button"); + canvasPreviewDuplicateAction.className = "tile-action" + canvasPreviewDuplicateAction.innerHTML = "dup" + canvasPreviewDuplicateAction.setAttribute('onclick', 'piskel.duplicateFrame('+ tileNumber +')'); + + canvasPreview.getContext('2d').drawImage(frames[tileNumber], 0, 0, 320, 320, 0, 0 , 128, 128); + preview.appendChild(canvasPreview); + preview.appendChild(canvasPreviewDuplicateAction); + + if(frames.length > 1) { + var canvasPreviewDeleteAction = document.createElement("button"); + canvasPreviewDeleteAction.className = "tile-action" + canvasPreviewDeleteAction.innerHTML = "del" + canvasPreviewDeleteAction.setAttribute('onclick', 'piskel.removeFrame('+ tileNumber +')'); + preview.appendChild(canvasPreviewDeleteAction); + } + + return preview; + }, + refreshAnimatedPreview : function () { var context = $('animated-preview').getContext('2d'); // erase canvas, verify proper way @@ -64,6 +117,30 @@ this.createPreviews(); }, + removeFrame: function(frameIndex) { + index = frameIndex - 1 < 0 ? 0 : frameIndex - 1; + animIndex = 0; + frames.splice(frameIndex, 1); + $('canvas-container').innerHTML = ""; + $('canvas-container').appendChild(this.getCurrentCanvas()); + this.createPreviews(); + }, + + duplicateFrame: function(frameIndex) { + index = frameIndex + 1; + animIndex = 0; + var duplicateCanvas = frames[frameIndex].cloneNode(true); + // Copy canvas content: + var context = duplicateCanvas.getContext('2d'); + context.drawImage(frames[frameIndex], 0, 0); + + // Insert cloned node into frame collection: + frames.splice(frameIndex + 1, 0, duplicateCanvas); + $('canvas-container').innerHTML = ""; + $('canvas-container').appendChild(this.getCurrentCanvas()); + this.createPreviews(); + }, + updateCursorInfo : function (event) { var cursor = $('cursorInfo'); cursor.style.top = event.clientY + 10 + "px"; @@ -121,7 +198,7 @@ canvas.setAttribute('height', '320'); canvas.setAttribute('onmousemove', 'piskel.onCanvasMousemove(arguments[0])'); canvas.setAttribute('oncontextmenu', 'piskel.onCanvasContextMenu(arguments[0])'); - canvas.setAttribute('onclick', 'piskel.onCanvasClick(arguments[0])'); + //canvas.setAttribute('onclick', 'piskel.onCanvasClick(arguments[0])'); var context = canvas.getContext('2d'); context.fillStyle = "white"; @@ -131,6 +208,8 @@ context.drawImage(frames[index], 0, 0, 320, 320, 0, 0 , 320, 320); } + // TODO: We should probably store some metadata or enhance a domain object instead + // of the rendered view ? It will allow to decouple view and model and clean a bunch of code above. frames.push(canvas); this.setFrame(frames.length - 1); }