Skip to content

Instantly share code, notes, and snippets.

@wboykinm
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wboykinm/9144571 to your computer and use it in GitHub Desktop.
Save wboykinm/9144571 to your computer and use it in GitHub Desktop.
map.js, still perched between angular and jquery dependencies
var mapModule = angular.module('mapModule', []);
mapModule.controller('mapCtrl', ['$scope', function($scope){
//do nothing
}]);
mapModule.directive('map', function(){
var mobile = (window.devicePixelRatio > 1);
var desktopMapId = "faraday2.hb90naie";
var mobileMapId = "landplanner.hajfpk7a";
var desktopRefId = "faraday2.hb927i5h";
var mobileRefId = "faraday2.hb92k1l3";
var currentMapId = (mobile) ? mobileMapId : desktopMapId;
var currentRefId = (mobile) ? mobileRefId : desktopRefId;
return {
restrict: 'E',
link: function(scope, element, attrs){
// Build map, set baselayers
var map = L.mapbox.map(element[0], currentMapId, {
detectRetina: true,
zoomControl: false //take away the zoom controls on the top left
});
map.setView([43.073, -89.401], 11);
if (!mobile) {
//add zoom controls on the top right if we're not on mobile
new L.Control.Zoom({ position: 'topright' }).addTo(map);
}
// Adding choropleth tiles here, visible to zoom 14
cartodb.createLayer(map, {
user_name: 'faraday',
type: 'cartodb',
cartodb_logo: false,
sublayers: [{
sql: "SELECT * FROM dane_county_tracts",
cartocss: "#table_name [zoom<14][aland>0]{polygon-opacity: 0.8;line-color: #FFF;line-width: 0;line-opacity: 0;[mean_hh_inc <= 86839]{polygon-fill: #333333;}[mean_hh_inc <= 77010]{polygon-fill: #3c4745;}[mean_hh_inc <= 66569]{polygon-fill: #465b56;}[mean_hh_inc <= 53669]{polygon-fill: #537165;}[mean_hh_inc <= 45069]{polygon-fill: #658672;}[mean_hh_inc <= 38652]{polygon-fill: #7d9b7a;}[mean_hh_inc <= 34652]{polygon-fill: #99af7d;}[mean_hh_inc <= 29881]{polygon-fill: #bdc277;}[mean_hh_inc <= 11409]{polygon-fill: #e9d362;}}"
}]
}).addTo(map)
// ADD THE REFERENCE OVERLAY (THE TOP OF THE SANDWICH) HERE:
var topPane = map._createPane('leaflet-top-pane', map.getPanes().mapPane);
var topLayer = new L.mapbox.tileLayer(currentRefId).addTo(map);
topPane.appendChild(topLayer.getContainer());
topLayer.setZIndex(7);
////////Playing with d3 fire //////////
function addMask(svg, prefix, x, y, offset) {
var gradient = svg.append('defs')
.append('linearGradient')
.attr('id', prefix + 'Gradient')
.attr('gradientUnits', 'objectBoundingBox')
.attr('x2', x)
.attr('y2', y)
gradient.append('stop')
.attr('offset', offset)
.attr('stop-color', 'white')
.attr('stop-opacity', 1)
gradient.append('stop')
.attr('offset', offset + 0.1)
.attr('stop-color', 'white')
.attr('stop-opacity', 0)
var mask = svg.select('defs')
.append('mask')
.attr('id', prefix + 'Mask')
.attr('maskUnits', 'objectBoundingBox')
.attr('maskContentUnits', 'objectBoundingBox')
.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', 1)
.attr('height', 1)
.attr('fill', 'url(#' + prefix + 'Gradient)')
}
function timeStampSort(a, b) {
var a = new Date(a.timestamp),
b = new Date(b.timestamp)
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
// feed
(function() {
var radius = 20;
var margin = {top: 0 + radius, right: 0, bottom: 50, left: 0},
width = radius * 2 - margin.left - margin.right,
height = 1000 - margin.top - margin.bottom;
d3.csv("../data/responses.csv", null, function(error, data) {
var responseData = data.slice(0,numResponses).sort(timeStampSort).reverse();
var y = d3.time.scale()
.domain(d3.extent(responseData, function(response) { return new Date(response.timestamp); }))
.range([height, 0]);
var yAxis = d3.svg.axis()
.scale(y)
.tickPadding(50)
.tickFormat(d3.time.format('%B %Y'))
.orient("left");
var svg = d3.select("#feed")
.attr('width', radius * 2)
.attr('viewBox', '0 0 ' + width + ' ' + height)
.attr('preserveAspectRatio', "xMidYMin")
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
addMask(svg, 'feed', 0, 1, 0.7)
svg.attr('mask', 'url(#feedMask)')
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (width - radius) + ", 0)")
.call(yAxis)
var responses = svg.selectAll("g.response")
.data(responseData)
var response = responses.enter().append('g').attr('class', 'response')
response.append("circle")
.attr("class", "dot")
.attr("r", radius)
.attr("cx", width - radius - margin.right)
.attr("cy", function(d,i) {
var prev = $(this).parent().prev('.response');
if (prev.length > 0) {
var prevBottom = prev[0].getBBox().y + prev[0].getBBox().height;
return d3.max([prevBottom + radius, y(new Date(d.timestamp))])
} else {
return y(new Date(d.timestamp));
}
})
.on("mouseover", function(d) {
var bubble = document.querySelector('#feedBubble');
bubble.find('.person').text(d.name);
bubble.find('.channel').text(d.channel);
bubble.find('.time').attr('title', d.timestamp).timeago('updateFromDOM');
var box = this.getBoundingClientRect();
var top = Math.round(box.top + box.height / 2 - bubble.outerHeight() / 2);
var left = Math.round(box.left - bubble.outerWidth() - 8);
bubble.css({top: top + 'px', left: left + 'px'});
bubble.show();
})
.on("mouseout", function() {
document.querySelector('#feedBubble').hide();
})
response.append("text")
.attr("class", "icon")
.text(function(d) { return channelData.filter(function(channel) { return channel.nickname == d.channel })[0].icon })
.attr("x", width - radius)
.attr("y", function(d) { return $(this).prev('.dot').first().attr('cy'); })
.attr('dy', radius / 4)
});
})();
// campaigns
(function() {
var radius = 20;
var margin = {top: radius, right: 10, bottom: radius, left: 10},
width = 1000 - margin.right - margin.left,
height = radius * 4 - margin.top - margin.bottom;
d3.csv("../data/campaigns.csv", null, function(error, data) {
var campaignData = data.slice(0,numCampaigns).sort(timeStampSort);
var x = d3.time.scale()
.domain(d3.extent(campaignData, function(campaign) { return new Date(campaign.timestamp); }))
.range([0, width]);
var xAxis = d3.svg.axis()
.scale(x)
.tickPadding(50)
.tickFormat(d3.time.format('%B %Y'))
.orient("top");
var svg = d3.select("#timeline")
.attr('height', radius * 2 + 10)
.attr('viewBox', '0 0 ' + width + ' ' + height)
.attr('preserveAspectRatio', "xMinYMid")
.append("g")
.attr("transform", "translate(" + (margin.left + radius) + "," + margin.top + ")");
addMask(svg, 'timeline', 1, 0, 0.75)
svg.attr('mask', 'url(#timelineMask)')
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0, " + (height - margin.bottom - radius) + ")")
.call(xAxis)
var campaigns = svg.selectAll("g.campaign")
.data(campaignData)
var campaign = campaigns.enter().append('g').attr('class', 'campaign')
campaign.append("circle")
.attr("class", "dot")
.attr("r", radius)
.attr("cy", height - radius - margin.bottom)
.attr("cx", function(d,i) {
var prev = $(this).parent().prev('.campaign');
if (prev.length > 0) {
var prevRight = prev[0].getBBox().x + prev[0].getBBox().width;
return d3.max([prevRight + radius, x(new Date(d.timestamp))])
} else {
return x(new Date(d.timestamp));
}
})
.on("mouseover", function(d) {
var bubble = document.querySelector('#campaignBubble');
bubble.find('.name').text(d.name);
bubble.find('.size').text(d.size);
bubble.find('.channel').text(d.channel);
bubble.find('.time').attr('title', d.timestamp).timeago('updateFromDOM');
var box = this.getBoundingClientRect();
var top = Math.round(box.top - bubble.outerHeight() - 12);
var left = Math.round(box.left + box.width / 2 - bubble.outerWidth() / 2);
bubble.css({top: top + 'px', left: left + 'px'});
bubble.removeClass("left center right")
if (left < 0) {
bubble.css({ left: Math.round(box.left + box.width / 2 - 12.5) + 'px' })
bubble.addClass("left");
} else if (left + bubble.outerWidth() > $(window).width()) {
bubble.addClass("right");
bubble.css({ left: Math.round(box.left + box.width / 2 - bubble.outerWidth() + 12.5) + 'px' })
} else
bubble.addClass("center");
bubble.show();
})
.on("mouseout", function() {
document.querySelector('#campaignBubble').hide();
})
campaign.append("text")
.attr("class", "icon")
.text(function(d) { return channelData.filter(function(channel) { return channel.nickname == d.channel })[0].icon })
.attr("y", height - margin.bottom - radius)
.attr("x", function(d) { return $(this).prev('.dot').first().attr('cx'); })
.attr('dx', 1)
.attr('dy', radius / 4)
});
})();
});
}
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment