Videos
This commit is contained in:
parent
b98f0e3904
commit
a8165249a4
24 changed files with 1486 additions and 105 deletions
|
|
@ -105,17 +105,18 @@ export class DashboardRecorder {
|
|||
|
||||
const mapBox = await this.page.locator('[data-tutorial="map"]').boundingBox();
|
||||
if (!mapBox) throw new Error('Map container has no bounding box');
|
||||
const clear = await this.clickableBox(mapBox);
|
||||
|
||||
const projected = snapshot.features
|
||||
.filter((feature) => feature.count > 0)
|
||||
.map((feature) => {
|
||||
const point = projectFromBounds(feature, snapshot.bounds, mapBox);
|
||||
if (!point) return null;
|
||||
const centerX = mapBox.x + mapBox.width / 2;
|
||||
const centerY = mapBox.y + mapBox.height / 2;
|
||||
const centerX = clear.left + (clear.right - clear.left) / 2;
|
||||
const centerY = clear.top + (clear.bottom - clear.top) / 2;
|
||||
const distanceFromCenter = Math.hypot(
|
||||
(point.x - centerX) / (mapBox.width / 2),
|
||||
(point.y - centerY) / (mapBox.height / 2)
|
||||
(point.x - centerX) / Math.max(1, (clear.right - clear.left) / 2),
|
||||
(point.y - centerY) / Math.max(1, (clear.bottom - clear.top) / 2)
|
||||
);
|
||||
return {
|
||||
h3: feature.h3,
|
||||
|
|
@ -136,10 +137,10 @@ export class DashboardRecorder {
|
|||
);
|
||||
const clearOfChrome = onScreen.filter(
|
||||
(target) =>
|
||||
target.x >= mapBox.x + 80 &&
|
||||
target.x <= mapBox.x + mapBox.width - 130 &&
|
||||
target.y >= mapBox.y + 105 &&
|
||||
target.y <= mapBox.y + mapBox.height - 115
|
||||
target.x >= clear.left &&
|
||||
target.x <= clear.right &&
|
||||
target.y >= clear.top &&
|
||||
target.y <= clear.bottom
|
||||
);
|
||||
|
||||
const candidates = (clearOfChrome.length > 0 ? clearOfChrome : onScreen).sort(
|
||||
|
|
@ -151,6 +152,37 @@ export class DashboardRecorder {
|
|||
return candidates.slice(0, limit).map(({ score: _score, ...target }) => target);
|
||||
}
|
||||
|
||||
/**
|
||||
* The pixel rect inside `mapBox` that's safe to click — i.e. not under
|
||||
* the dashboard's left filters pane, right details pane, or (on mobile)
|
||||
* the floating MobileBottomSheet. We detect the sheet via the only
|
||||
* `section.rounded-t-2xl` in the DOM and treat its top as a hard
|
||||
* bottom-clear limit; without that, hex() would happily return a
|
||||
* polygon hidden under the sheet on 9x16 cuts.
|
||||
*/
|
||||
private async clickableBox(mapBox: {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}): Promise<{ top: number; bottom: number; left: number; right: number }> {
|
||||
let bottomClear = mapBox.y + mapBox.height - 115;
|
||||
const sheet = await this.page
|
||||
.locator('section[class*="rounded-t-2xl"]')
|
||||
.first()
|
||||
.boundingBox()
|
||||
.catch(() => null);
|
||||
if (sheet && sheet.y > mapBox.y && sheet.y < bottomClear) {
|
||||
bottomClear = sheet.y - 16;
|
||||
}
|
||||
return {
|
||||
top: mapBox.y + 105,
|
||||
bottom: bottomClear,
|
||||
left: mapBox.x + 80,
|
||||
right: mapBox.x + mapBox.width - 130,
|
||||
};
|
||||
}
|
||||
|
||||
private async captureResponse(response: Response): Promise<void> {
|
||||
const kind = classifyApiRequest(response.url());
|
||||
if (!kind || !response.ok()) return;
|
||||
|
|
@ -249,6 +281,7 @@ export class DashboardRecorder {
|
|||
|
||||
const mapBox = await this.page.locator('[data-tutorial="map"]').boundingBox();
|
||||
if (!mapBox) throw new Error('Map container has no bounding box');
|
||||
const clear = await this.clickableBox(mapBox);
|
||||
|
||||
const projected = snapshot.features
|
||||
.filter((feature) => feature.properties.count > 0)
|
||||
|
|
@ -256,11 +289,11 @@ export class DashboardRecorder {
|
|||
const [lon, lat] = feature.properties.centroid;
|
||||
const point = projectFromBounds({ lat, lon }, snapshot.bounds, mapBox);
|
||||
if (!point) return null;
|
||||
const centerX = mapBox.x + mapBox.width / 2;
|
||||
const centerY = mapBox.y + mapBox.height / 2;
|
||||
const centerX = clear.left + (clear.right - clear.left) / 2;
|
||||
const centerY = clear.top + (clear.bottom - clear.top) / 2;
|
||||
const distanceFromCenter = Math.hypot(
|
||||
(point.x - centerX) / (mapBox.width / 2),
|
||||
(point.y - centerY) / (mapBox.height / 2)
|
||||
(point.x - centerX) / Math.max(1, (clear.right - clear.left) / 2),
|
||||
(point.y - centerY) / Math.max(1, (clear.bottom - clear.top) / 2)
|
||||
);
|
||||
return {
|
||||
h3: feature.properties.postcode,
|
||||
|
|
@ -281,10 +314,10 @@ export class DashboardRecorder {
|
|||
);
|
||||
const clearOfChrome = onScreen.filter(
|
||||
(target) =>
|
||||
target.x >= mapBox.x + 80 &&
|
||||
target.x <= mapBox.x + mapBox.width - 130 &&
|
||||
target.y >= mapBox.y + 105 &&
|
||||
target.y <= mapBox.y + mapBox.height - 115
|
||||
target.x >= clear.left &&
|
||||
target.x <= clear.right &&
|
||||
target.y >= clear.top &&
|
||||
target.y <= clear.bottom
|
||||
);
|
||||
|
||||
const candidates = (clearOfChrome.length > 0 ? clearOfChrome : onScreen).sort(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue