Cubetti.vue 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <template>
  2. <div id="cubetti" ref="cubetti" />
  3. </template>
  4. <style lang="pcss" scoped>
  5. @media screen(sm) {
  6. #cubetti {
  7. position: absolute;
  8. width: 200px !important;
  9. height: 200px !important;
  10. top: -55px !important;
  11. left: 0px !important;
  12. }
  13. }
  14. #cubetti {
  15. position: absolute;
  16. width: 120px;
  17. height: 120px;
  18. overflow: visible;
  19. top: -24px;
  20. left: -22px;
  21. }
  22. </style>
  23. <script lang="ts" setup>
  24. import { AmbientLight } from 'three/src/lights/AmbientLight';
  25. import { DirectionalLight } from 'three/src/lights/DirectionalLight';
  26. import { BoxGeometry } from 'three/src/geometries/BoxGeometry';
  27. import { Mesh } from 'three/src/objects/Mesh';
  28. import { MeshStandardMaterial } from 'three/src/materials/MeshStandardMaterial';
  29. import { PerspectiveCamera } from 'three/src/cameras/PerspectiveCamera';
  30. import { Scene } from 'three/src/scenes/Scene';
  31. import { Vector3 } from 'three/src/math/Vector3';
  32. import { WebGLRenderer } from 'three/src/renderers/WebGLRenderer';
  33. import anime from 'animejs';
  34. import { randInt } from 'three/src/math/MathUtils';
  35. import { LinearToneMapping } from 'three/src/constants';
  36. const scene = new Scene()
  37. const camera = new PerspectiveCamera(80, 1, 0.1, 1000)
  38. const renderer = new WebGLRenderer({ antialias: true, alpha: true })
  39. renderer.setPixelRatio(window.devicePixelRatio);
  40. renderer.toneMapping = LinearToneMapping
  41. renderer.toneMappingExposure = 2.5
  42. const directionalLight = new DirectionalLight(0xffffff)
  43. const ambientLight = new AmbientLight(0xffffff)
  44. const geometry = new BoxGeometry(1, 1, 1)
  45. const blueMaterial = new MeshStandardMaterial({ color: 'dodgerblue' })
  46. const greenMaterial = new MeshStandardMaterial({ color: 'greenyellow' })
  47. const orangeMaterial = new MeshStandardMaterial({ color: 'orange' })
  48. const blueCube = new Mesh(geometry, blueMaterial)
  49. blueCube.position.set(-1, 0, 1)
  50. const greenCube = new Mesh(geometry, greenMaterial)
  51. greenCube.position.set(1, 0, 1)
  52. const orangeCube = new Mesh(geometry, orangeMaterial)
  53. orangeCube.position.set(0, 0, -1)
  54. const cubeGroup = new Scene()
  55. cubeGroup.add(blueCube, greenCube, orangeCube)
  56. const cubettiAnims = [
  57. { // group spin
  58. targets: [cubeGroup.rotation],
  59. keyframes: [
  60. { y: 2 * Math.PI, duration: 1000 },
  61. ],
  62. easing: 'easeOutCubic',
  63. duration: 1000,
  64. complete: playRandomAnimation,
  65. },
  66. { // floating cubes
  67. targets: [orangeCube.position, blueCube.position, greenCube.position],
  68. keyframes: [
  69. { y: -0.5, duration: 500/3 },
  70. { y: 0.5, duration: 707/3 },
  71. { y: 0.0, duration: 500/3 },
  72. ],
  73. easing: 'easeInOutSine',
  74. delay: anime.stagger(500/3),
  75. complete: playRandomAnimation,
  76. },
  77. { // rotating cubes
  78. targets: [orangeCube.rotation, blueCube.rotation, greenCube.rotation],
  79. x: randInt(0, 1) * 2 * Math.PI, y: randInt(0, 1) * 2 * Math.PI, z: randInt(0, 1) * 2 * Math.PI, duration: 1000,
  80. easing: 'easeOutSine',
  81. delay: anime.stagger(500/3),
  82. complete: playRandomAnimation
  83. }
  84. ]
  85. const cubetti = ref()
  86. function playRandomAnimation() {
  87. setTimeout(() => {
  88. anime(cubettiAnims[randInt(0, cubettiAnims.length-1)])
  89. }, randInt(1000, 8000))
  90. }
  91. const animate = () => {
  92. requestAnimationFrame(animate)
  93. renderer.render(scene, camera)
  94. }
  95. const resizeCanvas = () => {
  96. if (window.innerWidth < 640) {
  97. renderer.setSize(120, 120);
  98. } else {
  99. renderer.setSize(200, 200);
  100. }
  101. }
  102. onMounted(() => {
  103. scene.add(camera)
  104. scene.add(ambientLight, directionalLight)
  105. scene.add(cubeGroup)
  106. // renderer.setSize(200, 200)
  107. resizeCanvas();
  108. camera.position.copy((new Vector3(-2, 1.5, 2)).multiplyScalar(1.2))
  109. camera.lookAt(0, 0, 0)
  110. scene.background = null
  111. cubetti.value.appendChild(renderer.domElement)
  112. window.addEventListener('resize', resizeCanvas);
  113. playRandomAnimation()
  114. animate()
  115. })
  116. onUnmounted(() => {
  117. window.removeEventListener('resize', resizeCanvas);
  118. })
  119. </script>