ng-img-crop.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. 'use strict';
  2. crop.directive('imgCrop', ['$timeout', 'cropHost', 'cropPubSub', function($timeout, CropHost, CropPubSub) {
  3. return {
  4. restrict: 'E',
  5. scope: {
  6. image: '=',
  7. resultImage: '=',
  8. changeOnFly: '=',
  9. areaType: '@',
  10. areaMinSize: '=',
  11. resultImageSize: '=',
  12. resultImageFormat: '@',
  13. resultImageQuality: '=',
  14. onChange: '&',
  15. onLoadBegin: '&',
  16. onLoadDone: '&',
  17. onLoadError: '&'
  18. },
  19. template: '<canvas></canvas>',
  20. controller: ['$scope', function($scope) {
  21. $scope.events = new CropPubSub();
  22. }],
  23. link: function(scope, element/*, attrs*/) {
  24. // Init Events Manager
  25. var events = scope.events;
  26. // Init Crop Host
  27. var cropHost=new CropHost(element.find('canvas'), {}, events);
  28. // Store Result Image to check if it's changed
  29. var storedResultImage;
  30. var updateResultImage=function(scope) {
  31. var resultImage=cropHost.getResultImageDataURI();
  32. if(storedResultImage!==resultImage) {
  33. storedResultImage=resultImage;
  34. if(angular.isDefined(scope.resultImage)) {
  35. scope.resultImage=resultImage;
  36. }
  37. scope.onChange({$dataURI: scope.resultImage});
  38. }
  39. };
  40. // Wrapper to safely exec functions within $apply on a running $digest cycle
  41. var fnSafeApply=function(fn) {
  42. return function(){
  43. $timeout(function(){
  44. scope.$apply(function(scope){
  45. fn(scope);
  46. });
  47. });
  48. };
  49. };
  50. // Setup CropHost Event Handlers
  51. events
  52. .on('load-start', fnSafeApply(function(scope){
  53. scope.onLoadBegin({});
  54. }))
  55. .on('load-done', fnSafeApply(function(scope){
  56. scope.onLoadDone({});
  57. }))
  58. .on('load-error', fnSafeApply(function(scope){
  59. scope.onLoadError({});
  60. }))
  61. .on('area-move area-resize', fnSafeApply(function(scope){
  62. if(!!scope.changeOnFly) {
  63. updateResultImage(scope);
  64. }
  65. }))
  66. .on('area-move-end area-resize-end image-updated', fnSafeApply(function(scope){
  67. updateResultImage(scope);
  68. }));
  69. // Sync CropHost with Directive's options
  70. scope.$watch('image',function(){
  71. cropHost.setNewImageSource(scope.image);
  72. });
  73. scope.$watch('areaType',function(){
  74. cropHost.setAreaType(scope.areaType);
  75. updateResultImage(scope);
  76. });
  77. scope.$watch('areaMinSize',function(){
  78. cropHost.setAreaMinSize(scope.areaMinSize);
  79. updateResultImage(scope);
  80. });
  81. scope.$watch('resultImageSize',function(){
  82. cropHost.setResultImageSize(scope.resultImageSize);
  83. updateResultImage(scope);
  84. });
  85. scope.$watch('resultImageFormat',function(){
  86. cropHost.setResultImageFormat(scope.resultImageFormat);
  87. updateResultImage(scope);
  88. });
  89. scope.$watch('resultImageQuality',function(){
  90. cropHost.setResultImageQuality(scope.resultImageQuality);
  91. updateResultImage(scope);
  92. });
  93. // Update CropHost dimensions when the directive element is resized
  94. scope.$watch(
  95. function () {
  96. return [element[0].clientWidth, element[0].clientHeight];
  97. },
  98. function (value) {
  99. cropHost.setMaxDimensions(value[0],value[1]);
  100. updateResultImage(scope);
  101. },
  102. true
  103. );
  104. // Destroy CropHost Instance when the directive is destroying
  105. scope.$on('$destroy', function(){
  106. cropHost.destroy();
  107. });
  108. }
  109. };
  110. }]);