1
0

LocalOrbitControls.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. <script lang="ts" setup>
  2. import type { Camera } from 'three'
  3. import { OrbitControls } from 'three-stdlib'
  4. import { onMounted, onUnmounted, ref, unref } from 'vue'
  5. import type { TresVector3 } from '@tresjs/core'
  6. import { extend, useRenderLoop, useTresContext } from '@tresjs/core'
  7. import { useEventListener } from '@vueuse/core'
  8. export interface OrbitControlsProps {
  9. /**
  10. * Whether to make this the default controls.
  11. *
  12. * @default false
  13. * @type {boolean}
  14. * @memberof OrbitControlsProps
  15. */
  16. makeDefault?: boolean
  17. /**
  18. * The camera to control.
  19. *
  20. * @type {Camera}
  21. * @memberof OrbitControlsProps
  22. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.camera
  23. */
  24. camera?: Camera
  25. /**
  26. * The dom element to listen to.
  27. *
  28. * @type {HTMLElement}
  29. * @memberof OrbitControlsProps
  30. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.domElement
  31. */
  32. domElement?: HTMLElement
  33. /**
  34. * The target to orbit around.
  35. *
  36. * @type {TresVector3}
  37. * @memberof OrbitControlsProps
  38. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.target
  39. */
  40. target?: TresVector3
  41. /**
  42. * Whether to enable damping (inertia)
  43. *
  44. * @default false
  45. * @type {boolean}
  46. * @memberof OrbitControlsProps
  47. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableDamping
  48. */
  49. enableDamping?: boolean
  50. /**
  51. * The damping inertia used if `.enableDamping` is set to true
  52. *
  53. * @default 0.05
  54. * @type {number}
  55. * @memberof OrbitControlsProps
  56. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.dampingFactor
  57. */
  58. dampingFactor?: number
  59. /**
  60. * Set to true to automatically rotate around the target.
  61. *
  62. * @default false
  63. * @type {boolean}
  64. * @memberof OrbitControlsProps
  65. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.autoRotate
  66. */
  67. autoRotate?: boolean
  68. /**
  69. * How fast to rotate around the target if `.autoRotate` is true.
  70. *
  71. * @default 2
  72. * @type {number}
  73. * @memberof OrbitControlsProps
  74. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.autoRotateSpeed
  75. */
  76. autoRotateSpeed?: number
  77. /**
  78. * Whether to enable panning.
  79. *
  80. * @default true
  81. * @type {boolean}
  82. * @memberof OrbitControlsProps
  83. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enablePan
  84. */
  85. enablePan?: boolean
  86. /**
  87. * How fast to pan the camera when the keyboard is used. Default is 7.0 pixels per keypress.
  88. *
  89. * @default 7.0
  90. * @type {number}
  91. * @memberof OrbitControlsProps
  92. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.keyPanSpeed
  93. */
  94. keyPanSpeed?: number
  95. /**
  96. * This object contains references to the keycodes for controlling camera panning.
  97. * Default is the 4 arrow keys.
  98. *
  99. * @default `{ LEFT: 'ArrowLeft', UP: 'ArrowUp', RIGHT: 'ArrowRight', BOTTOM: 'ArrowDown' }`
  100. * @type Record<string, string>
  101. * @memberof OrbitControlsProps
  102. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.keys
  103. */
  104. keys?: Record<string, string>
  105. /**
  106. * How far you can orbit horizontally, upper limit.
  107. * If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ],
  108. * with ( max - min < 2 PI ). Default is Infinity.
  109. *
  110. * @default Infinity
  111. * @type {number}
  112. * @memberof OrbitControlsProps
  113. * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxAzimuthAngle
  114. */
  115. maxAzimuthAngle?: number
  116. /**
  117. * How far you can orbit horizontally, lower limit.
  118. * If set, the interval [ min, max ] must be a sub-interval of [ - 2 PI, 2 PI ],
  119. * with ( max - min < 2 PI ).
  120. * Default is - Infinity.
  121. *
  122. * @default -Infinity
  123. * @type {number}
  124. * @memberof OrbitControlsProps
  125. * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minAzimuthAngle
  126. */
  127. minAzimuthAngle?: number
  128. /**
  129. * How far you can orbit vertically, upper limit.
  130. * Range is 0 to Math.PI radians, and default is Math.PI.
  131. *
  132. * @default Math.PI
  133. * @type {number}
  134. * @memberof OrbitControlsProps
  135. * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxPolarAngle
  136. */
  137. maxPolarAngle?: number
  138. /**
  139. * How far you can orbit vertically, lower limit.
  140. * Range is 0 to Math.PI radians, and default is 0.
  141. *
  142. * @default 0
  143. * @type {number}
  144. * @memberof OrbitControlsProps
  145. * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minPolarAngle
  146. */
  147. minPolarAngle?: number
  148. /**
  149. * The minimum distance of the camera to the target.
  150. * Default is 0.
  151. *
  152. * @default 0
  153. * @type {number}
  154. * @memberof OrbitControlsProps
  155. * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minDistance
  156. */
  157. minDistance?: number
  158. /**
  159. * The maximum distance of the camera to the target.
  160. * Default is Infinity.
  161. *
  162. * @default Infinity
  163. * @type {number}
  164. * @memberof OrbitControlsProps
  165. * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxDistance
  166. */
  167. maxDistance?: number
  168. /**
  169. * The minimum field of view angle, in radians.
  170. * Default is 0.
  171. *
  172. * @default 0
  173. * @type {number}
  174. * @memberof OrbitControlsProps
  175. * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.minZoom
  176. */
  177. minZoom?: number
  178. /**
  179. * The maximum field of view angle, in radians.
  180. * ( OrthographicCamera only ).
  181. * Default is Infinity.
  182. *
  183. * @default Infinity
  184. * @type {number}
  185. * @memberof OrbitControlsProps
  186. * @see https://threejs.org/docs/index.html?q=orbi#examples/en/controls/OrbitControls.maxZoom
  187. */
  188. maxZoom?: number
  189. touches?: {
  190. ONE?: number
  191. TWO?: number
  192. }
  193. /**
  194. * Whether to enable zooming.
  195. *
  196. * @default true
  197. * @type {boolean}
  198. * @memberof OrbitControlsProps
  199. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableZoom
  200. */
  201. enableZoom?: boolean
  202. /**
  203. * How fast to zoom in and out. Default is 1.
  204. *
  205. * @default 1
  206. * @type {number}
  207. * @memberof OrbitControlsProps
  208. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.zoomSpeed
  209. */
  210. zoomSpeed?: number
  211. /**
  212. * Whether to enable rotating.
  213. *
  214. * @default true
  215. * @type {boolean}
  216. * @memberof OrbitControlsProps
  217. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.enableRotate
  218. */
  219. enableRotate?: boolean
  220. /**
  221. * How fast to rotate around the target. Default is 1.
  222. *
  223. * @default 1
  224. * @type {number}
  225. * @memberof OrbitControlsProps
  226. * @see https://threejs.org/docs/#examples/en/controls/OrbitControls.rotateSpeed
  227. */
  228. rotateSpeed?: number
  229. }
  230. // TODO: remove disable once eslint is updated to support vue 3.3
  231. const {
  232. autoRotate = false,
  233. autoRotateSpeed = 2,
  234. enableDamping = false,
  235. dampingFactor = 0.05,
  236. enablePan = true,
  237. keyPanSpeed = 7,
  238. maxAzimuthAngle = Number.POSITIVE_INFINITY,
  239. minAzimuthAngle = Number.NEGATIVE_INFINITY,
  240. maxPolarAngle = Math.PI,
  241. minPolarAngle = 0,
  242. minDistance = 0,
  243. maxDistance = Number.POSITIVE_INFINITY,
  244. minZoom = 0,
  245. maxZoom = Number.POSITIVE_INFINITY,
  246. enableZoom = true,
  247. zoomSpeed = 1,
  248. enableRotate = true,
  249. rotateSpeed = 1,
  250. target = [0, 0, 0],
  251. } = defineProps<OrbitControlsProps>()
  252. const emit = defineEmits(['change', 'start', 'end'])
  253. const { renderer, camera: activeCamera } = useTresContext()
  254. const controls = ref<OrbitControls | null>(null)
  255. extend({ OrbitControls })
  256. function addEventListeners() {
  257. useEventListener(controls.value as any, 'change', () => emit('change', controls.value))
  258. useEventListener(controls.value as any, 'start', () => emit('start', controls.value))
  259. useEventListener(controls.value as any, 'end', () => emit('end', controls.value))
  260. }
  261. const { onLoop } = useRenderLoop()
  262. onLoop(() => {
  263. if (controls.value && (enableDamping || autoRotate)) {
  264. controls.value.update()
  265. }
  266. })
  267. onMounted(() => {
  268. addEventListeners()
  269. })
  270. onUnmounted(() => {
  271. if (controls.value) {
  272. controls.value.dispose()
  273. }
  274. })
  275. </script>
  276. <template>
  277. <TresOrbitControls
  278. v-if="activeCamera && renderer"
  279. ref="controls"
  280. :target="target"
  281. :auto-rotate="autoRotate"
  282. :auto-rotate-speed="autoRotateSpeed"
  283. :enable-damping="enableDamping"
  284. :damping-factor="dampingFactor"
  285. :enable-pan="enablePan"
  286. :key-pan-speed="keyPanSpeed"
  287. :keys="keys"
  288. :max-azimuth-angle="maxAzimuthAngle"
  289. :min-azimuth-angle="minAzimuthAngle"
  290. :max-polar-angle="maxPolarAngle"
  291. :min-polar-angle="minPolarAngle"
  292. :min-distance="minDistance"
  293. :max-distance="maxDistance"
  294. :min-zoom="minZoom"
  295. :max-zoom="maxZoom"
  296. :touches="touches"
  297. :enable-zoom="enableZoom"
  298. :zoom-speed="zoomSpeed"
  299. :enable-rotate="enableRotate"
  300. :rotate-speed="rotateSpeed"
  301. :args="[unref(activeCamera) || camera, renderer?.domElement || domElement]"
  302. />
  303. </template>