+
+
+
Kennisgrafiek wordt ingeladen ...
+
+
Klik op een punt op de kaart om de kennisgrafiek te laden
@@ -10,8 +13,10 @@
+
+
+
+ +
+ -
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/graph/composables/useTriplesFetching.js b/frontend/src/components/graph/composables/useTriplesFetching.js
index f25d7cd..2e46e77 100644
--- a/frontend/src/components/graph/composables/useTriplesFetching.js
+++ b/frontend/src/components/graph/composables/useTriplesFetching.js
@@ -3,17 +3,27 @@ import * as d3 from "d3";
import {triplesToGraph} from "@/components/graph/functions/triplesToGraph";
const NODE_RADIUS = 8;
+const NODE_STROKE_WIDTH = 1.5;
const NODE_TEXT_FONT_SIZE = 11;
const LINK_TEXT_FONT_SIZE = 9;
function visualizeTriples(triples) {
- const svg = d3.select("#knowledge-graph");
+ const div = d3.select("#knowledge-graph")
+ div.select("svg").remove();
+ const svg = div.append("svg")
svg.selectAll("*").remove();
const g = svg.append("g");
+ const tooltip = div.append("div")
+ .attr("id", "tooltip")
+ .attr("class", "shadow-medium body body-xxsmall-regular")
+ .style("display", "none")
+
const width = +svg.style("width").replace("px", "")
const height = +svg.style("height").replace("px", "");
const graph = triplesToGraph(triples);
+ d3.select("#knowledge-graph-loading").remove();
+ d3.select("#knowledge-graph-zoom-buttons").style("opacity", "1")
const force = d3.forceSimulation(graph.nodes);
function dragstart() {
@@ -24,6 +34,19 @@ function visualizeTriples(triples) {
return x < lo ? lo : x > hi ? hi : x;
}
+ function onMouseOver(event, text) {
+ tooltip.style("display", "block").text(text)
+ }
+
+ function onMouseOut() {
+ tooltip.style("display", "none");
+ }
+
+ function onMouseMove(event, marginBottom) {
+ let width = +tooltip.style("width").replace("px", "");
+ tooltip.style("left", `${event.layerX - width / 2}px`).style("top", `${event.layerY - marginBottom}px`)
+ }
+
function dragged(event, d) {
d.fx = clamp(event.x, 0, width);
d.fy = clamp(event.y, 0, height);
@@ -63,9 +86,10 @@ function visualizeTriples(triples) {
.append("text")
.attr("class", "link-text")
.style("font-size", `${LINK_TEXT_FONT_SIZE}px`)
- .text(function (d) {
- return d.predicate;
- });
+ .on("mouseover", (event, d) => onMouseOver(event, d.predicate.id))
+ .on("mouseout", onMouseOut)
+ .on("mousemove", event => onMouseMove(event, 42))
+ .text(d => d.predicate.label);
// ==================== Add Link Names =====================
const nodeTexts = g
.selectAll(".node-text")
@@ -74,9 +98,10 @@ function visualizeTriples(triples) {
.append("text")
.attr("class", "node-text")
.style("font-size", `${NODE_TEXT_FONT_SIZE}px`)
- .text(function (d) {
- return d.label;
- });
+ .on("mouseover", (event, d) => onMouseOver(event, d.id))
+ .on("mouseout", onMouseOut)
+ .on("mousemove", event => onMouseMove(event, 42))
+ .text(d => d.label);
// ==================== Add Node =====================
const nodes = g
.selectAll(".node")
@@ -85,6 +110,7 @@ function visualizeTriples(triples) {
.append("circle")
.attr("class", "node")
.attr("r", NODE_RADIUS)
+ .style("stroke-width", `${NODE_STROKE_WIDTH}px`)
.call(drag);
let transform;
@@ -92,47 +118,54 @@ function visualizeTriples(triples) {
const zoom = d3.zoom().on("zoom", e => {
g.attr("transform", () => transform = e.transform);
nodes.attr("r", NODE_RADIUS / Math.sqrt(transform.k))
- nodeTexts.style("font-size", `${11 / Math.sqrt(transform.k)}px`)
- linkTexts.style("font-size", `${9 / Math.sqrt(transform.k)}px`)
+ nodes.style("stroke-width", `${NODE_STROKE_WIDTH / Math.sqrt(transform.k)}px`)
+ nodeTexts.style("font-size", `${NODE_TEXT_FONT_SIZE / Math.sqrt(transform.k)}px`)
+ linkTexts.style("font-size", `${LINK_TEXT_FONT_SIZE / Math.sqrt(transform.k)}px`)
})
+ const zoomInBtn = d3.select("#knowledge-graph-zoom-in-btn")
+ .on("click", () => zoom.scaleBy(svg.transition().duration(350), 1.5))
+ const zoomOutBtn = d3.select("#knowledge-graph-zoom-out-btn")
+ .on("click", () => zoom.scaleBy(svg.transition().duration(350), 0.75))
+
function ticked() {
+ const DISTANCE_FACTOR = 2.5;
nodes
.attr("cx", function (d) {
- return 2 * d.x;
+ return DISTANCE_FACTOR * d.x;
})
.attr("cy", function (d) {
- return 2 * d.y;
+ return DISTANCE_FACTOR * d.y;
});
links
.attr("x1", function (d) {
- return 2 * d.source.x;
+ return DISTANCE_FACTOR * d.source.x;
})
.attr("y1", function (d) {
- return 2 * d.source.y;
+ return DISTANCE_FACTOR * d.source.y;
})
.attr("x2", function (d) {
- return 2 * d.target.x;
+ return DISTANCE_FACTOR * d.target.x;
})
.attr("y2", function (d) {
- return 2 * d.target.y;
+ return DISTANCE_FACTOR * d.target.y;
});
nodeTexts
.attr("x", function (d) {
- return 2 * d.x + 12;
+ return DISTANCE_FACTOR * d.x + 12;
})
.attr("y", function (d) {
- return 2 * d.y + 3;
+ return DISTANCE_FACTOR * d.y + 3;
});
linkTexts
.attr("x", function (d) {
- return 4 + 2 * (d.source.x + d.target.x) / 2;
+ return 4 + DISTANCE_FACTOR * (d.source.x + d.target.x) / 2;
})
.attr("y", function (d) {
- return 4 + 2 * (d.source.y + d.target.y) / 2;
+ return 4 + DISTANCE_FACTOR * (d.source.y + d.target.y) / 2;
});
}
diff --git a/frontend/src/components/graph/functions/triplesToGraph.js b/frontend/src/components/graph/functions/triplesToGraph.js
index 7ade3c4..95c5810 100644
--- a/frontend/src/components/graph/functions/triplesToGraph.js
+++ b/frontend/src/components/graph/functions/triplesToGraph.js
@@ -1,33 +1,40 @@
-function filterNodesById(nodes,id){
- return nodes.filter(function(n) { return n.id === id; });
+function filterNodesById(nodes, id) {
+ return nodes.filter(function (n) {
+ return n.id === id;
+ });
}
-export function triplesToGraph(triples){
+export function triplesToGraph(triples) {
//Graph
- var graph={nodes:[], links:[]};
+ var graph = {nodes: [], links: []};
//Initial Graph from triples
- triples.forEach(function(triple){
- var subjId = triple.subject;
- var predId = triple.predicate;
- var objId = triple.object;
+ triples.forEach(function (triple) {
+ var subject = triple.subject;
+ var predicate = triple.predicate;
+ var object = triple.object;
- var subjNode = filterNodesById(graph.nodes, subjId)[0];
- var objNode = filterNodesById(graph.nodes, objId)[0];
+ var subjNode = filterNodesById(graph.nodes, subject.value)[0];
+ var objNode = filterNodesById(graph.nodes, object.value)[0];
- if(subjNode==null){
- subjNode = {id:subjId, label:subjId, weight:1};
+ if (subjNode == null) {
+ subjNode = {id: subject.value, label: subject.prefixedValue, weight: 1};
graph.nodes.push(subjNode);
}
- if(objNode==null){
- objNode = {id:objId, label:objId, weight:1};
+ if (objNode == null) {
+ objNode = {id: object.value, label: object.prefixedValue, weight: 1};
graph.nodes.push(objNode);
}
- graph.links.push({source:subjNode, target:objNode, predicate:predId, weight:1});
+ graph.links.push({
+ source: subjNode,
+ target: objNode,
+ predicate: {label: predicate.prefixedValue, id: predicate.value},
+ weight: 1
+ });
});
return graph;
diff --git a/frontend/src/components/linechart/LineChart.vue b/frontend/src/components/linechart/LineChart.vue
index 3cb2bd9..78032a8 100644
--- a/frontend/src/components/linechart/LineChart.vue
+++ b/frontend/src/components/linechart/LineChart.vue
@@ -108,7 +108,7 @@ export default {
});
},
error => {
- console.log(error);
+ console.error(error);
this.connect()
}
);
diff --git a/frontend/src/components/map/LeafletMap.vue b/frontend/src/components/map/LeafletMap.vue
index ea9f7dc..543868f 100644
--- a/frontend/src/components/map/LeafletMap.vue
+++ b/frontend/src/components/map/LeafletMap.vue
@@ -13,7 +13,7 @@
time = timestamp;
timePeriod = period;
}"
- @realtime-toggled="(isRealTimeEnabled) => isRealTimeEnabled ? connect() : disconnect()"
+ @realtime-toggled="isRealTimeEnabled => isRealTimeEnabled ? connect() : disconnect()"
/>
@@ -100,18 +100,13 @@ export default {
mounted() {
this.connect()
- console.log(import.meta.env.VITE_WS_BASE_URL);
- this.map = L.map("map", {zoomAnimation: false, zoomControl: false}).setView([50.7747, 4.4852], 8)
+ this.map = L.map("map", {zoomAnimation: false, zoomControl: false}).setView([50.9, 4.15], 8)
L.control.zoom({position: "topright"}).addTo(this.map)
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap'
}).addTo(this.map);
- //TODO: delete this and hard code the bounds of Flanders/Belgium for performance reasons
this.map.on("popupclose", () => this.memberId = null)
- // this.map.on("moveend", () => {
- // this.fetchMembers();
- // });
this.fetchMembers();
for (let [key, value] of this.layersToShow.entries()) {
if (value) {
@@ -139,7 +134,10 @@ export default {
timestamp: new Date(this.time).toISOString().replace("Z", ""),
timePeriod: this.timePeriod
},
- data: this.map.getBounds(),
+ data: {
+ _northEast: {lat: 51.61113728, lng: 6.60827637},
+ _southWest: {lat: 49.37098431, lng: 2.38952637}
+ },
headers: {
'Content-type': 'application/json',
'Access-Control-Allow-Origin': '*'
@@ -157,12 +155,13 @@ export default {
},
//websocket
connect() {
+ this.layers.forEach(layer => layer.clearLayers())
this.stompClient = new Stomp.client(`${import.meta.env.VITE_WS_BASE_URL}/update`, {debug: false});
this.stompClient.connect(
{},
() => this.subscribe(),
error => {
- console.log(error);
+ console.error(error);
this.connect()
}
);
@@ -190,7 +189,7 @@ export default {
}
},
updateMarker(marker) {
- marker.setStyle({color: '#808080'})
+ marker.setStyle({color: '#A813F7'})
}
}
@@ -241,6 +240,10 @@ export default {
margin: 12px;
}
+.leaflet-popup-content-wrapper {
+ border-radius: 3px !important;
+}
+
.marker-cluster-flanders {
position: relative;
color: #fff;
@@ -262,6 +265,37 @@ export default {
gap: 6px;
}
+.popup-grid {
+ display: grid;
+ row-gap: 6px;
+ column-gap: 12px;
+ grid-template-columns: auto auto;
+}
+
+.popup-gipod-icon {
+ width: 11px;
+ height: 16px;
+}
+
+.popup-bluebike-icon {
+ width: 24px;
+ height: 24px;
+}
+
+.popup-grid-icon {
+ grid-column-start: span 2;
+ justify-self: center;
+}
+
+.popup-title {
+ grid-column-start: span 2;
+ justify-self: center;
+}
+
+.popup-grid-end {
+ justify-self: end;
+}
+
.popup-verkeersmeting-map-marker {
width: 16px;
height: 16px;
diff --git a/frontend/src/components/map/composables/useMarkers.js b/frontend/src/components/map/composables/useMarkers.js
index 191071b..95b57b6 100644
--- a/frontend/src/components/map/composables/useMarkers.js
+++ b/frontend/src/components/map/composables/useMarkers.js
@@ -54,7 +54,7 @@ export function useMarkers(memberGeometries, collection, onMarkerClicked, onPopu
}
}
let geoJson = L.geoJson(geoJsonFeature, {onEachFeature: onEachFeature, pointToLayer: pointToLayer})
- geoJson.setStyle({color: '#808080'});
+ geoJson.setStyle({color: '#A813F7'});
markers.push(geoJson)
})
return markers;
diff --git a/frontend/src/components/map/composables/usePopup.js b/frontend/src/components/map/composables/usePopup.js
index 58952e5..579cc14 100644
--- a/frontend/src/components/map/composables/usePopup.js
+++ b/frontend/src/components/map/composables/usePopup.js
@@ -1,34 +1,37 @@
import mapsMarker from "../../../assets/svgs/legend/maps.marker.svg"
import carIcon from "../../../assets/svgs/legend/car.svg"
import bikeIcon from "../../../assets/svgs/legend/bike.svg"
+import alertIcon from "../../../assets/svgs/legend/alert-triangle-filled.svg"
+
+function getBikeString(number) {
+ return number === "1" ? "fiets" : "fietsen";
+}
+
export function usePopup(collection, properties) {
- console.log(collection)
switch (collection) {
case "gipod":
- return `
${properties.startTime}
`
+ return `
+
+
+
+
`
case "verkeersmeting":
return ``
case "bluebikes":
- return `