LocalOrbitControls.vue 9.3 KB

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