agentscript
Version:
AgentScript Model in Model/View architecture
103 lines (85 loc) • 3.34 kB
HTML
<html>
<head>
<title>CountyWalker</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.8.0/dist/leaflet.css">
<link rel="stylesheet" href="./map.css">
</head>
<body>
<div id="map"></div>
<script type="module">
import * as util from '../src/utils.js'
import * as gis from '../src/gis.js'
import GeoWorld from '../src/GeoWorld.js'
import TwoDraw from '../src/TwoDraw.js'
import Animator from '../src/Animator.js'
import CountiesModel from '../models/CountiesModel.js'
import * as L from 'https://unpkg.com/leaflet@1.8.0/dist/leaflet-src.esm.js'
import elementOverlay from '../vendor/elementOverlay.js'
// If not using the default model options:
const counties = await fetch('../models/data/nmcounties.json').then(resp => resp.json())
const world = new GeoWorld({ bbox: counties, patchesWidth: 100 })
const model = new CountiesModel(world)
await model.startup()
model.setup()
const drawOptions = {
patchesColor: 'transparent',
linksColor: 'gray',
linksWidth: 4,
turtlesSize: 6,
turtlesColor: t =>
view.drawOptions.turtlesMap.atIndex(t.county + 1),
}
const view = new TwoDraw(model, {
div: util.createCanvas(0, 0), // the view will resize
drawOptions,
})
// ===== Start of map & layers
const bbox = model.world.bbox
const bboxCenter = model.world.bboxCenter()
// ===== The map using the div, model center and Z. World is a GeoWorld
const zoom = 7
// preferCanvas seems to be needed for model on top of json?
const map = L.map('map', { preferCanvas: true, })
.setView(gis.latlon(bboxCenter), zoom)
// ===== Map's terrain
L.tileLayer(gis.template('osm'), {
attribution: gis.attribution('osm'),
}).addTo(map)
// ===== A border around the model
const latlngs = gis.latlon(gis.bboxCoords(bbox))
L.rectangle(latlngs, { color: 'black', weight: 1, fill: false }).addTo(map)
// ===== A JSON layer with popup, fairly common
L.geoJSON(counties, {
style: (feature) => ({
color: 'red',
fillOpacity: 0.2,
weight: 3,
}),
}).bindPopup(
layer =>
layer.feature.properties.NAME +
', pop: ' +
layer.feature.properties.population.toLocaleString()
).addTo(map)
// ===== The model layer, on top, using Cody's ElementOverlay
const [west, south, east, north] = bbox
const bounds = new L.LatLngBounds(
new L.LatLng(north, west),
new L.LatLng(south, east)
)
const ElementOverlay = elementOverlay(L)
const modelLayer = new ElementOverlay(view.canvas, bounds).addTo(map)
// ===== End of map & layers
const anim = new Animator(
() => {
model.step()
view.draw()
},
-1, // 500, // run 500 steps
20 // 30 // 30 fps
)
util.toWindow({ map, modelLayer, anim, util })
</script>
</body>
</html>