index.vue 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. <template>
  2. <div class="paint" v-show="showPaint && role == 'leader'">
  3. <div class="toolbar">
  4. <ul>
  5. <li v-show="show == false" @click="start">
  6. <i class="iconfont iconkd_tagging"></i>
  7. <div>标记</div>
  8. </li>
  9. <li v-if="show" @click="end">
  10. <i class="iconfont iconclose"></i>
  11. <div>关闭</div>
  12. </li>
  13. </ul>
  14. </div>
  15. </div>
  16. </template>
  17. <script>
  18. import { app } from "@/core"
  19. import { objects } from "@/core/base"
  20. import config from "@/config"
  21. import { getRole, sendToH5,sendToApp } from "../../../socket"
  22. import settings from "@/core/settings"
  23. import math from "@/core/util/math"
  24. import convertTool from "@/core/util/convertTool"
  25. import texture from "@/core/util/texture.js"
  26. import lerp from "@/core/util/lerp"
  27. import transitions from "@/core/util/transitions"
  28. import easing from "@/core/util/easing"
  29. let meshGroup = null //new THREE.Object3D()
  30. let circles = []
  31. const map = texture.load(config.getStaticResource("img/scene_tabele.png?v=1"), null, null, {
  32. antialias: false,
  33. })
  34. export default {
  35. props: {
  36. showPaint: Boolean,
  37. },
  38. data() {
  39. return {
  40. role: getRole(),
  41. show: false,
  42. flags: [],
  43. canUndo: false,
  44. colorA: "#02c8ae",
  45. colorB: "#2e98fe",
  46. }
  47. },
  48. created() {
  49. const self = this
  50. if (meshGroup == null) {
  51. meshGroup = new THREE.Object3D()
  52. meshGroup.name = "shop-circles"
  53. if (app.ready) {
  54. app.model.add(meshGroup)
  55. } else {
  56. this.$bus.on("ready", function() {
  57. app.model.add(meshGroup)
  58. })
  59. }
  60. }
  61. function remove() {
  62. setTimeout(() => {
  63. self.flags.shift()
  64. if (self.flags.length) {
  65. remove()
  66. }
  67. self.updateCirclesDrawing(self.flags)
  68. }, 1000)
  69. }
  70. function syncAction(data) {
  71. if (data.type == "flags") {
  72. self.flags.push(data.data)
  73. self.updateCirclesDrawing(self.flags)
  74. remove()
  75. }
  76. }
  77. this.$bus.on("shop/sync/action", syncAction)
  78. this.$once("hook:beforeDestroy", () => {
  79. this.$bus.off("shop/sync/action", syncAction)
  80. this.show = false
  81. this.flags = []
  82. this.updateCirclesDrawing(this.flags)
  83. })
  84. },
  85. watch: {
  86. show() {
  87. sendToApp('cart',!this.show)
  88. this.$bus.emit("shop/header/disable", this.show)
  89. setTimeout(() => {
  90. app.play.control.noFly = this.show
  91. }, 300);
  92. },
  93. },
  94. mounted() {
  95. var self = this
  96. function draw(e) {
  97. if (!self.show) {
  98. return
  99. }
  100. const x = (e.touches[0] || e).clientX
  101. const y = (e.touches[0] || e).clientY
  102. const f = {
  103. sid: Date.now(),
  104. pos: self.transformTo3d({ x, y }),
  105. color: self.colorA,
  106. }
  107. self.flags.push(f)
  108. self.updateCirclesDrawing(self.flags)
  109. setTimeout(() => {
  110. self.flags.shift()
  111. self.updateCirclesDrawing(self.flags)
  112. }, 1000)
  113. sendToH5({ type: "flags", data: f })
  114. }
  115. const $player = document.getElementById("player")
  116. $player.addEventListener("mousedown", draw)
  117. $player.addEventListener("touchstart", draw)
  118. this.role = getRole()
  119. },
  120. methods: {
  121. start() {
  122. this.show = true
  123. },
  124. undo() {
  125. this.flags.pop()
  126. this.updateCirclesDrawing(this.flags)
  127. },
  128. end() {
  129. this.show = false
  130. this.flags = []
  131. this.updateCirclesDrawing(this.flags)
  132. },
  133. updateCirclesDrawing(flags) {
  134. //呈现一系列circles 其中包含已经绘制好的
  135. var dels = []
  136. circles.forEach(circle => {
  137. //检查是否有要删除的
  138. var find = flags.find(info => circle.sid == info.sid)
  139. if (!find) {
  140. dels.push(circle)
  141. }
  142. })
  143. dels.forEach(circle => this.fadeCircle(circle))
  144. flags.forEach(info => {
  145. //再添加新的
  146. var circle = meshGroup.children.find(circle => circle.sid == info.sid)
  147. if (circle) {
  148. //如果要修改什么属性在这修改
  149. } else {
  150. this.createCircle(info.sid, info.pos, info.color)
  151. }
  152. })
  153. },
  154. transformTo3d(pos2d) {
  155. //获取三维坐标
  156. const data = new THREE.Vector3()
  157. const mouse = new THREE.Vector2()
  158. math.convertScreenPositionToNDC(pos2d.x, pos2d.y, mouse)
  159. var intersect = convertTool.getMouseIntersect(
  160. objects.player.camera,
  161. [objects.model.skybox],
  162. mouse
  163. )
  164. if (!intersect) {
  165. console.error("no intersect ??")
  166. } else {
  167. data.copy(intersect.point)
  168. var dir = data
  169. .clone()
  170. .sub(objects.player.position)
  171. .normalize()
  172. data.copy(objects.player.position.clone().add(dir))
  173. }
  174. return data
  175. },
  176. createCircle(sid, pos, color) {
  177. //绘制新的圈
  178. var circle = new THREE.Sprite(this.getMat(color))
  179. circle.sid = sid
  180. circle.position.copy(pos)
  181. circle.quaternion.copy(objects.player.camera.quaternion)
  182. circle.scale.set(0.05, 0.05, 0.05)
  183. meshGroup.add(circle)
  184. circles.push(circle)
  185. /*var scale = math.getScaleForConstantSize({
  186. width2d:100,
  187. camera:objects.player.camera,
  188. position: pos
  189. })
  190. bubble.scale.copy(scale)*/
  191. },
  192. fadeCircle(circle) {
  193. //开始消失
  194. //console.log("fadeCircle"+circle.sid)
  195. var _duration = 800
  196. transitions.start(
  197. lerp.property(circle.material, "opacity", 0),
  198. _duration,
  199. () => {
  200. this.removeCircle(circle)
  201. },
  202. 0,
  203. easing[settings.transition.blendEasing],
  204. "shop-circles-fade",
  205. settings.freeze.shopCircle
  206. )
  207. //从列表中删除
  208. var index = circles.indexOf(circle)
  209. circles.splice(index, 1)
  210. },
  211. removeCircle(circle) {
  212. //移除某个圈 <!-- sid -->
  213. //var circle = meshGroup.children.find(circle=>circle.sid == sid);
  214. //console.log("removeC " + circle.sid)
  215. circle.material.dispose()
  216. circle.parent.remove(circle)
  217. },
  218. getMat(color) {
  219. /*var mat = this.materials[color]
  220. if (mat) return mat
  221. else {
  222. mat = new THREE.SpriteMaterial({
  223. transparent: true,
  224. depthTest: false,
  225. map: map,
  226. side: THREE.DoubleSide,
  227. color: color,
  228. })
  229. this.materials[color] = mat
  230. return mat
  231. }*/
  232. return new THREE.SpriteMaterial({
  233. transparent: true,
  234. depthTest: false,
  235. map: map,
  236. side: THREE.DoubleSide,
  237. color: color,
  238. })
  239. },
  240. },
  241. }
  242. </script>
  243. <style lang="scss" scoped>
  244. .paint {
  245. position: absolute;
  246. left: 0;
  247. top: 0;
  248. width: 100%;
  249. height: 100%;
  250. z-index: 99;
  251. pointer-events: none !important;
  252. .toolbar {
  253. pointer-events: auto;
  254. position: absolute;
  255. right: 0.35rem;
  256. bottom: 4.5rem;
  257. padding: 0.4rem 0.2rem;
  258. border-radius: 30px;
  259. z-index: 100;
  260. background-color: rgba(0, 0, 0, 0.3);
  261. ul,
  262. li {
  263. margin: 0;
  264. padding: 0;
  265. list-style: none;
  266. }
  267. li {
  268. padding: 0.3px;
  269. text-align: center;
  270. font-size: 14px;
  271. margin-bottom: 0.5rem;
  272. &:last-child {
  273. margin-bottom: 0;
  274. }
  275. i {
  276. font-size: 20px;
  277. &.icon_cancel {
  278. font-size: 22px;
  279. }
  280. // &.iconclose {
  281. // font-size: 14px;
  282. // }
  283. }
  284. }
  285. }
  286. }
  287. </style>