//2016 JAVASCRIPT var eventOutputContainer = document.getElementById("message"); // DON'T FORGET TO CHANGE THIS CODE DEPENDING ON THE DATA YOU'RE DISPLAYING IN YOUR TOOLTIP var tooltip = d3.select("div.tooltip"); var tooltip_category = d3.select("#cat"); var map = L.map('map').setView([22.799606, 113.567950], 9); //this is the Mapbox implementation, supply your own access token L.tileLayer('https://api.tiles.mapbox.com/v4/{mapid}/{z}/{x}/{y}.png?access_token={accessToken}', { attribution: 'Map data © OpenStreetMap, Imagery © Mapbox', mapid: 'mapbox.dark', accessToken: "pk.eyJ1IjoiYWszNzkzIiwiYSI6ImNpZjdmZ3V5eTBpOXpzaGx6a3hvbjVoemQifQ.Fflvuzl9_moN4a8H_k4m0w" }).addTo(map); //create variables to store a reference to svg and g elements var svg_overlay = d3.select(map.getPanes().overlayPane).append("svg"); var g_overlay = svg_overlay.append("g").attr("class", "leaflet-zoom-hide"); var svg = d3.select(map.getPanes().overlayPane).append("svg"); var g_line = svg.append("g").attr("class", "leaflet-zoom-hide"); var g = svg.append("g").attr("class", "leaflet-zoom-hide"); function projectPoint(x, y) { return map.latLngToLayerPoint(new L.LatLng(y, x)); } function projectStream(x, y) { var point = projectPoint(x, y); this.stream.point(point.x, point.y); } var transform = d3.geo.transform({point: projectStream}), path = d3.geo.path().projection(transform); var slidervalue = document.getElementById("slider").value; function updateData(){ g.selectAll("circle").remove() g_line.selectAll("path").remove() d3.json("sample.geojson", function(error, data) { if (error) return console.error(error); var pointData = data.features.filter(function(d) { return d.geometry.type == "Point"; }) var pathData = data.features.filter(function(d) { return d.geometry.type == "LineString"; }) console.log(pointData); console.log(pathData); //create placeholder circle geometry and bind it to data var circles = g.selectAll("circle").data(pointData); circles.enter() .append("circle") .on("mouseover", function(d){ tooltip.style("visibility", "visible"); tooltip_category.text("Category: " + d.properties.type); }) .on("mousemove", function(){ tooltip.style("top", (d3.event.pageY-10)+"px") tooltip.style("left",(d3.event.pageX+10)+"px"); }) .on("mouseout", function(){ tooltip.style("visibility", "hidden"); }) .attr("r",7) .attr("fill-opacity", .1) .style("fill", "white"); var lines = g_line.selectAll("path").data(pathData); lines.enter().append("path") map.on("viewreset", update); update(); transition(); function update() { // get bounding box of data var bounds = path.bounds(data), topLeft = bounds[0], bottomRight = bounds[1]; var buffer = 50; // reposition the SVG to cover the features. svg .attr("width", bottomRight[0] - topLeft[0] + (buffer * 2)) .attr("height", bottomRight[1] - topLeft[1] + (buffer * 2)) .style("left", (topLeft[0] - buffer) + "px") .style("top", (topLeft[1] - buffer) + "px"); g .attr("transform", "translate(" + (-topLeft[0] + buffer) + "," + (-topLeft[1] + buffer) + ")"); g_line.attr("transform", "translate(" + (-topLeft[0] + buffer) + "," + (-topLeft[1] + buffer) + ")"); // update circle position and size circles .attr("cx", function(d) { return projectPoint(d.geometry.coordinates[0], d.geometry.coordinates[1]).x; }) .attr("cy", function(d) { return projectPoint(d.geometry.coordinates[0], d.geometry.coordinates[1]).y; }) ; lines .attr("d", path) }; console.log(lines) function transition() { lines.transition() .duration(7500) .attrTween("stroke-dasharray", tweenDash) .each("end", function() { d3.select(this).call(transition);// infinite loop }); } // this function feeds the attrTween operator above with the // stroke and dash lengths function tweenDash() { return function(t) { //total length of path (single value) var l = lines.node().getTotalLength(); // this is creating a function called interpolate which takes // as input a single value 0-1. The function will interpolate // between the numbers embedded in a string. An example might // be interpolatString("0,500", "500,500") in which case // the first number would interpolate through 0-500 and the // second number through 500-500 (always 500). So, then // if you used interpolate(0.5) you would get "250, 500" // when input into the attrTween above this means give me // a line of length 250 followed by a gap of 500. Since the // total line length, though is only 500 to begin with this // essentially says give me a line of 250px followed by a gap // of 250px. interpolate = d3.interpolateString("0," + l, l + "," + l); //t is fraction of time 0-1 since transition began var marker = d3.select("#marker"); // p is the point on the line (coordinates) at a given length // along the line. In this case if l=50 and we're midway through // the time then this would 25. var p = lines.node().getPointAtLength(t * l); //Move the marker to that point marker.attr("transform", "translate(" + p.x + "," + p.y + ")"); //move marker console.log(interpolate(t)) return interpolate(t); } } //end tweenDash update() changeSlider();}) } function changeSlider(){ console.log(document.getElementById("slider").value) g.selectAll("circle") .attr("r",7) .attr("fill-opacity", .1) .style("fill", "white") .filter( function (d) {return(d.properties.time == document.getElementById("slider").value)}) .attr("fill-opacity", 1) .style("fill", "#FFB218") .attr("r", 10) }; // call function to update geometry ; ; updateData();