-
Notifications
You must be signed in to change notification settings - Fork 0
#4 Localstorage
Localstorage gebruik je als je een data object wilt opslaan aan de client side. Dit kan handig zijn om bijvoorbeeld een inlogstatus of winkelwagentje te onthouden. Dit is bij mijn applicatie niet van toepassing, dus ik ga localstorage gebruiken om een transform in op te slaan.
Bij mijn mapchart van Nederland is er een optie om in te zoomen en te pannen. Deze functie zit in D3 en is heel makkelijk toe te passen door d3.zoom te gebruiken. D3.zoom maakt gebruik van een transform, die wordt geplaatst op alle inhoud van mijn svg. Als ik deze transform weet op te slaan in mijn localstorage kan ik de map positie na een page reload behouden.
om mijn transform op te slaan heb ik een aantal verschillende dingen geprobeerd. Als eerst ben ik aan de gang gegaan in react. Hierbij heb ik geprobeerd om de value van de translate op te slaan wanneer deze veranderd, maar dit lukte niet en ik kreeg de hele tijd foutmeldingen. Er waren problemen met scoping en DOM elementen die nog niet bestonden op het moment van aanroepen.
Nadat ik hier veel te lang mee bezig was ben ik gaan nadenken over de plek waarop ik alles ging storen, en kwam ik erachter dat in mijn react niet de beste optie was. Vervolgens heb ik de code verplaatst naar de plek in D3 waar de transform wordt toegepast. Deze transform heb ik eruit gepakt en in een andere functie meegegeven die ik heb geïmporteerd.
import { storeData } from '../../localStorage' //imports function that stores data
function onZoom(event, mapSVG) { //gets calles from zoom on map
mapSVG.selectAll('svg g').attr('transform', event.transform); //transforms objects
translate = event.transform; //sets value to translate
storeData(translate); //calls function with correct value
}
Nu wordt de transform meegegeven aan de functie storeData(). Alles wat deze functie vervolgens doet is de data in de localstorage zetten. Dit had ik ter plekke in de onZoom functie kunnen doen, maar ik vind het zelf overzichtelijker om dit in een apart bestand te doen, zodat ik alle localstorage code op 1 plek kan hebben.
const storage = window.localStorage //define local storage
function storeData(data) { //gets data from zoom function
storage.setItem('zoom', JSON.stringify(data))
}
De juiste data wordt nu opgeslagen in de localstorage, nu moet het alleen nog toegepast worden op het element wanneer deze inlaadt. Hiervoor had ik weer moeite met de juiste plek zoeken, maar na een aantal dingen te proberen heb ik deze functie vlak boven mijn onZoom() call gezet, zodat de zoom uit de store eerst wordt toegepast.
mapSVG.selectAll('g') //sets transform from localstorage
.attr('transform', getStorage)
//zooming on map
mapSVG.call(d3.zoom().codeForZoom)
Om de juiste data te krijgen moet ik de data uit de localstorage eerst wat aanpassen, zodat er een goede translate wordt gereturnd. Dit doe ik door middel van de volgende functie:
function getStorage() {
let data = JSON.parse(storage.getItem('zoom'));
let css = 'translate(' + data.x + ',' + data.y + ') scale(' + data.k + ')';
return css //returns correct css property
}
Nu wordt er correcte CSS terug gestuurd, wat direct gebruikt kan worden op de attr. Dit werkt, totdat er nog geen data in de localstorage staat, dan komt er een error message omdat er iets undifined wordt teruggestuurd. Dit is op te lossen door een simpele if statement, waardoor er niet undifined kan worden gereturnd en de pagina heel blijft.
function getStorage() {
let data = JSON.parse(storage.getItem('zoom'));
if (data) { //checks if there is data, error prevention
let css = 'translate(' + data.x + ',' + data.y + ') scale(' + data.k + ')';
return css //returns correct css property
}
}