Hello.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. <template>
  2. <q-layout
  3. ref="layout"
  4. view="lHh Lpr fff"
  5. :left-class="{'bg-grey-2': true}"
  6. >
  7. <q-toolbar slot="header" class="glossy">
  8. <q-btn
  9. flat
  10. @click="$refs.layout.toggleLeft()"
  11. >
  12. <q-icon name="menu" />
  13. </q-btn>
  14. <q-toolbar-title>
  15. Quasar App
  16. <div slot="subtitle">Running on Quasar v{{$q.version}}</div>
  17. </q-toolbar-title>
  18. </q-toolbar>
  19. <div slot="left">
  20. <!--
  21. Use <q-side-link> component
  22. instead of <q-item> for
  23. internal vue-router navigation
  24. -->
  25. <q-list no-border link inset-delimiter>
  26. <q-list-header>Essential Links</q-list-header>
  27. <q-item @click="launch('http://quasar-framework.org')">
  28. <q-item-side icon="school" />
  29. <q-item-main label="Docs" sublabel="quasar-framework.org" />
  30. </q-item>
  31. <q-item @click="launch('http://forum.quasar-framework.org')">
  32. <q-item-side icon="record_voice_over" />
  33. <q-item-main label="Forum" sublabel="forum.quasar-framework.org" />
  34. </q-item>
  35. <q-item @click="launch('https://gitter.im/quasarframework/Lobby')">
  36. <q-item-side icon="chat" />
  37. <q-item-main label="Gitter Channel" sublabel="Quasar Lobby" />
  38. </q-item>
  39. <q-item @click="launch('https://twitter.com/quasarframework')">
  40. <q-item-side icon="rss feed" />
  41. <q-item-main label="Twitter" sublabel="@quasarframework" />
  42. </q-item>
  43. </q-list>
  44. </div>
  45. <!--
  46. Replace following <div> with
  47. <router-view /> component
  48. if using subRoutes
  49. -->
  50. <div class="layout-padding logo-container non-selectable no-pointer-events">
  51. <div class="logo" :style="position">
  52. <img src="~assets/quasar-logo-full.svg">
  53. </div>
  54. </div>
  55. </q-layout>
  56. </template>
  57. <script>
  58. import {
  59. dom,
  60. event,
  61. openURL,
  62. QLayout,
  63. QToolbar,
  64. QToolbarTitle,
  65. QBtn,
  66. QIcon,
  67. QList,
  68. QListHeader,
  69. QItem,
  70. QItemSide,
  71. QItemMain
  72. } from 'quasar'
  73. const
  74. { viewport } = dom,
  75. { position } = event,
  76. moveForce = 30,
  77. rotateForce = 40,
  78. RAD_TO_DEG = 180 / Math.PI
  79. function getRotationFromAccel (accelX, accelY, accelZ) {
  80. /* Reference: http://stackoverflow.com/questions/3755059/3d-accelerometer-calculate-the-orientation#answer-30195572 */
  81. const sign = accelZ > 0 ? 1 : -1
  82. const miu = 0.001
  83. return {
  84. roll: Math.atan2(accelY, sign * Math.sqrt(Math.pow(accelZ, 2) + miu * Math.pow(accelX, 2))) * RAD_TO_DEG,
  85. pitch: -Math.atan2(accelX, Math.sqrt(Math.pow(accelY, 2) + Math.pow(accelZ, 2))) * RAD_TO_DEG
  86. }
  87. }
  88. export default {
  89. name: 'index',
  90. components: {
  91. QLayout,
  92. QToolbar,
  93. QToolbarTitle,
  94. QBtn,
  95. QIcon,
  96. QList,
  97. QListHeader,
  98. QItem,
  99. QItemSide,
  100. QItemMain
  101. },
  102. data () {
  103. return {
  104. orienting: window.DeviceOrientationEvent && !this.$q.platform.is.desktop,
  105. rotating: window.DeviceMotionEvent && !this.$q.platform.is.desktop,
  106. moveX: 0,
  107. moveY: 0,
  108. rotateY: 0,
  109. rotateX: 0
  110. }
  111. },
  112. computed: {
  113. position () {
  114. const transform = `rotateX(${this.rotateX}deg) rotateY(${this.rotateY}deg)`
  115. return {
  116. top: this.moveY + 'px',
  117. left: this.moveX + 'px',
  118. '-webkit-transform': transform,
  119. '-ms-transform': transform,
  120. transform
  121. }
  122. }
  123. },
  124. methods: {
  125. launch (url) {
  126. openURL(url)
  127. },
  128. move (evt) {
  129. const
  130. {width, height} = viewport(),
  131. {top, left} = position(evt),
  132. halfH = height / 2,
  133. halfW = width / 2
  134. this.moveX = (left - halfW) / halfW * -moveForce
  135. this.moveY = (top - halfH) / halfH * -moveForce
  136. this.rotateY = (left / width * rotateForce * 2) - rotateForce
  137. this.rotateX = -((top / height * rotateForce * 2) - rotateForce)
  138. },
  139. rotate (evt) {
  140. if (evt.rotationRate &&
  141. evt.rotationRate.beta !== null &&
  142. evt.rotationRate.gamma !== null) {
  143. this.rotateX = evt.rotationRate.beta * 0.7
  144. this.rotateY = evt.rotationRate.gamma * -0.7
  145. }
  146. else {
  147. /* evt.acceleration may be null in some cases, so we'll fall back
  148. to evt.accelerationIncludingGravity */
  149. const
  150. accelX = evt.acceleration.x || evt.accelerationIncludingGravity.x,
  151. accelY = evt.acceleration.y || evt.accelerationIncludingGravity.y,
  152. accelZ = evt.acceleration.z || evt.accelerationIncludingGravity.z - 9.81,
  153. rotation = getRotationFromAccel(accelX, accelY, accelZ)
  154. this.rotateX = rotation.roll * 0.7
  155. this.rotateY = rotation.pitch * -0.7
  156. }
  157. },
  158. orient (evt) {
  159. if (evt.beta === null || evt.gamma === null) {
  160. window.removeEventListener('deviceorientation', this.orient, false)
  161. this.orienting = false
  162. window.addEventListener('devicemotion', this.rotate, false)
  163. }
  164. else {
  165. this.rotateX = evt.beta * 0.7
  166. this.rotateY = evt.gamma * -0.7
  167. }
  168. }
  169. },
  170. mounted () {
  171. this.$nextTick(() => {
  172. if (this.orienting) {
  173. window.addEventListener('deviceorientation', this.orient, false)
  174. }
  175. else if (this.rotating) {
  176. window.addEventListener('devicemove', this.rotate, false)
  177. }
  178. else {
  179. document.addEventListener('mousemove', this.move)
  180. }
  181. })
  182. },
  183. beforeDestroy () {
  184. if (this.orienting) {
  185. window.removeEventListener('deviceorientation', this.orient, false)
  186. }
  187. else if (this.rotating) {
  188. window.removeEventListener('devicemove', this.rotate, false)
  189. }
  190. else {
  191. document.removeEventListener('mousemove', this.move)
  192. }
  193. }
  194. }
  195. </script>
  196. <style lang="stylus">
  197. .logo-container
  198. width 255px
  199. height 242px
  200. perspective 800px
  201. position absolute
  202. top 50%
  203. left 50%
  204. transform translateX(-50%) translateY(-50%)
  205. .logo
  206. position absolute
  207. transform-style preserve-3d
  208. </style>