index.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <template>
  2. <section class="app-container">
  3. <van-nav-bar :title="subjectInfo.name" />
  4. <count-down v-if="showCountDown" :time="5" @end-count-down="exec" />
  5. </section>
  6. </template>
  7. <script setup lang="ts">
  8. /*
  9. * 组件名: spatialOrientationAbility
  10. * 组件用途: 空间定向训练
  11. * 创建日期: 2024/8/16
  12. * 编写者: JutarryWu
  13. */
  14. import { shuffle } from 'lodash-es'
  15. import Url_forest from '/@/assets/images/task/spatialOrientationAbility/forest.png'
  16. import Url_hospital from '/@/assets/images/task/spatialOrientationAbility/hospital.png'
  17. import Url_lakes from '/@/assets/images/task/spatialOrientationAbility/lakes.png'
  18. import Url_massif from '/@/assets/images/task/spatialOrientationAbility/massif.png'
  19. import Url_cat from '/@/assets/images/task/spatialOrientationAbility/cat.png'
  20. import Url_flower from '/@/assets/images/task/spatialOrientationAbility/flower.png'
  21. import Url_car from '/@/assets/images/task/spatialOrientationAbility/car.png'
  22. import Url_trafficLight from '/@/assets/images/task/spatialOrientationAbility/trafficLight.png'
  23. import Url_stop from '/@/assets/images/task/spatialOrientationAbility/stop.png'
  24. import Url_house from '/@/assets/images/task/spatialOrientationAbility/house.png'
  25. interface IData {
  26. level?: number
  27. onceStartTime?: string
  28. onceEndTime?: string
  29. reactionTime?: number
  30. xAxis?: string | number
  31. yAxis?: string | number
  32. id?: number
  33. text?: string
  34. name?: string
  35. value?: string
  36. imgUrl?: string
  37. angle?: string
  38. }
  39. const subjectInfo = ref({
  40. name: '空间定向训练'
  41. })
  42. const showCountDown = ref(false) // 显示倒计时
  43. const levelNum = [3, 5, 7] // 正式测试:3个难度等级需要呈现的刺激目标数
  44. let tryCount = 3 // 正式测试:每个难度等级需要进行的试次数
  45. const showDataArr = ref<IData[]>([])
  46. let arrDataDemo: IData[] = [
  47. { id: 0, text: '森林', name: '森林', value: 'forest', imgUrl: Url_forest, angle: '', xAxis: '', yAxis: '' },
  48. { id: 1, text: '医院', name: '医院', value: 'hospital', imgUrl: Url_hospital, angle: '', xAxis: '', yAxis: '' },
  49. { id: 2, text: '湖泊', name: '湖泊', value: 'lakes', imgUrl: Url_lakes, angle: '', xAxis: '', yAxis: '' },
  50. { id: 3, text: '山', name: '山', value: 'massif', imgUrl: Url_massif, angle: '', xAxis: '', yAxis: '' },
  51. { id: 4, text: '猫', name: '猫', value: 'cat', imgUrl: Url_cat, angle: '', xAxis: '', yAxis: '' },
  52. { id: 5, text: '花', name: '花', value: 'flower', imgUrl: Url_flower, angle: '', xAxis: '', yAxis: '' },
  53. { id: 6, text: '车', name: '车', value: 'car', imgUrl: Url_car, angle: '', xAxis: '', yAxis: '' },
  54. {
  55. id: 7,
  56. text: '红绿灯',
  57. name: '红绿灯',
  58. value: 'trafficLight',
  59. imgUrl: Url_trafficLight,
  60. angle: '',
  61. xAxis: '',
  62. yAxis: ''
  63. },
  64. { id: 8, text: '停止牌', name: '停止牌', value: 'soldier', imgUrl: Url_stop, angle: '', xAxis: '', yAxis: '' },
  65. { id: 9, text: '房子', name: '房子', value: 'house', imgUrl: Url_house, angle: '', xAxis: '', yAxis: '' }
  66. ]
  67. /**
  68. * 生成不重叠随机点
  69. * @param centerX
  70. * @param centerY
  71. * @param radius
  72. * @param existingPoints
  73. */
  74. const generateRandomPoint = (
  75. centerX: number,
  76. centerY: number,
  77. radius: number,
  78. existingPoints: Record<string, any>[]
  79. ) => {
  80. let angle = Math.random() * 2 * Math.PI
  81. let distance = Math.sqrt(Math.random()) * radius // 确保点更均匀地分布在圆内
  82. let xAxis = centerX + distance * Math.cos(angle)
  83. let yAxis = centerY + distance * Math.sin(angle)
  84. // 检查是否与现有点重叠
  85. for (let point of existingPoints) {
  86. let dx = xAxis - point.xAxis
  87. let dy = yAxis - point.yAxis
  88. if (Math.sqrt(dx * dx + dy * dy) < radius / 3) {
  89. // 阈值设为半径的1/4
  90. return generateRandomPoint(centerX, centerY, radius, existingPoints) // 递归调用直到找到合适的点
  91. }
  92. }
  93. return { xAxis, yAxis }
  94. }
  95. const generateNonOverlappingPoints = (centerX: number, centerY: number, radius: number, num: number) => {
  96. let points = [{ xAxis: centerX, yAxis: centerY }] // 中心点
  97. for (let i = 0; i < num; i++) {
  98. let newPoint = generateRandomPoint(centerX, centerY, radius, points)
  99. points.push(newPoint)
  100. }
  101. return points.map((item) => {
  102. return {
  103. xAxis: (item.xAxis + 16) / 41.4,
  104. yAxis: (item.yAxis + 16) / 41.4
  105. }
  106. })
  107. }
  108. // 以下生成随机位置显示图例方法
  109. const initImgData = (level: number, num: number) => {
  110. // 随机生成6个物品的位置
  111. let items = generateNonOverlappingPoints(175, 175, 175, num - 1)
  112. arrDataDemo = shuffle(arrDataDemo)
  113. let tempItems: IData[] = arrDataDemo.slice(0, num)
  114. let extraInfo = {
  115. level: levelNum[level],
  116. onceStartTime: '',
  117. onceEndTime: '',
  118. reactionTime: 0
  119. }
  120. items.forEach((item, index) => {
  121. tempItems[index] = { ...tempItems[index], ...item, ...extraInfo }
  122. })
  123. return tempItems
  124. }
  125. const initImgDataList = () => {
  126. for (let i = 0; i < levelNum.length; i++) {
  127. while (tryCount > 0) {
  128. let tempData: IData[] = initImgData(i, levelNum[i])
  129. showDataArr.value = [...showDataArr.value, ...tempData]
  130. tryCount--
  131. }
  132. }
  133. showDataArr.value = shuffle(showDataArr.value)
  134. console.log('生成的随机点位:', showDataArr.value)
  135. }
  136. function exec() {
  137. showCountDown.value = false
  138. }
  139. onMounted(() => {
  140. showCountDown.value = true
  141. initImgDataList()
  142. })
  143. </script>
  144. <style scoped lang="less">
  145. .app-container {
  146. }
  147. </style>