<!DOCTYPE html>
<html ng-app="app">
<head>
<link data-require="bootstrap-css@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<link rel="stylesheet" href="style.css" />
<script src="http://code.angularjs.org/1.2.26/angular.js"></script>
<!--ngDialog-->
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.7/css/ngDialog.min.css" />
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.7/css/ngDialog-theme-default.min.css" />
<script src="http://cdnjs.cloudflare.com/ajax/libs/ng-dialog/0.3.7/js/ngDialog.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div id="d" ng-controller="canvasCont">
<div class="row">
<!-- RIGHT COLUMN -->
<div class="toolbox well well-sm">
<h4>Tools</h4>
<span class="glyphicon glyphicon-sunglasses"></span> Filters
<span class="glyphicon glyphicon-erase"></span> Eraser
<span class="glyphicon glyphicon-move"></span> Moving
<span class="glyphicon glyphicon-tint"></span> Moving
<span class="glyphicon glyphicon-picture"></span> Import image
<span class="glyphicon glyphicon-font"></span> Add text
<span class="glyphicon glyphicon-cog"></span> Settings
</div>
<div class="col-md-3 col-sm-3">
<div class="toolbox well well-sm">
<h4>Colors</h4>
<div class="colorblock" ng-repeat="color in colorsArray" style="background:{{color}}" ng-click="selectColor(color)" ng-class="{'selected':color==selectedcolor}"></div>
<h4>Brushes</h4>
<div class="sizeblock" ng-repeat="size in sizesArray" style="width:{{size}}px;height:{{size}}px" ng-click="selectSize(size)" ng-class="{'selected':size==selectedsize}"></div>
</div>
</div>
<!-- CENTRAL ZONE -->
<div class="col-md-6 col-sm-6">
<div class="layer-box" style="width:{{canvasWidth}}px; height:{{canvasHeight}}px;">
<canvas ng-class="{active: (activeLayerIndex == layer.id), hidden : !layer.visible }" ng-repeat="layer in layers" layerid="layer.id" width="{{canvasWidth}}" height="{{canvasHeight}}" drawing=""></canvas>
</div>
</div>
<!-- LEFT COLUMN -->
<div class="col-md-3 col-sm-3">
<!--layers settings-->
<div class="controls well well-sm">
<h4>Layers <span class="badge">{{layers.length}}</span></h4>
<button ng-click="addLayer()" class="btn btn-primary">Add layer</button>
<ul class="list-group layer-list">
<li title="{{layer.id}}" class="list-group-item" ng-repeat="layer in layers track by $index" ng-click="selectThis(layer)" ng-class="{'layer-invisible': !layer.visible , 'layer-active':layer.id == activeLayerIndex}">
<button type="button" class="btn btn-default btn-xs" ng-click="removeThis(layer)"><span class="glyphicon glyphicon-remove"></span>
</button>
{{layer.name}}
<button type="button" class="btn btn-default btn-xs visibility-button" ng-show="layer.visible" ng-click="toggleThis(layer)"><span class="glyphicon glyphicon-eye-close"></span>
</button>
<button type="button" class="btn btn-default btn-xs visibility-button" ng-show="!layer.visible" ng-click="toggleThis(layer)"><span class="glyphicon glyphicon-eye-open"></span>
</button>
</li>
</ul>
</div>
</div>
</div>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Button with data-target
</button>
<div class="collapse" id="collapseExample">
<div class="well">
activeLayerIndex: {{activeLayerIndex}}
<br>
layers: {{layers | json}}
</div>
</div>
</div>
</body>
</html>
var app = angular.module("app", ['ngDialog']);
app.config(['ngDialogProvider', function (ngDialogProvider) {
ngDialogProvider.setDefaults({
className: 'ngdialog-theme-default',
plain: true,
showClose: true,
closeByDocument: true,
closeByEscape: true
});
}]);
app.constant('APP_PRESETS', {
'colors' : ['#000','#f00','#0f0','#00f','#fff', '#00FA9A', '#FFA500', '#FFFF00'],
'sizes' : [3,5,10,20],
'canvas' : {
'width' : 500,
'height': 200
},
'basicLayer' : {
"name": "untitled",
"id": 0,
"visible": true
}
});
app.controller("canvasCont", ['$scope', '$rootScope','ngDialog', 'APP_PRESETS',
function($scope, $rootScope, ngDialog, APP_PRESETS) {
$scope.selectedcolor = '#fff',
$scope.selectedsize = 10,
$scope.layers = [];
$scope.colorsArray = APP_PRESETS.colors;
$scope.sizesArray = APP_PRESETS.sizes;
$scope.canvasWidth = APP_PRESETS.canvas.width;
$scope.canvasHeight = APP_PRESETS.canvas.height;
$scope.selectColor = function(c) {
$scope.selectedcolor = c;
$rootScope.selectedcolor = c;
}
$scope.selectSize = function(s) {
$scope.selectedsize = s;
$rootScope.selectedsize = s;
}
/*
basic layer structure
*/
$scope.saveLayerName = function(newlayername){
if (newlayername.length < 2) {
$scope.newlayername_note = 'Too short layer name';
return false;
}
var newLyr = angular.extend({
"name": "untitled",
"id": 0,
"visible": true
}, {
"name": newlayername,
"id": Date.now().toString().substr(5),
"visible": true
});
$scope.layers.push(newLyr);
return true;
}
$scope.addLayer = function() {
ngDialog.open({
template: 'addLayertemplate.html',
scope: $scope,
plain: false
});
}
$scope.removeThis = function(lr) {
$scope.layers = $scope.layers.filter(function(item) {
return item.id != lr.id;
})
};
$scope.toggleThis = function(lr) {
lr.visible = !lr.visible;
}
$scope.selectThis = function(lr){
$scope.activeLayerIndex = lr.id;
$rootScope.activeLayerID = lr.id;
}
}])
app.directive("drawing", function($rootScope) {
return {
scope: {
sel: '=',
layerid : '='
},
restrict: "A",
link: function(scope, element, attrs) {
var ctx = element[0].getContext('2d');
// variable that decides if something should be drawn on mousemove
var drawing = false;
// the last coordinates before the current move
var lastX;
var lastY;
element.bind('mousedown', function(event) {
if ($rootScope.activeLayerID == scope.layerid) {
if (event.offsetX !== undefined) {
lastX = event.offsetX;
lastY = event.offsetY;
} else {
lastX = event.layerX - event.currentTarget.offsetLeft;
lastY = event.layerY - event.currentTarget.offsetTop;
}
// begins new line
ctx.beginPath();
drawing = true;
}
});
element.bind('mousemove', function(event) {
if ($rootScope.activeLayerID == scope.layerid) {
if (drawing) {
// get current mouse position
if (event.offsetX !== undefined) {
currentX = event.offsetX;
currentY = event.offsetY;
} else {
currentX = event.layerX - event.currentTarget.offsetLeft;
currentY = event.layerY - event.currentTarget.offsetTop;
}
draw(lastX, lastY, currentX, currentY);
// set current coordinates to last one
lastX = currentX;
lastY = currentY;
}
}
});
element.bind('mouseup', function(event) {
// stop drawing
drawing = false;
});
// canvas reset
function reset() {
element[0].width = element[0].width;
}
function draw(lX, lY, cX, cY) {
// line from
ctx.moveTo(lX, lY);
// to
ctx.lineTo(cX, cY);
// color
ctx.strokeStyle = $rootScope.selectedcolor;
ctx.lineWidth = $rootScope.selectedsize;
// draw it
ctx.stroke();
}
}
};
});
/*
function colorPicker(){
var img = new Image();
img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
img.onload = function() {
ctx.drawImage(img, 0, 0);
img.style.display = 'none';
};
var color = document.getElementById('color');
function pick(event) {
var x = event.layerX;
var y = event.layerY;
var pixel = ctx.getImageData(x, y, 1, 1);
var data = pixel.data;
var rgba = 'rgba(' + data[0] + ',' + data[1] +
',' + data[2] + ',' + data[3] + ')';
color.style.background = rgba;
color.textContent = rgba;
}
canvas.addEventListener('mousemove', pick);
}
*/
/* Styles go here */
body {
font-family: "Eau Naturelle", "Helvetica", "Arial", "Lucida Grande", "Gill Sans", "Verdana", sans-serif;
font-weight: 100;
color: #444;
background-color: #ddd;
}
#canvas {
border-bottom: 1px solid rgba(0, 0, 0, 0.3);
background-color: #FFF;
box-shadow: 0 9px 20px -5px rgba(0, 0, 0, 0.8);
}
h1 {
color: #444;
font-family: "Eau Naturelle", "Helvetica", "Arial", "Lucida Grande", "Gill Sans", "Verdana", sans-serif;
font-weight: 500;
}
a {
color: #4a9;
text-decoration: none;
font-style: italic;
font-weight: 800;
}
.colorblock, .sizeblock {
display:inline-block;
}
.colorblock {
width: 20px;
height: 20px;
cursor: pointer;
margin:2px;
border-radius:5px;
border: 2px solid transparent;
}
.sizeblock {
background: #000;
border-radius: 20px;
cursor: pointer;
margin: 2px;
}
.selected {
border: 2px solid cyan;
}
.visibility-button {
float:right;
}
.layer-box canvas{
position:absolute;
z-index:10;
}
.layer-box canvas.active{
z-index:100;
}
.layer-box canvas.hidden{
opacity:0;
}
.layer-active {
background: #0044cc;
color:#fff;
}
.layer-invisible .visibility-marker {
color: #f00;
}
# Simple AngularJS drawing directive
Now also works with FireFox!
<div class="dialog-contents">
<label>Layer name:</label>
<input type="text" ng-model="newlayername" />
<div class="note" ng-show="alertshow && newlayername.length<2">too short!</div>
<input type="button" value="OK" ng-click="alertshow = true && saveLayerName(newlayername) && closeThisDialog()" />
</div>