author Angelo Gladding
name My World
published 2025-08-03T18:21:12.840302-07:00
type entry
updated 2025-08-13T16:49:21.966057-07:00
url /map, /2025/08/04/qz
visibility public
Content
<div id=map></div> <style> #map { height: 60em; width: 100%; } </style> <link href=https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.css rel=stylesheet> <script src=https://api.mapbox.com/mapbox-gl-js/v2.15.0/mapbox-gl.js></script> <script> mapboxgl.accessToken = 'pk.eyJ1IjoicmFndC1hZyIsImEiOiJjbWR3ZjZ5cjkxMmRhMmtwbHVlcDBrN240In0.nCEdq0_XYbjl8jq6YV4p5g'; const map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/satellite-streets-v12', center: [-118.150, 34.113], // Centered on South Pasadena (ZIP 91030) zoom: 13 }); map.addControl(new mapboxgl.NavigationControl()); </script> <!--input id="addrInput" type="text" value="1856 Hanscom Dr, South Pasadena, CA" style="width:60%;padding:4px"> <button id="addrBtn">Show Parcel</button--> <script> (function () { function ringsToGeoJSON(rings){ return { type:'Feature', geometry:{ type:'Polygon', coordinates: rings.map(function(r){ return r.map(function(c){ return [c[0], c[1]] }) }) }, properties:{} } } function fitToFeature(feature){ var coords = feature.geometry.coordinates[0] var xs = coords.map(function(c){ return c[0] }), ys = coords.map(function(c){ return c[1] }) var b = [[Math.min.apply(null,xs), Math.min.apply(null,ys)], [Math.max.apply(null,xs), Math.max.apply(null,ys)]] map.fitBounds(b, { padding: 60, duration: 500 }) } function toEnvMeters(lat, lon, m){ var dLat = m / 111132 var dLon = m / (111320 * Math.cos(lat * Math.PI / 180)) return { xmin: lon - dLon, ymin: lat - dLat, xmax: lon + dLon, ymax: lat + dLat, spatialReference: { wkid: 4326 } } } async function queryParcelByPoint(lon, lat){ // try precise contains with a point var url = new URL('https://arcgis.gis.lacounty.gov/arcgis/rest/services/DRP/GISNET_Public/MapServer/333/query') url.searchParams.set('geometry', JSON.stringify({ x: lon, y: lat, spatialReference:{wkid:4326} })) url.searchParams.set('geometryType','esriGeometryPoint') url.searchParams.set('spatialRel','esriSpatialRelContains') url.searchParams.set('inSR','4326'); url.searchParams.set('outSR','4326') url.searchParams.set('where','1=1') url.searchParams.set('outFields','AIN,SitusFullAddress') url.searchParams.set('returnGeometry','true'); url.searchParams.set('f','json') var r = await fetch(url.toString()) if (r.ok) { var d = await r.json() if (d.features && d.features.length && d.features[0].geometry && d.features[0].geometry.rings) return d.features[0] } // fallback: tiny 3 m envelope intersects (handles edge/precision) var tiny = toEnvMeters(lat, lon, 3) var u2 = new URL('https://arcgis.gis.lacounty.gov/arcgis/rest/services/DRP/GISNET_Public/MapServer/333/query') u2.searchParams.set('geometry', JSON.stringify(tiny)) u2.searchParams.set('geometryType','esriGeometryEnvelope') u2.searchParams.set('spatialRel','esriSpatialRelIntersects') u2.searchParams.set('inSR','4326'); u2.searchParams.set('outSR','4326') u2.searchParams.set('where','1=1') u2.searchParams.set('outFields','AIN,SitusFullAddress') u2.searchParams.set('returnGeometry','true'); u2.searchParams.set('f','json') var r2 = await fetch(u2.toString()) if (!r2.ok) return null var d2 = await r2.json() return (d2.features && d2.features.length) ? d2.features[0] : null } async function drawParcelAt(lon, lat){ var feat = await queryParcelByPoint(lon, lat) if (!feat) return console.warn('No parcel at click') var parcelFeature = ringsToGeoJSON(feat.geometry.rings) // clear old if (map.getLayer('parcel-line')) map.removeLayer('parcel-line') if (map.getLayer('parcel-fill')) map.removeLayer('parcel-fill') if (map.getSource('parcel')) map.removeSource('parcel') // add new map.addSource('parcel', { type:'geojson', data: parcelFeature }) map.addLayer({ id:'parcel-fill', type:'fill', source:'parcel', paint:{ 'fill-color':'#ffae00', 'fill-opacity':0.25 } }) map.addLayer({ id:'parcel-line', type:'line', source:'parcel', paint:{ 'line-color':'#ff7300', 'line-width':2 } }) fitToFeature(parcelFeature) } function ensureMapReady(fn){ if (map && map.isStyleLoaded && map.isStyleLoaded()) fn() else map.once('load', fn) } ensureMapReady(function(){ map.getCanvas().style.cursor = 'crosshair' map.on('click', function(e){ drawParcelAt(e.lngLat.lng, e.lngLat.lat) }) }) })() </script> |