0

I have a new project based on construction. Here we will have huge image sets of building architecture and engineering diagrams.

This is my small plunker link attempt trying to do so.

I do not know if this is possible, I want to click on different section of image, create tag and have comment thread based on those tags.

May someone help me to get the popover just next to cursor where mouse is clicked on top of image. Tags created will be for that section and next time any user wants to preview can mouse over to the image and see tags as tool-tips then follow the comment thread for that tag.

I have tried with angular but Jquery or any other js framework is fine as long as it works.

<body ng-controller="MainCtrl">
<br>
<div class='container-fluid'>
  <div class='alert alert-info'>
    <h4>Click the image and tag</h4>
  </div>
  <div class='row'>
    <div class='col-lg-11'>
      <div class='col-sm-11 ' >
        <img tagover src='http://www.studioats.com/wp-content/uploads/2011/05/A2-1A-First-Floor-Plan-Area-A-12x18.jpg' height='300' width='500' />
      </div>  
      <div class='col-sm-3 well'  >
        <p><span class='label label-info'>Comments</span>&nbsp;{{tagName}}</p>
        <textarea class='form-control' placeholder='comments here'></textarea>
      </div>    
    </div>
  </div>
</div>

Script

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {  

});


app.directive('tagover', function ($compile,$templateCache,$interpolate) {
var getTemplate = function (contentType,attrs) {
    var template = '';
    switch (contentType) {
        case 'comment':
            var template  = "<div class='' >";
                template += "<input class='form-control' type='text' ng-model='tagName' placeholder='tag name'>";
                template += "</div>";
                template += "</div>";
            break;
    }
    return template;
} //

return {
    restrict: "A",
    link: function (scope, element, attrs) {
        var popOverContent;
        var d = new Date();
        var mm = d.getMonth()+1;

        popOverContent = getTemplate("comment",attrs);
        var compiled = $compile(popOverContent)(scope);

        var options = {
            content: compiled,
            placement: "bottom",
            html: true,
            date: scope.date
        };
        $(element).popover(options);
    }
};
});
  • I think firstly you should plan carefully how you are going to do this, please take a look at this question and you will have general idea how it is going to be built: "http://stackoverflow.com/questions/6832964/interactive-floor-plans-in-html5" – Shota Aug 24 '15 at 21:21
  • Hi @Shota Thanks for sharing your concern. First thing your flash based sample do not work. Second we have different concept. You want to display already available data onMouseover, I want to gather data for each section of image from user. – Aashis Binod Khanal Aug 25 '15 at 16:53

1 Answers1

3

I think that's easier to do with angular-leaflet-directive. Leaflet is a mapping tool where you can add your image as overlay and you can add your marker/tags as you need it. The positions are stored as geo coordinates (longitude/latitude) but I think that's OK. If you need to have the positions in pixels you could calculated them but I think you don't need that.

Below I've hacked a short demo for you or at this fiddle.

Right after the leaflet-directive I've added the tagNames scope variable for debugging.

Things that should be improved for your app:

  • Add markers to a service so you can store them in localstorage or a database
  • Sometimes there is an error in the console TypeError: t.className is undefined not sure what it is, it happens randomly during paning the map.
  • Check if the max. bounds of the map is correct. I haven't checked that it's copied from a demo code.
  • Check if you need mouseout for the markers. I've commented it so you can click at the input for the tag name.
  • Read how tiling images is working then you can split one high resolution image into many tiles and you'll get a better user experience but for starting you can work with one image and add the tiles later.
  • Check if you need layers (e.g. first floor or second floor). I think that could be added to the leaflet but then you need to check if you have to add a visibility attribute to your markers (if that's not handled by leaflet).

angular.module("taggingApp", ["leaflet-directive"])
.controller('tagController', TagController);

//string.format helper
String.prototype.format = function() {
    var formatted = this;
    for (var i = 0; i < arguments.length; i++) {
        var regexp = new RegExp('\\{'+i+'\\}', 'gi');
        formatted = formatted.replace(regexp, arguments[i]);
    }
    return formatted;
};

function TagController($scope, $compile, $log, $timeout, leafletData, leafletBoundsHelpers) {
    var markerCount = 0;
    var html = '<div>Please add tag name: <input ng-model="tagNames.m{0}"/><button ng-click="remove(\'m{0}\')">remove tag</button></div>marker key: m{0}'; //.format(markerCount); //template for marker
    
    // image size = 1.296px × 864px
    var maxBounds = leafletBoundsHelpers.createBoundsFromArray([[-540, -960], [540, 960]]);
    angular.extend($scope, {
        tagNames: {
         m0: 'first tag'
        }, // tagnames
        defaults: {
          scrollWheelZoom: false,
          crs: 'Simple',
          maxZoom: 2
        },
        
        markers: {
            m0: {
                lat: 33,
                lng: 4,
                //message: "I'm a static marker - m" + markerCount,
             message: html.format(markerCount++),
                getMessageScope: function() { return $scope;},
                icon: {},
            }
        },
        center: {
            lat: 0,
            lng: 0,
            zoom: 0
        },
        maxBounds: maxBounds,
        layers: {
            baselayers: {
                home: {
                    name: 'home',
                    type: 'imageOverlay',
                    url: 'http://www.studioats.com/wp-content/uploads/2011/05/A2-1A-First-Floor-Plan-Area-A-12x18.jpg',
                    bounds: [[-540, -960], [540, 960]],
                    layerParams: {
                      noWrap: true,
                      attribution: 'demo tile...'
                    }
                }
            }
        }
    });
    
    $scope.$on('leafletDirectiveMarker.mouseover', function(e, args) {
        args.leafletEvent.target.openPopup();
 });
    
    /*$scope.$on('leafletDirectiveMarker.mouseout', function(e, args) {
        args.leafletEvent.target.closePopup();
 });*/
    
    $scope.remove = function(markerName) {
        console.log(markerName, $scope.markers);
     // remove marker
        
        if ( $scope.tagNames && $scope.tagNames[markerName] ) 
            delete $scope.tagNames[markerName];
        
        delete $scope.markers[markerName];
        markerCount-- < 0 ? 0: markerCount;
        console.log(markerCount);
    };
    
    $scope.$on('leafletDirectiveMap.click', function(scope, e) {
     //console.log(e, pos);
        var lat = e.leafletEvent.latlng.lat,
            lng = e.leafletEvent.latlng.lng;
        //alert("Lat, Lon : " + e.leafletEvent.latlng.lat + ", " + e.leafletEvent.latlng.lng)
        
        $scope.markers['m'+(++markerCount)] = {
                lat: lat,
                lng: lng,
                //message: "I'm a static marker - m" + markerCount,
             message: html.format(markerCount),
                getMessageScope: function() { return $scope;},
                icon: {},
            };
        
        
 });
}
<link href="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.4/angular.js"></script>
<script src="http://tombatossals.github.io/angular-leaflet-directive/dist/angular-leaflet-directive.min.js"></script>
<script src="http://cdn.leafletjs.com/leaflet-0.7.1/leaflet.js"></script>
<div ng-app="taggingApp" ng-controller="tagController">
<leaflet width="500px" height="500px" center="center" layers="layers" defaults="defaults" markers="markers"></leaflet>
    {{tagNames | json}}
</div>
AWolf
  • 8,770
  • 5
  • 33
  • 39
  • I'd like to add that there's a very good [example page](http://tombatossals.github.io/angular-leaflet-directive/examples/0000-viewer.html#/basic/first-example) for angular-leaflet there you can browse many examples. – AWolf Aug 24 '15 at 23:24
  • Thank you for the great idea. Definitely I should work. Will come back to you for any difficulties. – Aashis Binod Khanal Aug 25 '15 at 16:03