|
<html> |
|
<head> |
|
<meta |
|
name="viewport" |
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, minimal-ui" |
|
/> |
|
<link |
|
rel="stylesheet" |
|
href="https://unpkg.com/[email protected]/dist/leaflet.css" |
|
crossorigin="" |
|
/> |
|
<script |
|
src="https://unpkg.com/[email protected]/dist/leaflet.js" |
|
crossorigin="" |
|
></script> |
|
|
|
<script src="http://localhost:8080/zepto/zepto.min.js"></script> |
|
<script src="http://localhost:8080/leaflet-hash/leaflet-hash.js"></script> |
|
|
|
<link |
|
href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.css" |
|
rel="stylesheet" |
|
/> |
|
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.js"></script> |
|
<script src="https://unpkg.com/mapbox-gl-leaflet/leaflet-mapbox-gl.js"></script> |
|
|
|
<script src="https://unpkg.com/@turf/turf@6/turf.min.js"></script> |
|
|
|
<!-- Load Esri Leaflet from CDN --> |
|
<script src="https://unpkg.com/esri-leaflet@^3.0.8/dist/esri-leaflet.js"></script> |
|
|
|
<link rel="stylesheet" href="http://localhost:8080/css/l.geosearch.css" /> |
|
<style type="text/css"> |
|
body, |
|
#map { |
|
height: 100%; |
|
margin: 0; |
|
padding: 0; |
|
background-image: url(images/transparent.png); |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<div id="map"></div> |
|
<script> |
|
var leaflet = L.map("map", { |
|
scrollWheelZoom: false, |
|
attributionControl: false, |
|
keyboardPanOffset: 256, |
|
maxZoom: 22, |
|
}); |
|
|
|
if (!location.hash) leaflet.setView([34.0775, -118.2096], 13); |
|
new L.Hash(leaflet); |
|
|
|
var mapbox = L.mapboxGL({ |
|
accessToken: |
|
"pk.eyJ1Ijoib21lcjA5IiwiYSI6ImNreWJkcjdmczBlYmMydm9mazYwMnBxMm8ifQ.yC2TC8C5hsIFb13-HgP_Pw", |
|
container: "map", // container ID |
|
style: { |
|
version: 8, |
|
sources: { |
|
"raster-tiles": { |
|
type: "raster", |
|
tiles: ["http://localhost:8080/{z}/{x}/{y}.png"], |
|
tileSize: 256, |
|
}, |
|
}, |
|
layers: [ |
|
{ |
|
id: "simple-tiles", |
|
type: "raster", |
|
source: "raster-tiles", |
|
minzoom: 0, |
|
maxzoom: 22, |
|
}, |
|
], |
|
}, |
|
preserveDrawingBuffer: true, |
|
}).addTo(leaflet); |
|
|
|
var map = mapbox._glMap; |
|
|
|
window.zoningLayer = L.esri |
|
.featureLayer({ |
|
url: "https://public.gis.lacounty.gov/public/rest/services/LACounty_Cache/LACounty_Parcel/MapServer/0", |
|
}) |
|
.addTo(leaflet); |
|
|
|
zoningLayer.bindPopup( |
|
function (el) { |
|
var f = el.feature; |
|
updateArea({ features: [f] }); |
|
Object.keys(f.properties).forEach((key) => { |
|
if (!f.properties[key] || f.properties[key] === " ") { |
|
delete f.properties[key]; |
|
} |
|
}); |
|
return ( |
|
"<pre>" + |
|
JSON.stringify(f.properties, null, " ").replace(/[\{\}"]/g, "") + |
|
"</pre>" |
|
); |
|
}, |
|
{ maxHeight: "200" } |
|
); |
|
|
|
function getPixels(ctx) { |
|
return ctx.readPixels ? getPixels3d(ctx) : getPixels2d(ctx); |
|
} |
|
|
|
function getPixels3d(gl) { |
|
var canvas = gl.canvas; |
|
var height = canvas.height; |
|
var width = canvas.width; |
|
var buffer = new Uint8Array(width * height * 4); |
|
|
|
gl.readPixels( |
|
0, |
|
0, |
|
canvas.width, |
|
canvas.height, |
|
gl.RGBA, |
|
gl.UNSIGNED_BYTE, |
|
buffer |
|
); |
|
|
|
return buffer; |
|
} |
|
|
|
function getPixels2d(ctx) { |
|
var canvas = ctx.canvas; |
|
var height = canvas.height; |
|
var width = canvas.width; |
|
|
|
return ctx.getImageData(0, 0, width, height).data; |
|
} |
|
|
|
function webglToCanvas2d(webgl, canvas2D) { |
|
var outCanvas = canvas2D |
|
? canvas2D.canvas || canvas2D |
|
: document.createElement("canvas"); |
|
var outContext = outCanvas.getContext("2d", { antialias: false }); |
|
var outImageData; |
|
|
|
webgl = |
|
webgl instanceof WebGLRenderingContext |
|
? webgl |
|
: webgl.getContext("webgl", { antialias: false }) || |
|
webgl.getContext("experimental-webgl", { antialias: false }); |
|
|
|
outCanvas.width = webgl.canvas.width; |
|
outCanvas.height = webgl.canvas.height; |
|
outImageData = outContext.getImageData( |
|
0, |
|
0, |
|
outCanvas.width, |
|
outCanvas.height |
|
); |
|
|
|
outImageData.data.set(new Uint8ClampedArray(getPixels3d(webgl).buffer)); |
|
outContext.putImageData(outImageData, 0, 0); |
|
outContext.translate(0, outCanvas.height); |
|
outContext.scale(1, -1); |
|
outContext.drawImage(outCanvas, 0, 0); |
|
outContext.setTransform(1, 0, 0, 1, 0, 0); |
|
|
|
return outCanvas; |
|
} |
|
|
|
function downloadCanvasAsImage(canvas, fileName) { |
|
console.log(doStats(canvas)); |
|
// var link = document.createElement("a"); |
|
// link.download = fileName; |
|
// link.href = canvas.toDataURL(); |
|
// link.click(); |
|
} |
|
|
|
var points = []; |
|
var savedPolygon; |
|
|
|
function saveClipped() { |
|
var mapCanvas = mapbox._glMap.getCanvas(); |
|
var ctx = mapCanvas.getContext("webgl", { antialias: false }); |
|
var canvas2d = webglToCanvas2d(ctx); |
|
var ctx2d = canvas2d.getContext("2d", { antialias: false }); |
|
var clippedCanvas = document.createElement("canvas"); |
|
clippedCanvas.width = mapCanvas.clientWidth; |
|
clippedCanvas.height = mapCanvas.clientHeight; |
|
var clippedCtx = clippedCanvas.getContext("2d", { antialias: false }); |
|
var factX = mapCanvas.clientWidth / mapCanvas.width; |
|
var factY = mapCanvas.clientHeight / mapCanvas.height; |
|
var minX = points[0].x; |
|
var maxX = points[0].x; |
|
var minY = points[0].y; |
|
var maxY = points[0].y; |
|
for (var i = 1; i < points.length; i++) { |
|
if (points[i].x < minX) minX = points[i].x; |
|
else if (points[i].x > maxX) { |
|
maxX = points[i].x; |
|
} |
|
if (points[i].y < minY) minY = points[i].y; |
|
else if (points[i].y > maxY) { |
|
maxY = points[i].y; |
|
} |
|
} |
|
clippedCtx.scale(1 / factX, 1 / factY); |
|
clippedCtx.translate(-minX, -minY); |
|
clippedCtx.beginPath(); |
|
clippedCtx.moveTo(points[0].x, points[0].y); |
|
for (var i = 1; i < points.length; i++) { |
|
clippedCtx.lineTo(points[i].x, points[i].y); |
|
} |
|
clippedCtx.closePath(); |
|
clippedCtx.lineWidth = 1; |
|
clippedCtx.stroke(); |
|
clippedCtx.clip(); |
|
clippedCtx.scale(factX, factY); |
|
clippedCtx.drawImage(canvas2d, 0, 0); |
|
var finalCanvas = document.createElement("canvas"); |
|
var finalWidth = (maxX - minX) / factX; |
|
var finalHeight = (maxY - minY) / factY; |
|
finalCanvas.width = finalWidth; |
|
finalCanvas.height = finalHeight; |
|
var finalCtx = finalCanvas.getContext("2d", { antialias: false }); |
|
finalCtx.drawImage( |
|
clippedCanvas, |
|
0, |
|
0, |
|
finalWidth, |
|
finalHeight, |
|
0, |
|
0, |
|
finalWidth, |
|
finalHeight |
|
); |
|
downloadCanvasAsImage(finalCanvas, "clipped-image.png"); |
|
} |
|
|
|
function updateArea(e) { |
|
points = []; |
|
if (e.features[0].geometry.type == "Polygon") { |
|
savedPolygon = e.features[0]; |
|
var polygonId = e.features[0].id; |
|
var coords = savedPolygon.geometry.coordinates[0]; |
|
coords.forEach(function (coord) { |
|
points.push(mapbox._glMap.project(coord)); |
|
}); |
|
setTimeout(saveClipped, 100); |
|
} |
|
} |
|
|
|
function doStats(canv) { |
|
var ctx = canv.getContext("2d", { antialias: false }); |
|
var imagedata = ctx.getImageData(0, 0, canv.width, canv.height); |
|
var data = imagedata.data; |
|
var counts = {}; |
|
var total = 0; |
|
var colors = { |
|
"210,205,192,255": "grey", |
|
"255,0,0,255": "red", |
|
"137,205,102,255": "lightgreen", |
|
"38,115,0,255": "darkgreen", |
|
"205,170,102,255": "tan", |
|
}; |
|
for (let i = 0; i < data.length; i += 4) { |
|
var rgba = [data[i], data[i + 1], data[i + 2], data[i + 3]]; |
|
var str = rgba.join(","); |
|
// console.log(rgba, str, counts[str]); |
|
if (!counts[str]) counts[str] = 1; |
|
else counts[str]++; |
|
if (colors[str]) total++; |
|
} |
|
|
|
var results = []; |
|
Object.keys(colors).forEach((c) => { |
|
var color = colors[c]; |
|
var count = counts[c] || 0; |
|
results.push({ |
|
color, |
|
count, |
|
percent: (count / total) * 100, |
|
}); |
|
}); |
|
return results; |
|
} |
|
</script> |
|
</body> |
|
</html> |