diff --git a/packages/examples/package.json b/packages/examples/package.json index 5df1404..1e647ae 100644 --- a/packages/examples/package.json +++ b/packages/examples/package.json @@ -3,14 +3,15 @@ "version": "0.1.0", "private": true, "dependencies": { - "@datavis-tech/polylabel": "^1.2.0", - "@testing-library/jest-dom": "^5.9.0", - "@testing-library/react": "^10.2.0", - "@testing-library/user-event": "^11.2.0", + "@datavis-tech/polylabel": "^1.3.0", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^10.3.0", + "@testing-library/user-event": "^12.0.2", "d3-array": "^2.4.0", "d3-color": "^1.4.1", "d3-fetch": "^1.2.0", "d3-geo": "^1.12.1", + "d3-geo-projection": "^2.9.0", "prettier": "^2.0.5", "react": "^16.13.1", "react-dom": "^16.13.1", diff --git a/packages/examples/src/pleth/PolygonLabelsLayer.js b/packages/examples/src/pleth/PolygonLabelsLayer.js index e0f8538..c25999a 100644 --- a/packages/examples/src/pleth/PolygonLabelsLayer.js +++ b/packages/examples/src/pleth/PolygonLabelsLayer.js @@ -3,6 +3,9 @@ import styled from 'styled-components'; import polylabel from '@datavis-tech/polylabel'; import { maxIndex } from 'd3-array'; +const centroidWeight = 0.01; +const precision = 1; + const Text = styled.text` pointer-events: none; user-select: none; @@ -33,15 +36,20 @@ export const PolygonLabelsLayer = ({ const id = feature.id; const name = feature.properties.name; if (feature.geometry.type === 'Polygon') { - const coordinates = polylabel([ - feature.geometry.coordinates[0].map(projection), - ]); + const coordinates = polylabel( + [feature.geometry.coordinates[0].map(projection)], + precision, + false, + centroidWeight + ); labels.push({ id, name, coordinates }); } else if (feature.geometry.type === 'MultiPolygon') { const polylabels = feature.geometry.coordinates .map((polygon) => polygon[0].map(projection)) .filter((projectedPolygon) => !projectedPolygon.some((d) => d === null)) - .map((projectedPolygon) => polylabel([projectedPolygon])); + .map((projectedPolygon) => + polylabel([projectedPolygon], precision, false, centroidWeight) + ); if (polylabels.length > 0) { const coordinates = polylabels[maxIndex(polylabels, (d) => d.distance)]; labels.push({ id, name, coordinates }); diff --git a/packages/examples/src/pleth/geoAlbersUsaTerritories.js b/packages/examples/src/pleth/geoAlbersUsaTerritories.js new file mode 100644 index 0000000..34164b7 --- /dev/null +++ b/packages/examples/src/pleth/geoAlbersUsaTerritories.js @@ -0,0 +1,202 @@ +// From https://github.com/stamen/dirty-reprojectors/blob/master/projections/albers-usa-territories.js +const d3 = require('d3-geo'); + +const epsilon = 0.000001; + +function multiplex(streams) { + return { + point(x, y) { + for (const s of streams) s.point(x, y); + }, + sphere() { + for (const s of streams) s.sphere(); + }, + lineStart() { + for (const s of streams) s.lineStart(); + }, + lineEnd() { + for (const s of streams) s.lineEnd(); + }, + polygonStart() { + for (const s of streams) s.polygonStart(); + }, + polygonEnd() { + for (const s of streams) s.polygonEnd(); + }, + }; +} + +export function geoAlbersUsaTerritories() { + var cache, + cacheStream, + lower48 = d3.geoAlbers(), + lower48Point, + alaska = d3 + .geoConicEqualArea() + .rotate([154, 0]) + .center([-2, 58.5]) + .parallels([55, 65]), + alaskaPoint, + hawaii = d3 + .geoConicEqualArea() + .rotate([157, 0]) + .center([-3, 19.9]) + .parallels([8, 18]), + hawaiiPoint, + puertoRico = d3 + .geoConicEqualArea() + .rotate([66, 0]) + .center([0, 18]) + .parallels([8, 18]), + puertoRicoPoint, + guamMariana = d3 + .geoConicEqualArea() + .rotate([-145, 0]) + .center([0, 16]) + .parallels([10, 20]), + guamMarianaPoint, + americanSamoa = d3 + .geoConicEqualArea() + .rotate([170, 0]) + .center([0, -14]) + .parallels([-14, 0]), + americanSamoaPoint, + point, + pointStream = { + point: function (x, y) { + point = [x, y]; + }, + }; + + function albersUsaTerritories(coordinates) { + var x = coordinates[0], + y = coordinates[1]; + return ( + (point = null), + (lower48Point.point(x, y), point) || + (alaskaPoint.point(x, y), point) || + (hawaiiPoint.point(x, y), point) || + (puertoRicoPoint.point(x, y), point) || + (guamMarianaPoint.point(x, y), point) || + (americanSamoaPoint.point(x, y), point) + ); + } + + albersUsaTerritories.invert = function (coordinates) { + var k = lower48.scale(), + t = lower48.translate(), + x = (coordinates[0] - t[0]) / k, + y = (coordinates[1] - t[1]) / k; + return (y >= 0.12 && y < 0.234 && x >= -0.425 && x < -0.214 + ? alaska + : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 + ? hawaii + : y >= 0.204 && y < 0.234 && x >= 0.3 && x < 0.38 + ? puertoRico + : y >= 0.05 && y < 0.204 && x >= 0.34 && x < 0.38 + ? guamMariana + : y >= 0.16 && y < 0.204 && x >= 0.28 && x < 0.34 + ? americanSamoa + : lower48 + ).invert(coordinates); + }; + + albersUsaTerritories.stream = function (stream) { + return cache && cacheStream === stream + ? cache + : (cache = multiplex([ + lower48.stream((cacheStream = stream)), + alaska.stream(stream), + hawaii.stream(stream), + puertoRico.stream(stream), + guamMariana.stream(stream), + americanSamoa.stream(stream), + ])); + }; + + albersUsaTerritories.precision = function (_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_); + alaska.precision(_); + hawaii.precision(_); + puertoRico.precision(_); + guamMariana.precision(_); + americanSamoa.precision(_); + return reset(); + }; + + albersUsaTerritories.scale = function (_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_); + alaska.scale(_ * 0.35); + hawaii.scale(_); + puertoRico.scale(_); + guamMariana.scale(_); + americanSamoa.scale(_); + return albersUsaTerritories.translate(lower48.translate()); + }; + + albersUsaTerritories.translate = function (_) { + if (!arguments.length) return lower48.translate(); + var k = lower48.scale(), + x = +_[0], + y = +_[1]; + + lower48Point = lower48 + .translate(_) + .clipExtent([ + [x - 0.455 * k, y - 0.238 * k], + [x + 0.455 * k, y + 0.238 * k], + ]) + .stream(pointStream); + + alaskaPoint = alaska + .translate([x - 0.31 * k, y + 0.201 * k]) + .clipExtent([ + [x - 0.425 * k + epsilon, y + 0.12 * k + epsilon], + [x - 0.214 * k - epsilon, y + 0.234 * k - epsilon], + ]) + .stream(pointStream); + + hawaiiPoint = hawaii + .translate([x - 0.205 * k, y + 0.212 * k]) + .clipExtent([ + [x - 0.214 * k + epsilon, y + 0.166 * k + epsilon], + [x - 0.115 * k - epsilon, y + 0.234 * k - epsilon], + ]) + .stream(pointStream); + + puertoRicoPoint = puertoRico + .translate([x + 0.335 * k, y + 0.224 * k]) + .clipExtent([ + [x + 0.3 * k, y + 0.204 * k], + [x + 0.38 * k, y + 0.234 * k], + ]) + .stream(pointStream); + + guamMarianaPoint = guamMariana + .translate([x + 0.36 * k, y + 0.14 * k]) + .clipExtent([ + [x + 0.34 * k, y + 0.05 * k], + [x + 0.38 * k, y + 0.204 * k], + ]) + .stream(pointStream); + + americanSamoaPoint = americanSamoa + .translate([x + 0.315 * k, y + 0.18 * k]) + .clipExtent([ + [x + 0.28 * k, y + 0.16 * k], + [x + 0.34 * k, y + 0.204 * k], + ]) + .stream(pointStream); + + return reset(); + }; + + function reset() { + cache = cacheStream = null; + return albersUsaTerritories; + } + + return albersUsaTerritories.scale(1070); +} diff --git a/packages/examples/src/pleth/index.js b/packages/examples/src/pleth/index.js index e0db77f..b5e5497 100644 --- a/packages/examples/src/pleth/index.js +++ b/packages/examples/src/pleth/index.js @@ -1,5 +1,6 @@ import React, { useRef, useCallback } from 'react'; -import { geoAlbersUsa, geoPath } from 'd3-geo'; +import { geoPath } from 'd3-geo'; +import { geoAlbersUsaTerritories } from './geoAlbersUsaTerritories'; import { Wrapper } from './styles'; import { useResizeObserver } from './useResizeObserver'; import { useCache } from './useCache'; @@ -17,7 +18,9 @@ const Pleth = ({ layers, dataProviders, activeId }) => { ); // TODO make this dynamic per region. - const projection = geoAlbersUsa(); + const projection = geoAlbersUsaTerritories() + .scale(1300) + .translate([487.5, 305]); const path = geoPath(projection); diff --git a/packages/examples/yarn.lock b/packages/examples/yarn.lock index 1b4624d..ae7b118 100644 --- a/packages/examples/yarn.lock +++ b/packages/examples/yarn.lock @@ -1117,10 +1117,10 @@ resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-10.1.0.tgz#f0950bba18819512d42f7197e56c518aa491cf18" integrity sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg== -"@datavis-tech/polylabel@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@datavis-tech/polylabel/-/polylabel-1.2.0.tgz#814d8aa4307d280a71600c9e6ee496620f0fc6bc" - integrity sha512-qpdeaMSMdDd5PwywM2e12UB3iPsLAQfiam8OWhhq5Ci/c56k07OP2vSyI4uisxdBd9g4p5r/BFPs+C4zMovoSQ== +"@datavis-tech/polylabel@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@datavis-tech/polylabel/-/polylabel-1.3.0.tgz#2ddbefaaa70172630c41c9d5ff45397374f56221" + integrity sha512-TBs2CTXILNSOCtSreWeVNfwfLzACtaoSDjyjCBZ/Y3mCOkbBQMrlCrgQcgrxMpnv72PmJda3NGs+wQ3m0OzFSA== dependencies: tinyqueue "^2.0.3" @@ -1452,17 +1452,17 @@ "@svgr/plugin-svgo" "^4.3.1" loader-utils "^1.2.3" -"@testing-library/dom@^7.9.0": - version "7.15.0" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.15.0.tgz#f47d2c391406846177ad5153f51bd5c5ef0c972e" - integrity sha512-H+cQksHNYjxTS62S+exT5ZcBZeJXE3NDHUKs6MTopp4cMgd8DHX78IUohyUGqJRD1AthtgnKujrPTxYdWZ/w9w== +"@testing-library/dom@^7.14.2": + version "7.16.2" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.16.2.tgz#f7a20b5548817e5c7ed26077913372d977be90af" + integrity sha512-4fT5l5L+5gfNhUZVCg0wnSszbRJ7A1ZHEz32v7OzH3mcY5lUsK++brI3IB2L9F5zO4kSDc2TRGEVa8v2hgl9vA== dependencies: "@babel/runtime" "^7.10.2" aria-query "^4.0.2" dom-accessibility-api "^0.4.5" pretty-format "^25.5.0" -"@testing-library/jest-dom@^5.9.0": +"@testing-library/jest-dom@^5.10.1": version "5.10.1" resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.10.1.tgz#6508a9f007bd74e5d3c0b3135b668027ab663989" integrity sha512-uv9lLAnEFRzwUTN/y9lVVXVXlEzazDkelJtM5u92PsGkEasmdI+sfzhZHxSDzlhZVTrlLfuMh2safMr8YmzXLg== @@ -1477,18 +1477,18 @@ lodash "^4.17.15" redent "^3.0.0" -"@testing-library/react@^10.2.0": - version "10.2.1" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.2.1.tgz#f0c5ac9072ad54c29672150943f35d6617263f26" - integrity sha512-pv2jZhiZgN1/alz1aImhSasZAOPg3er2Kgcfg9fzuw7aKPLxVengqqR1n0CJANeErR1DqORauQaod+gGUgAJOQ== +"@testing-library/react@^10.3.0": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-10.3.0.tgz#d615385b8d86ef4d76142a423755d471b3673295" + integrity sha512-Rhn5uJK6lYHWzlGVbK6uAvheAW8AUoFYxTLGdDxgsJDaK/PYy5drWfW/6YpMMOKMw+u6jHHl4MNHlt5qLHnm0Q== dependencies: "@babel/runtime" "^7.10.2" - "@testing-library/dom" "^7.9.0" + "@testing-library/dom" "^7.14.2" -"@testing-library/user-event@^11.2.0": - version "11.4.2" - resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-11.4.2.tgz#90d98fd18455ae81d008e9b26e94d25e8d5bf846" - integrity sha512-Kut7G1L+ffozEhYTDNjV9C6RFbUfsKA05rGr1arwbSUoDZQ82OMmsyaXEDznT22Qc0PtZ1Hz3soX0pPosu8+Sw== +"@testing-library/user-event@^12.0.2": + version "12.0.2" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-12.0.2.tgz#66fa2c64a50b47726c008eacecb9a42b43cd9a2b" + integrity sha512-hJLv9saOJ7WJsRINPPTMmgEya85+L55FRRf1xgFO8HznaUO58YOf+cj+yf/POkhls9pVIPLRoGjzxgvmAsptYg== dependencies: "@babel/runtime" "^7.10.2" @@ -3551,7 +3551,17 @@ d3-fetch@^1.2.0: dependencies: d3-dsv "1" -d3-geo@^1.12.1: +d3-geo-projection@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/d3-geo-projection/-/d3-geo-projection-2.9.0.tgz#826db62f748e8ecd67cd00aced4c26a236ec030c" + integrity sha512-ZULvK/zBn87of5rWAfFMc9mJOipeSo57O+BBitsKIXmU4rTVAnX1kSsJkE0R+TxY8pGNoM1nbyRRE7GYHhdOEQ== + dependencies: + commander "2" + d3-array "1" + d3-geo "^1.12.0" + resolve "^1.1.10" + +d3-geo@^1.12.0, d3-geo@^1.12.1: version "1.12.1" resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.12.1.tgz#7fc2ab7414b72e59fbcbd603e80d9adc029b035f" integrity sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg== @@ -9104,6 +9114,13 @@ resolve@1.15.0: dependencies: path-parse "^1.0.6" +resolve@^1.1.10: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.15.1, resolve@^1.3.2, resolve@^1.8.1: version "1.15.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8"