Example #1
0
    init: function() {

        // wait until domready to require leaflet
        L = require('leaflet');

        this.identifier = utils.getUniqueId();
        var markup = template({identifier: this.identifier});
        this.$el = $(this.selector).first();
        this.$el.append(markup);
        this.render();
    },
LineStreaming.prototype._init = function() {

    var data = this.data;
    var height = this.height;
    var width = this.width;
    var opts = this.opts;
    var selector = this.selector;
    var self = this;

    var series = data.series;

    var tip;

    if(this.opts.tooltips) {
        var format = d3.format('.02f');
        tip = d3.tip()
            .attr('class', 'd3-tip')
            .html(function(d, i) {
                return 'Series: ' + d.i;
            });
    }

    var defaultSize = 6;

    this.size = data.size ? data.size : _.fill(_.range(series.length), defaultSize)

    var yDomain = nestedExtent(series.map(function(d) {return d.d}), function(d) {
        return d.y;
    });
    var xDomain = nestedExtent(series.map(function(d) {return d.d}), function(d) {
        return d.x;
    });

    var ySpread = Math.abs(yDomain[1] - yDomain[0]) || 1;
    var xSpread = Math.abs(xDomain[1] - xDomain[0]) || 1;

    this.x = d3.scale.linear()
        .domain([xDomain[0] - 0.05 * xSpread, xDomain[1] + 0.05 * xSpread])
        .range([0, width]);

    this.y = d3.scale.linear()
        .domain([yDomain[0] - 0.1 * ySpread, yDomain[1] + 0.1 * ySpread])
        .range([height, 0]);

    this.line = d3.svg.line()
        .x(function (d, i) {
            return self.x(d.x);
        })
        .y(function (d, i) {
            return self.y(d.y);
        })

    this.zoom = d3.behavior.zoom()
        .x(this.x)
        .y(this.y)
        .on('zoom', zoomed);

    var svg = d3.select(selector)
        .append('svg:svg')
        .attr('class', 'line-plot')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom)
        .append('svg:g')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')

    if(this.opts.tooltips) {
        svg.call(tip);
    }

    svg.append('svg:rect')
        .attr('width', width)
        .attr('height', height)
        .attr('class', 'plot');


    var makeXAxis = function () {
        return d3.svg.axis()
            .scale(self.x)
            .orient('bottom')
            .ticks(5);
    };

    var makeYAxis = function () {
        return d3.svg.axis()
            .scale(self.y)
            .orient('left')
            .ticks(5);
    };

    this.xAxis = d3.svg.axis()
        .scale(this.x)
        .orient('bottom')
        .ticks(5);

    svg.append('svg:g')
        .attr('class', 'x axis')
        .attr('transform', 'translate(0, ' + height + ')')
        .call(this.xAxis);

    this.yAxis = d3.svg.axis()
        .scale(this.y)
        .orient('left')
        .ticks(5);

    svg.append('g')
        .attr('class', 'y axis')
        .call(this.yAxis);

    svg.append('g')
        .attr('class', 'x grid')
        .attr('transform', 'translate(0,' + height + ')')
        .call(makeXAxis()
                .tickSize(-height, 0, 0)
                .tickFormat(''));

    svg.append('g')
        .attr('class', 'y grid')
        .call(makeYAxis()
                .tickSize(-width, 0, 0)
                .tickFormat(''));

    var clipId = utils.getUniqueId();
    var clip = svg.append('svg:clipPath')
        .attr('id', clipId)
        .append('svg:rect')
        .attr('x', 0)
        .attr('y', 0)
        .attr('width', width)
        .attr('height', height);

    var chartBody = svg.append('g')
        .attr('clip-path', 'url(#' + clipId + ')');

    var toggleOpacity = 0;

    if(_.has(this.data, 'xaxis')) {
        var txt = this.data.xaxis;
        if(_.isArray(txt)) {
            txt = txt[0];
        }
        svg.append("text")
            .attr("class", "x label")
            .attr("text-anchor", "middle")
            .attr("x", width / 2)
            .attr("y", height + margin.bottom - 10)
            .text(txt);
    }
    if(_.has(this.data, 'yaxis')) {
        var txt = this.data.yaxis;
        if(_.isArray(txt)) {
            txt = txt[0];
        }

        svg.append("text")
            .attr("class", "y label")
            .attr("text-anchor", "middle")
            .attr("transform", "rotate(-90)")
            .attr("x", - height / 2)
            .attr("y", -40)
            .text(txt);
    }


    var path = chartBody.selectAll('.line')
        .data(series)
        .enter()
        .append('path')
        .attr('class', 'line')
        .attr('stroke', function(d) {return d.c})
        .style('stroke-width', function(d) {return d.s ? d.s : defaultSize})
        .style('stroke-opacity', 0.9)
        .attr('d', function(d) { return self.line(d.d)})

    function updateAxis() {

        self.svg.select('.x.axis').transition().duration(500).ease('linear').call(self.xAxis);
        self.svg.select('.y.axis').transition().duration(500).ease('linear').call(self.yAxis);
        self.svg.select('.x.grid')
            .transition().duration(500).ease('linear')
            .call(makeXAxis()
                .tickSize(-height, 0, 0)
                .tickFormat(''));
        self.svg.select('.y.grid')
            .transition().duration(500).ease('linear')
            .call(makeYAxis()
                    .tickSize(-width, 0, 0)
                    .tickFormat(''));
    }

    function zoomed() {

        updateAxis();
        self.svg.selectAll('.line')
            .attr('class', 'line')
            .attr('d', function(d) { return self.line(d.d)});
    }

    this.defaultSize = defaultSize;
    this.svg = svg;
    this.zoomed = zoomed;
    this.updateAxis = updateAxis;
    this.series = series;
    this.path = path;
    this.defaultSize = defaultSize;
    this.xTick = xDomain[1] + 1

}
ImgPoly.prototype._init = function() {

    var opts = this.opts;
    var data = this.data ? this.data : {};
    var images = this.images;
    var selector = this.selector;
    var self = this;

    this.mid = utils.getUniqueId();
    this.markup = '<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.css"/><div id="image-map-' + this.mid + '" class="image-map"></div>';

    var image = images[0];
    var coords = [];

    this.$el = $(selector).first();
    this.$el.append(this.markup);

    var maxWidth = this.$el.width();

    // create an image so we can get aspect ratio
    this.img = new Image();
    var img = this.img;
    img.src = utils.cleanImageURL(image);
    var COLOR_MODES;

    img.onload = function() {

        // get image dimensions
        var imw = img.width;
        var imh = img.height;

        // use image dimensions to set css
        var w = maxWidth,
            h = maxWidth * (imh / imw);

        self.$el.find('#image-map-' + self.mid).width(w).height(h);

        //create the map
        if(self.map) {
            self.map.remove();    
        }
        self.map = L.map('image-map-' + self.mid, {
            minZoom: 1,
            maxZoom: 8,
            center: [w/2, h/2],
            zoom: 1,
            attributionControl: false,
            zoomControl: false,
            crs: L.CRS.Simple,
        });
        
        var map = self.map;
             
        // calculate the edges of the image, in coordinate space
        var southWest = map.unproject([0, h], 1);
        var northEast = map.unproject([w, 0], 1);
        var bounds = new L.LatLngBounds(southWest, northEast);
         
        // add the image overlay to cover the map
        var overlay = L.imageOverlay(img.src, bounds);
        map.addLayer(overlay)
         
        // tell leaflet that the map is exactly as big as the image
        map.setMaxBounds(bounds);

        // add free drawing
        var freeDraw = new L.FreeDraw({
          mode: L.FreeDraw.MODES.CREATE | L.FreeDraw.MODES.DELETE | L.FreeDraw.MODES.DELETE,
        });

        // set free drawing options
        freeDraw.options.attemptMerge = false;
        freeDraw.options.setHullAlgorithm('brian3kb/graham_scan_js');
        freeDraw.options.setSmoothFactor(0);
        
        // add the free drawing layer
        map.addLayer(freeDraw);

        // initialize with any polygons from the data
        if (!_.isEmpty(data)) {

            var polygons = data.polygons;

            polygons = polygons.map(function (g) {
                var converted = [];
                g.map(function (p) {
                    var newp = new L.point(p[0] / (imw / w), p[1] / (imh / h), false);
                    var newpoint = map.unproject(newp, 1);
                    converted.push(newpoint);
                });
                return converted;
            });

            freeDraw.options.simplifyPolygon = false;
            polygons.forEach(function (g) {
                freeDraw.createPolygon(g, true);
            });
            freeDraw.options.simplifyPolygon = true;

            COLOR_MODES = ['white', 'bright', 'data-white'];
            var colorIndex = 2;

            getUserData()

        } else {

            COLOR_MODES = ['white', 'bright'];
            var colorIndex = 0;

        }

        d3.select(self.$el[0]).on('keydown', keydown).on('keyup', keyup);

        updateStyles();

        function updateStyles() {

            var c;
            if(COLOR_MODES[colorIndex].indexOf('white') > -1) {
                c = d3.hsl('rgb(255,255,255)');
            } else if (COLOR_MODES[colorIndex].indexOf('bright') > -1) {
                c = d3.hsl('rgb(240,30,110)');
            }

            var isData = (data.color && COLOR_MODES[colorIndex].indexOf('data') > -1);

            d3.select(self.$el[0])
               .selectAll('.image-map g path.leaflet-freedraw-polygon')
               .style('stroke', function(d, i) {
                if(isData && i < data.color.length) {
                    return data.color[i];
                }
                return c;
               })
               .style('fill', function(d, i) {
                var fill;
                if(isData && i < data.color.length) {
                    fill = d3.hsl(data.color[i]);
                } else {
                    fill = c;
                }
                return fill.brighter(1.2).toString();
               }); 

        }


        var mod = function(x, n) {
            return ((x%n)+n)%n;
        };
        function keydown() {
            if (d3.event.altKey) {
                freeDraw.setMode(L.FreeDraw.MODES.EDIT);
            }
            if (d3.event.metaKey | d3.event.shiftKey) {
                freeDraw.setMode(L.FreeDraw.MODES.VIEW);
            }
            if (d3.event.shiftKey & (d3.event.keyCode == 37 | d3.event.keyCode == 39)) {
                d3.event.preventDefault();
                if (d3.event.keyCode == 37) {
                    colorIndex = mod(colorIndex - 1, COLOR_MODES.length);
                }
                if (d3.event.keyCode == 39) {
                    colorIndex = mod(colorIndex + 1, COLOR_MODES.length);
                }
                updateStyles();
            }
        }

        function keyup() {
            freeDraw.setMode(L.FreeDraw.MODES.CREATE | L.FreeDraw.MODES.DELETE)
        }

        self.emit('image:loaded');

        function getUserData() {
            // extract coordinates from regions
            var n = freeDraw.memory.states.length;
            var coords = freeDraw.memory.states[n-1].map( function(d) {
                var points = [];
                d.forEach(function (p) {
                    var newpoint = map.project(p, 1);
                    newpoint.x *= (imw / w);
                    newpoint.y *= (imh / h);
                    points.push([newpoint.x, newpoint.y]);
                });
                return points;
            });

            utils.sendCommMessage(self, 'selection', coords);
            utils.updateSettings(self, {
                coords: coords
            }, function(err) {
                if(err) {
                    console.log('err saving user data');
                    console.log(err);
                }
            });
        }

        self.$el.unbind().click(function() {
            getUserData()
        });

        utils.getSettings(self, function(err, settings) {
            if(!err) {
                coords = settings.coords;
            }
        });
        
        freeDraw.on('markers', updateStyles);
        freeDraw.on('destroy', function(d) {

            var i = d.index;
            
            if(data.color && _.isArray(data.color)) {
                data.color.splice(i, 1);    

                if(data.color.length === 0) {
                    colorIndex = 0;
                    COLOR_MODES = ['white', 'bright'];
                }
            }

            getUserData()
            updateStyles()
        })
        
        self.map = map
        self.bounds = bounds
        self.overlay = overlay
        
    }

};