I have a simple AngularJS / FabricJs application whose purpose is to allow moving / resizing an image before loading. There are essentially four steps:
1) I present a form with a canvas, and a rectangle inside of form to represent a clip area 2) browse for a local file 3) add it to the canvas 4) and have a button to capture the clip area inside of the canvas
The problem arises when I move the code from the directly embedded form and sit behind the angular directive. As soon as I moved the form to the directive, a problem arose, the image uploaded and added to the canvas without (any obvious) problems. However, as soon as you click somewhere on the canvas (for example, while trying to move the image), the added image no longer appears on the canvas (although checking the Canvas object still shows it as inside an array of objects).
JS app and helper:
var myApp = angular.module('myApp', []) // helper function to bind tot he on change of a input/file object (angularJs workaround) var invokeImageChange = function(that) { angular.element(that).scope().imageChange(that) angular.element(that).scope().$digest(); }
Controller:
var ImageCtrl = function($scope) { var desiredHeight = 300 var desiredWidth = 770 // I understand this docucment.gelElementById is not the angular way - and needs to be changed var myImageData = document.getElementById('fileData') var myImage = document.getElementById('myImage') var canvas = new fabric.Canvas('myCanvas') var rect = new fabric.Rect({ fill: 'lightgray', left: canvas.width / 2, top: canvas.height / 2, width: desiredWidth, height: desiredHeight, stroke: 'darkgray', strokeDashArray: [5, 5], selectable: false }); canvas.add(rect) var clipZone = { y: rect.top - (.5 * rect.height), x: rect.left - (.5 * rect.width), width: desiredWidth, height: desiredHeight, quality: 1 } $scope.caption = "" ; $scope.fileUrl = "" ; $scope.imageChange = function(inp) { console.log('imageChange') file = inp.files[0]; fr = new FileReader(); fr.onload = createImage; fr.readAsDataURL(file); var img = null function createImage() { console.log('createImage') img = new Image(); img.onload = imageLoaded; img.src = fr.result; } function imageLoaded() { console.log('imageLoaded') var fabImg = new fabric.Image(img) fabImg.scale(1.0).set({ left: canvas.width / 2, top: canvas.height / 2 }); canvas.add(fabImg) canvas.setActiveObject(fabImg) } } $scope.submit = function(event) { } $scope.capture = function() { console.log('capture') } }
Directive Code:
myApp.directive('ngImageEditor', function() { return { restrict: 'E', transclude: true, replace: true, controller: 'ImageCtrl', templateUrl: '\blah\pathToForm' }; });
where TemplateUrl refers to this form
<form name="uploadForm" ng-controller="ImageCtrl" method="post" enctype="multipart/form-data" action="/main/update" ng-submit="submit()"> <div class="control-group"> <label class="control-label" for="file">Image File</label> <div class="controls"> <input type="file" name="file" ng-model="file" onchange="invokeImageChange(this)"/> <input type="text" id="fileData" name="fileData" ng-model="fileUrl"/> </div> </div> <div class="control-group"> <div class="controls"> <input type="button" value="Upload" ng-click="capture()"/> </div> </div> <div> <canvas id="myCanvas" width="800" height="400" style="border:1px solid #000000;"></canvas> </div> <img id="myImage" style="border: 1px solid burlywood"> </form>
Hope the JsFiddle below will help people understand what I'm talking about. Thanks in advance!
Play
1) browse to an image 2) move the image (notice the image disappears in the second link)
Work (image can be moved) (without directive):
http://jsfiddle.net/PNwbp/1/
Broken / Issues (image disappears when moved) (with directive):
http://jsfiddle.net/faFVW/23/