@ericchen1990/pano-view 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ import * as react from 'react';
2
2
  import { ReactNode, ComponentPropsWithoutRef } from 'react';
3
3
  import { Texture, ColorRepresentation, Vector3 } from 'three';
4
4
 
5
- declare const MAX_HOTSPOT_PITCH = 89.9;
5
+ declare const MAX_HOTSPOT_PITCH = 90;
6
6
  type HotspotPosition = {
7
7
  /** Horizontal panorama angle in degrees. Positive values look right. */
8
8
  yaw: number;
@@ -36,6 +36,8 @@ type HotspotCommonProps = {
36
36
  width?: number;
37
37
  /** Angular height in degrees. Defaults to 8. */
38
38
  height?: number;
39
+ /** Overall multiplier for the hotspot's angular width and height. Defaults to 1. */
40
+ scale?: number;
39
41
  /** Defaults to "billboard". */
40
42
  mode?: HotspotMode;
41
43
  /**
@@ -305,7 +307,7 @@ type PolygonVerticesChangeEvent = {
305
307
  position: HotspotPosition;
306
308
  startPosition: HotspotPosition;
307
309
  };
308
- type PolygonHotspotProps = Omit<HotspotCommonProps, "position" | "width" | "height" | "mode" | "distance" | "scaleMode" | "onDragStart" | "onPositionChange" | "onDragEnd"> & {
310
+ type PolygonHotspotProps = Omit<HotspotCommonProps, "position" | "width" | "height" | "scale" | "mode" | "distance" | "scaleMode" | "rotation" | "onDragStart" | "onPositionChange" | "onDragEnd"> & {
309
311
  vertices: HotspotPosition[];
310
312
  fill?: ColorRepresentation;
311
313
  fillOpacity?: number;
@@ -337,7 +339,7 @@ type PolylineVerticesChangeEvent = {
337
339
  position: HotspotPosition;
338
340
  startPosition: HotspotPosition;
339
341
  };
340
- type PolylineHotspotProps = Omit<HotspotCommonProps, "position" | "width" | "height" | "mode" | "distance" | "scaleMode" | "onDragStart" | "onPositionChange" | "onDragEnd"> & {
342
+ type PolylineHotspotProps = Omit<HotspotCommonProps, "position" | "width" | "height" | "scale" | "mode" | "distance" | "scaleMode" | "rotation" | "onDragStart" | "onPositionChange" | "onDragEnd"> & {
341
343
  vertices: HotspotPosition[];
342
344
  stroke?: ColorRepresentation;
343
345
  /** Screen-space line width in CSS pixels. Defaults to 2. */
@@ -464,6 +466,7 @@ type PointHotspotDefinitionBase = HotspotDefinitionBase & {
464
466
  position: HotspotPosition;
465
467
  width?: number;
466
468
  height?: number;
469
+ scale?: number;
467
470
  mode?: HotspotMode;
468
471
  distance?: number;
469
472
  scaleMode?: HotspotScaleMode;
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as react from 'react';
2
2
  import { ReactNode, ComponentPropsWithoutRef } from 'react';
3
3
  import { Texture, ColorRepresentation, Vector3 } from 'three';
4
4
 
5
- declare const MAX_HOTSPOT_PITCH = 89.9;
5
+ declare const MAX_HOTSPOT_PITCH = 90;
6
6
  type HotspotPosition = {
7
7
  /** Horizontal panorama angle in degrees. Positive values look right. */
8
8
  yaw: number;
@@ -36,6 +36,8 @@ type HotspotCommonProps = {
36
36
  width?: number;
37
37
  /** Angular height in degrees. Defaults to 8. */
38
38
  height?: number;
39
+ /** Overall multiplier for the hotspot's angular width and height. Defaults to 1. */
40
+ scale?: number;
39
41
  /** Defaults to "billboard". */
40
42
  mode?: HotspotMode;
41
43
  /**
@@ -305,7 +307,7 @@ type PolygonVerticesChangeEvent = {
305
307
  position: HotspotPosition;
306
308
  startPosition: HotspotPosition;
307
309
  };
308
- type PolygonHotspotProps = Omit<HotspotCommonProps, "position" | "width" | "height" | "mode" | "distance" | "scaleMode" | "onDragStart" | "onPositionChange" | "onDragEnd"> & {
310
+ type PolygonHotspotProps = Omit<HotspotCommonProps, "position" | "width" | "height" | "scale" | "mode" | "distance" | "scaleMode" | "rotation" | "onDragStart" | "onPositionChange" | "onDragEnd"> & {
309
311
  vertices: HotspotPosition[];
310
312
  fill?: ColorRepresentation;
311
313
  fillOpacity?: number;
@@ -337,7 +339,7 @@ type PolylineVerticesChangeEvent = {
337
339
  position: HotspotPosition;
338
340
  startPosition: HotspotPosition;
339
341
  };
340
- type PolylineHotspotProps = Omit<HotspotCommonProps, "position" | "width" | "height" | "mode" | "distance" | "scaleMode" | "onDragStart" | "onPositionChange" | "onDragEnd"> & {
342
+ type PolylineHotspotProps = Omit<HotspotCommonProps, "position" | "width" | "height" | "scale" | "mode" | "distance" | "scaleMode" | "rotation" | "onDragStart" | "onPositionChange" | "onDragEnd"> & {
341
343
  vertices: HotspotPosition[];
342
344
  stroke?: ColorRepresentation;
343
345
  /** Screen-space line width in CSS pixels. Defaults to 2. */
@@ -464,6 +466,7 @@ type PointHotspotDefinitionBase = HotspotDefinitionBase & {
464
466
  position: HotspotPosition;
465
467
  width?: number;
466
468
  height?: number;
469
+ scale?: number;
467
470
  mode?: HotspotMode;
468
471
  distance?: number;
469
472
  scaleMode?: HotspotScaleMode;
package/dist/index.mjs CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  useRef
21
21
  } from "react";
22
22
  import { Euler, MathUtils, PerspectiveCamera } from "three";
23
- var MAX_PITCH = 89.9;
23
+ var MAX_PITCH = 90;
24
24
  var INERTIA_ROTATION_DAMPING = 8;
25
25
  var INERTIA_ZOOM_DAMPING = 12;
26
26
  var DEFAULT_ROTATE_DAMPING = 14;
@@ -559,9 +559,10 @@ import { BackSide } from "three";
559
559
  import { MathUtils as MathUtils2, Vector3 } from "three";
560
560
 
561
561
  // src/hotspot/types.ts
562
- var MAX_HOTSPOT_PITCH = 89.9;
562
+ var MAX_HOTSPOT_PITCH = 90;
563
563
 
564
564
  // src/hotspot/coordinates.ts
565
+ var POLE_EPSILON_DEGREES = 1e-6;
565
566
  function normalizePanoYaw(yaw) {
566
567
  if (!Number.isFinite(yaw)) {
567
568
  return 0;
@@ -572,12 +573,18 @@ function clampPanoPitch(pitch) {
572
573
  if (!Number.isFinite(pitch)) {
573
574
  return 0;
574
575
  }
575
- return MathUtils2.clamp(pitch, -MAX_HOTSPOT_PITCH, MAX_HOTSPOT_PITCH);
576
+ const clamped = MathUtils2.clamp(
577
+ pitch,
578
+ -MAX_HOTSPOT_PITCH,
579
+ MAX_HOTSPOT_PITCH
580
+ );
581
+ return Math.abs(clamped) >= MAX_HOTSPOT_PITCH - POLE_EPSILON_DEGREES ? Math.sign(clamped) * MAX_HOTSPOT_PITCH : clamped;
576
582
  }
577
583
  function normalizePanoPosition(position) {
584
+ const pitch = clampPanoPitch(position.pitch);
578
585
  return {
579
- yaw: normalizePanoYaw(position.yaw),
580
- pitch: clampPanoPitch(position.pitch)
586
+ yaw: Math.abs(pitch) === MAX_HOTSPOT_PITCH ? 0 : normalizePanoYaw(position.yaw),
587
+ pitch
581
588
  };
582
589
  }
583
590
  function panoPositionToVector3(position, radius = 1) {
@@ -705,7 +712,7 @@ var PanoView = forwardRef2(
705
712
  const normalizedInitialView = useMemo2(
706
713
  () => ({
707
714
  yaw: initialView?.yaw ?? DEFAULT_VIEW.yaw,
708
- pitch: initialView?.pitch ?? DEFAULT_VIEW.pitch,
715
+ pitch: clampPanoPitch(initialView?.pitch ?? DEFAULT_VIEW.pitch),
709
716
  fov: Math.max(
710
717
  normalizedMinFov,
711
718
  Math.min(initialView?.fov ?? DEFAULT_VIEW.fov, normalizedMaxFov)
@@ -2505,6 +2512,9 @@ function angularSizeToWorldSize(size, radius) {
2505
2512
  const safeSize = Number.isFinite(size) ? MathUtils4.clamp(Math.abs(size), MIN_ANGULAR_SIZE, MAX_ANGULAR_SIZE) : MIN_ANGULAR_SIZE;
2506
2513
  return 2 * radius * Math.tan(MathUtils4.degToRad(safeSize) / 2);
2507
2514
  }
2515
+ function resolveScale(scale) {
2516
+ return Number.isFinite(scale) && scale > 0 ? scale : 1;
2517
+ }
2508
2518
  function resolveDistance(placement, distance, width, height) {
2509
2519
  const maximumDistance = maximumHotspotDistance(width, height);
2510
2520
  if (placement === "surface") {
@@ -2569,6 +2579,7 @@ function HotspotAnchor({
2569
2579
  position,
2570
2580
  width,
2571
2581
  height,
2582
+ scale = 1,
2572
2583
  useAngularScale = true,
2573
2584
  focusContent,
2574
2585
  mode = "billboard",
@@ -2597,7 +2608,15 @@ function HotspotAnchor({
2597
2608
  const normalizedPosition = normalizePanoPosition(position);
2598
2609
  const rendering = internalOrientation && internalPlacement ? { orientation: internalOrientation, placement: internalPlacement } : HOTSPOT_MODE_RENDERING[mode];
2599
2610
  const { orientation: orientation2, placement } = rendering;
2600
- const resolvedDistance = resolveDistance(placement, distance, width, height);
2611
+ const resolvedScale = resolveScale(scale);
2612
+ const scaledWidth = width * resolvedScale;
2613
+ const scaledHeight = height * resolvedScale;
2614
+ const resolvedDistance = resolveDistance(
2615
+ placement,
2616
+ distance,
2617
+ scaledWidth,
2618
+ scaledHeight
2619
+ );
2601
2620
  const worldPosition = useMemo6(
2602
2621
  () => panoPositionToVector3(normalizedPosition, resolvedDistance),
2603
2622
  [normalizedPosition.pitch, normalizedPosition.yaw, resolvedDistance]
@@ -2606,8 +2625,8 @@ function HotspotAnchor({
2606
2625
  () => createSurfaceQuaternion(normalizedPosition),
2607
2626
  [normalizedPosition.pitch, normalizedPosition.yaw]
2608
2627
  );
2609
- const worldWidth = angularSizeToWorldSize(width, resolvedDistance);
2610
- const worldHeight = angularSizeToWorldSize(height, resolvedDistance);
2628
+ const worldWidth = angularSizeToWorldSize(scaledWidth, resolvedDistance);
2629
+ const worldHeight = angularSizeToWorldSize(scaledHeight, resolvedDistance);
2611
2630
  const focusGeometry = useMemo6(() => {
2612
2631
  const planeGeometry = new PlaneGeometry3(1, 1);
2613
2632
  const geometry = new EdgesGeometry(planeGeometry);