wrongmove/immoweb/script.js
2025-05-26 19:41:36 +00:00

170 lines
5.2 KiB
JavaScript

// rivet
var filter = {city:'London', country:null, mode:'qmprice'};
filter['countries'] = Array.from(new Set(data.features.map(function(d){return d['properties']['country']})));
rivets.bind(document.getElementById('overlay'), {filter: filter});
function clone(d){
return JSON.parse(JSON.stringify(d));
}
function percentile(arr, p) {
if (arr.length === 0) return 0;
if (typeof p !== 'number') throw new TypeError('p must be a number');
if (p <= 0) return arr[0];
if (p >= 1) return arr[arr.length - 1];
var index = arr.length * p,
lower = Math.floor(index),
upper = lower + 1,
weight = index % 1;
if (upper >= arr.length) return arr[lower];
return arr[lower] * (1 - weight) + arr[upper] * weight;
}
function update(){
// close overlay
var modal = document.getElementById('modal_overlay');
modal.classList.toggle('modal-open');
// init heatmap
heatmap = new HexgridHeatmap(map, "hexgrid-heatmap", "waterway-label");
heatmap.setIntensity(6); // dunno yet
heatmap.setSpread(0.15); // dunno yet
heatmap.setCellDensity(0.5); // small value == bigger hexagons
heatmap.setPropertyName(filter.mode);
// set filter
if(filter.city){
cityDim.filterExact(filter.city);
} else if(filter.country){
countryDim.filterExact(filter.country);
}else{
alert('nothing loadable');
}
filter.count = cityDim.top(Infinity).length;
var subset = {"type": "FeatureCollection", "features": []};
indexDim.top(Infinity).forEach(function(i){
subset.features.push(data.features[i.index]);
});
loadData(subset);
}
function loadData(subset){
heatmap.setData(subset);
var values = subset.features.map(function(d){return d['properties'][filter.mode]});
values = values.sort(function(a,b){return a-b;});
// setting the color stops, min is at 5th percentile, max at 95percentile
var min = values[Math.round(values.length * 0.05)];
var max = values[Math.round(values.length * 0.95)];
var colorStopsPerc = [
[0, "rgba(0,185,243,0)"],
[25, "rgba(0,185,243,0.24)"],
[60, "rgba(255,223,0,0.3)"],
[100, "rgba(255,105,0,0.3)"],
];
makeLegend(colorStopsPerc, min, max);
var colorStopsValue = colorStopsPerc.map(function(d){
return [min + d[0]*(max-min)/100, d[1]];
});
heatmap.setColorStops(colorStopsValue);
heatmap.update();
//get bounding box and zoom to that area
// we use a 1% percentile since some data can be corrupt
var longitudes = subset.features.map(function(d){return d.geometry.coordinates[0];}).sort(function(a,b){return a-b;});
var latitudes = subset.features.map(function(d){return d.geometry.coordinates[1];}).sort(function(a,b){return a-b;});
var minlng = percentile(longitudes, 0.01);
var maxlng = percentile(longitudes, 0.99);
var minlat = percentile(latitudes, 0.01);
var maxlat = percentile(latitudes, 0.99);
map.fitBounds([
[minlng, minlat],
[maxlng, maxlat]
]);
}
mapboxgl.accessToken = 'pk.eyJ1IjoiZGktdG8iLCJhIjoiY2o0bnBoYXcxMW1mNzJ3bDhmc2xiNWttaiJ9.ZccatVk_4shzoAsEUXXecA';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
center: [13.38032, 49.994210],
zoom: 5
});
map.on("load", function(){
var crossData = data.features.map(function(d, i){
//clone properties
var props = clone(d['properties']);
props['index'] = i;
return props;
});
cf = crossfilter(crossData);
qmDim = cf.dimension(function(d){return d.qm;});
cityDim = cf.dimension(function(d){return d.city;});
countryDim = cf.dimension(function(d){return d.country;});
rentDim = cf.dimension(function(d){return d.total_price;});
roomsDim = cf.dimension(function(d){return d.rooms;});
indexDim = cf.dimension(function(d){return d.index;});
});
// map.addInteraction('my-polygon-click-interaction', {
// type: 'click',
// target: 'polygons',
// handler: (e) => {
// console.log('Polygon clicked:', e.feature);
// map.setFeatureState(e.feature, {highlight: true});
// }
// });
function makeLegend(colorstops, minValue, maxValue){
/**
* colorstops: [[0, 'green'], [100, 'red']]
* @type {number}
*/
var svg_height = 300, svg_width=70;
var svg = d3.select('#svg');
var defs = svg
.attr('height', svg_height)
.attr('width', svg_width);
var linearGradient = svg.append("defs")
.append("linearGradient")
.attr("id", "linear-gradient");
linearGradient
.attr("x1", "0%")
.attr("y1", "100%")
.attr("x2", "0%")
.attr("y2", "0%");
svg.append("rect")
.attr("width", svg_width*0.4)
.attr("height", svg_height)
.attr('rx', 4)
.style("fill", "url(#linear-gradient)");
colorstops.forEach(function(d){
linearGradient.append("stop")
.attr("offset", d[0] + "%")
.attr("stop-color", d[1]);
});
var xScale = d3.scaleLinear().range([svg_height-20,0]).domain([minValue,maxValue]);
var xAxis = d3.axisRight(xScale).ticks(5);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate("+svg_width/2+"," + (10) + ")")
.call(xAxis);
}