Player.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. import * as THREE from "three";
  2. import FloorplanControls from "../controls/FloorplanControls.js";
  3. import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
  4. import { TrackballControls } from "three/examples/jsm/controls/TrackballControls.js";
  5. import Line from "../box/object/Line";
  6. import LinePoints from "../box/object/LinePoints.js";
  7. import Marker from "../box/object/marker.js";
  8. import CircleTextLabel from "../box/object/CircleTextLabel.js";
  9. import PureTextLabel from "../box/object/PureTextLabel.js";
  10. import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
  11. const convertScreenToNDC = function (event, domElement) {
  12. let x = (event.offsetX / domElement.clientWidth) * 2 - 1;
  13. let y = -(event.offsetY / domElement.clientHeight) * 2 + 1;
  14. return new THREE.Vector2(x, y);
  15. };
  16. export default class Player {
  17. constructor(scene) {
  18. this.scene = scene;
  19. this.orthCamera = scene.orthCamera;
  20. this.floorplanControls = null;
  21. this.raycaster = null;
  22. this.position = new THREE.Vector3();
  23. this.pointerdown = new THREE.Vector2();
  24. this.pointerup = new THREE.Vector2();
  25. this.pointer = new THREE.Vector2();
  26. this.markPosition = new THREE.Vector3();
  27. this.touchImg = null;
  28. this.activeEdge = null;
  29. this.drawLine = null;
  30. this.startObj = null;
  31. this.marker = null;
  32. this.symbol = null;
  33. this.symbolIndex = 0;
  34. this.text = null;
  35. this.showText = "文本";
  36. this.selectItem = null;
  37. this.drawing = false;
  38. this.inited = false;
  39. this.renderLines = [];
  40. this.renderMarkers = [];
  41. this.activeEdges = [];
  42. this.renderSymbols = [];
  43. this.matLine = null;
  44. this.lineColor = 0xe44d54;
  45. // 1是画线,2是标方向, 3符号, 4文本
  46. this.mode = 0;
  47. this.init();
  48. }
  49. setMode(mode) {
  50. this.mode = mode;
  51. if (mode === 1 || mode === 2) {
  52. this.reset();
  53. this.setEditMode();
  54. }
  55. // 2方向
  56. if (mode === 2) {
  57. let pos = new THREE.Vector3(0, 0, -1);
  58. pos.unproject(this.orthCamera);
  59. pos.y = 5;
  60. this.marker = new Marker(pos);
  61. this.marker.visible = false;
  62. this.scene.scene.add(this.marker);
  63. this.drawing = true;
  64. }
  65. //符号
  66. if (mode === 3) {
  67. let pos = new THREE.Vector3(0, 0, -1);
  68. pos.unproject(this.orthCamera);
  69. pos.y = 5;
  70. this.symbolIndex += 1;
  71. this.symbol = new CircleTextLabel(this.symbolIndex, true);
  72. this.symbol.visible = false;
  73. this.scene.scene.add(this.symbol);
  74. console.log("this.symbol", this.symbol);
  75. this.drawing = true;
  76. }
  77. if (mode === 4) {
  78. let pos = new THREE.Vector3(0, 0, -1);
  79. pos.unproject(this.orthCamera);
  80. pos.y = 5;
  81. this.text = new PureTextLabel(this.showText, true);
  82. this.text.visible = false;
  83. this.scene.scene.add(this.text);
  84. this.drawing = true;
  85. }
  86. if (mode === 0) {
  87. this.setFreeMode();
  88. }
  89. this.scene.emit("mode", this.mode);
  90. }
  91. // removeMarker() {
  92. // if (this.marker) {
  93. // this.scene.scene.remove(this.marker);
  94. // this.marker = null;
  95. // }
  96. // }
  97. setFreeMode() {
  98. this.floorplanControls.enablePan = true;
  99. this.floorplanControls.mouseButtons = {
  100. LEFT: THREE.MOUSE.PAN,
  101. MIDDLE: THREE.MOUSE.DOLLY,
  102. RIGHT: THREE.MOUSE.PAN,
  103. };
  104. this.reset();
  105. }
  106. setEditMode() {
  107. this.floorplanControls.enablePan = true;
  108. this.floorplanControls.mouseButtons = {
  109. LEFT: THREE.MOUSE.ROTATE,
  110. MIDDLE: THREE.MOUSE.DOLLY,
  111. RIGHT: THREE.MOUSE.PAN,
  112. };
  113. }
  114. init = () => {
  115. // //floorplanControls
  116. // this.floorplanControls = new FloorplanControls(
  117. // this.orthCamera,
  118. // this.scene.domElement,
  119. // this
  120. // );
  121. this.floorplanControls = new OrbitControls(
  122. this.orthCamera,
  123. this.scene.domElement
  124. );
  125. this.floorplanControls.enablePan = true;
  126. // this.floorplanControls.target.set(0, 1, 0);
  127. // this.floorplanControls.rotateSpeed = 0.5;
  128. // this.floorplanControls.panSpeed = 0.75
  129. this.floorplanControls.maxDistance = 100;
  130. this.floorplanControls.minDistance = 3.5;
  131. this.floorplanControls.maxZoom = 500;
  132. this.floorplanControls.minZoom = 100;
  133. // this.floorplanControls.mouseButtons = {
  134. // LEFT: THREE.MOUSE.PAN,
  135. // MIDDLE: THREE.MOUSE.DOLLY,
  136. // RIGHT: THREE.MOUSE.PAN
  137. // }
  138. this.setMode(0);
  139. this.floorplanControls.enableRotate = false;
  140. this.raycaster = new THREE.Raycaster();
  141. this.onBindEvent();
  142. this.inited = true;
  143. this.matLine = new LineMaterial({
  144. color: this.lineColor,
  145. linewidth: 3, // in world units with size attenuation, pixels otherwise
  146. dashed: false,
  147. alphaToCoverage: true,
  148. });
  149. this.matLine.resolution = new THREE.Vector2(
  150. this.scene.width,
  151. this.scene.height
  152. );
  153. };
  154. onPointerMove = (e) => {
  155. // console.log("intersects", intersects);
  156. // if (this.mode === 0) {
  157. // const intersects = this.raycaster.intersectObjects(
  158. // this.scene.scene.children,
  159. // true
  160. // );
  161. // intersects.forEach((i) => {
  162. // if (String(i.object.name).includes("marker")) {
  163. // // console.log("i.object.name", i.object);
  164. // // debugger
  165. // }
  166. // });
  167. // }
  168. this.pointermove = convertScreenToNDC(e, this.scene.domElement);
  169. this.raycaster.setFromCamera(this.pointermove, this.orthCamera);
  170. if (!this.drawing) return;
  171. if (this.mode === 1) {
  172. let intersectArr = this.scene.boxManager.imgList;
  173. // if(this.startObj) {
  174. // let i = intersectArr.indexOf(this.startObj)
  175. // intersectArr.splice(i, 1)
  176. // }
  177. const intersects = this.raycaster.intersectObjects(intersectArr, false);
  178. if (intersects[0] && intersects[0].object !== this.startObj) {
  179. this.touchImg = intersects[0];
  180. this.setActiveLine(this.touchImg);
  181. }
  182. }
  183. if (this.mode === 2) {
  184. if (this.marker) {
  185. this.marker.visible = true;
  186. let pos = new THREE.Vector3(this.pointermove.x, this.pointermove.y, -1);
  187. pos.unproject(this.orthCamera);
  188. pos.y = 5;
  189. this.marker.position.copy(pos);
  190. }
  191. }
  192. if (this.mode === 3) {
  193. if (this.symbol) {
  194. this.symbol.visible = true;
  195. let pos = new THREE.Vector3(this.pointermove.x, this.pointermove.y, -1);
  196. pos.unproject(this.orthCamera);
  197. pos.y = 5;
  198. this.symbol.position.copy(pos);
  199. }
  200. }
  201. if (this.mode === 4) {
  202. if (this.text) {
  203. this.text.visible = true;
  204. let pos = new THREE.Vector3(this.pointermove.x, this.pointermove.y, -1);
  205. pos.unproject(this.orthCamera);
  206. pos.y = 5;
  207. this.text.position.copy(pos);
  208. }
  209. }
  210. };
  211. onPointerDown = (e) => {
  212. console.log("start draw");
  213. this.pointerdown = convertScreenToNDC(e, this.scene.domElement);
  214. if (this.mode === 0) {
  215. const intersects = this.raycaster.intersectObjects(
  216. this.scene.scene.children,
  217. true
  218. );
  219. intersects.forEach((i) => {
  220. if (
  221. String(i.object.name).includes("marker") ||
  222. String(i.object.name).includes("line")
  223. ) {
  224. this.selectItem = i.object;
  225. this.scene.emit("confirmDelete", i.object.uuid);
  226. }
  227. });
  228. }
  229. if (this.mode === 1) {
  230. this.raycaster.setFromCamera(this.pointerdown, this.orthCamera);
  231. let intersectArr = this.scene.boxManager.imgList;
  232. const intersects = this.raycaster.intersectObjects(intersectArr, false);
  233. console.log("intersects", intersects);
  234. if (intersects[0]) {
  235. this.startObj = intersects[0].object;
  236. this.drawing = true;
  237. } else {
  238. this.startObj = null;
  239. this.drawing = false;
  240. }
  241. }
  242. if (this.mode === 2) {
  243. if (this.marker) {
  244. this.raycaster.setFromCamera(this.pointerdown, this.orthCamera);
  245. let intersectArr = this.scene.boxManager.imgList;
  246. const intersects = this.raycaster.intersectObjects(intersectArr, false);
  247. if (intersects[0]) {
  248. // this.drawing = false;
  249. const imageId = intersects[0].object.userData;
  250. let lasPos = new THREE.Vector3(
  251. this.pointerdown.x,
  252. this.pointerdown.y,
  253. -1
  254. );
  255. lasPos.unproject(this.orthCamera);
  256. lasPos.y = 5;
  257. const marker = new Marker(lasPos);
  258. const activeMarkeritem = {
  259. id: imageId,
  260. point: lasPos.toArray(),
  261. };
  262. const exist = this.renderMarkers.find((item) => item.id === imageId);
  263. if (!exist) {
  264. this.scene.scene.add(marker);
  265. this.renderMarkers.push(activeMarkeritem);
  266. this.scene.scene.remove(this.marker);
  267. this.marker = null;
  268. } else {
  269. this.scene.emit("markerExist");
  270. }
  271. console.log("activeMarkeritem", activeMarkeritem);
  272. this.setMode(0);
  273. }
  274. }
  275. }
  276. if (this.mode === 3) {
  277. if (this.symbol) {
  278. let lasPos = new THREE.Vector3(
  279. this.pointerdown.x,
  280. this.pointerdown.y,
  281. -1
  282. );
  283. const activeSymbolItem = {
  284. id: this.symbolIndex,
  285. point: lasPos.toArray(),
  286. };
  287. this.renderSymbols.push(activeSymbolItem);
  288. this.setMode(0);
  289. }
  290. }
  291. if (this.mode === 4) {
  292. if (this.text) {
  293. let lasPos = new THREE.Vector3(
  294. this.pointerdown.x,
  295. this.pointerdown.y,
  296. -1
  297. );
  298. this.scene.emit("lockText");
  299. this.drawing = false;
  300. // const activeSymbolItem = {
  301. // id: this.symbolIndex,
  302. // point: lasPos.toArray(),
  303. // };
  304. // this.setMode(0);
  305. }
  306. }
  307. };
  308. onPointerUp = (e) => {
  309. this.pointerup = convertScreenToNDC(e, this.scene.domElement);
  310. // console.log("onPointerUp", this.pointerup);
  311. if (this.mode === 1) {
  312. this.drawing = false;
  313. this.floorplanControls.enabled = true;
  314. this.startObj = null;
  315. if (this.drawLine) {
  316. const points = this.drawLine.userData.points;
  317. const dir = this.drawLine.userData.dir;
  318. const finishLine = new LinePoints(points, 0, this.matLine);
  319. this.renderLines.push(points);
  320. this.scene.scene.add(finishLine);
  321. const imageId = this.touchImg.object.userData;
  322. const activeLineItem = {
  323. id: imageId,
  324. dir: [dir],
  325. };
  326. console.log("this.touchImg", activeLineItem, points);
  327. this.insertActiveEdge(activeLineItem);
  328. this.drawLine = null;
  329. }
  330. }
  331. if (this.mode === 2) {
  332. // this.drawing = false;
  333. }
  334. this.syncDrawData();
  335. };
  336. Listener = {
  337. onPointerDown: this.onPointerDown.bind(this),
  338. onPointerMove: this.onPointerMove.bind(this),
  339. onPointerUp: this.onPointerUp.bind(this),
  340. };
  341. onBindEvent = () => {
  342. this.scene.domElement.addEventListener(
  343. "pointerdown",
  344. this.Listener.onPointerDown
  345. );
  346. this.scene.domElement.addEventListener(
  347. "pointermove",
  348. this.Listener.onPointerMove,
  349. false
  350. );
  351. this.scene.domElement.addEventListener(
  352. "pointerup",
  353. this.Listener.onPointerUp
  354. );
  355. };
  356. unbindEvent = () => {
  357. this.scene.domElement.removeEventListener(
  358. "pointerdown",
  359. this.Listener.onPointerDown
  360. );
  361. this.scene.domElement.removeEventListener(
  362. "pointermove",
  363. this.Listener.onPointerMove
  364. );
  365. this.scene.domElement.removeEventListener(
  366. "pointerup",
  367. this.Listener.onPointerUp
  368. );
  369. };
  370. buildLine = () => {
  371. if (this.drawLine) {
  372. this.drawLine.removeFromParent();
  373. }
  374. let s = new THREE.Vector3(this.pointerdown.x, this.pointerdown.y, -1);
  375. let e = new THREE.Vector3(this.pointermove.x, this.pointermove.y, -1);
  376. s.unproject(this.orthCamera);
  377. e.unproject(this.orthCamera);
  378. s.y = 5;
  379. e.y = 5;
  380. const matLine = new LineMaterial({
  381. color: this.lineColor,
  382. linewidth: 3, // in world units with size attenuation, pixels otherwise
  383. dashed: false,
  384. alphaToCoverage: true,
  385. });
  386. matLine.resolution = new THREE.Vector2(this.scene.width, this.scene.height);
  387. this.drawLine = new Line(s, e, this.activeEdge, matLine);
  388. this.scene.scene.add(this.drawLine);
  389. };
  390. setActiveLine = (obj) => {
  391. function getTouchLine(x, y) {
  392. // [0 - 1]
  393. x -= 0.5;
  394. y -= 0.5;
  395. // console.log(x, y);
  396. if (x >= 0 && y >= 0) {
  397. if (x > y) {
  398. return 3;
  399. } else {
  400. return 0;
  401. }
  402. } else if (x >= 0 && y <= 0) {
  403. if (x > Math.abs(y)) {
  404. return 3;
  405. } else {
  406. return 2;
  407. }
  408. } else if (x <= 0 && y >= 0) {
  409. if (Math.abs(x) > y) {
  410. return 1;
  411. } else {
  412. return 0;
  413. }
  414. } else if (x <= 0 && y <= 0) {
  415. if (-x > -y) {
  416. return 1;
  417. } else {
  418. return 2;
  419. }
  420. }
  421. }
  422. if (this.activeEdge) {
  423. this.activeEdge.visible = false;
  424. this.activeEdge = null;
  425. }
  426. let num = getTouchLine(obj.uv.x, obj.uv.y);
  427. this.activeEdge = obj.object.touchLines.getObjectByName(num);
  428. this.activeEdge.visible = true;
  429. this.buildLine();
  430. };
  431. insertActiveEdge(item) {
  432. const exist = this.activeEdges.find((s) => item.id === s.id);
  433. if (exist) {
  434. exist.dir = [...new Set([...exist.dir, ...item.dir])];
  435. } else {
  436. this.activeEdges.push(item);
  437. }
  438. }
  439. insertActiveMarker(item) {
  440. const exist = this.activeEdges.find((s) => item.id === s.id);
  441. if (exist) {
  442. exist.dir = [...new Set([...exist.dir, ...item.dir])];
  443. } else {
  444. this.activeEdges.push(item);
  445. }
  446. }
  447. showAllActiveEdges() {
  448. if (this.inited) {
  449. let imgList = this.scene.boxManager.imgList;
  450. if (this.activeEdges.length > 0) {
  451. this.activeEdges.forEach((edge) => {
  452. const exist = imgList.find((item) => item.userData === edge.id);
  453. // console.log("exist", exist);
  454. if (exist) {
  455. edge.dir.forEach((dir) => {
  456. exist.touchLines.children[dir].visible = true;
  457. });
  458. }
  459. });
  460. } else {
  461. imgList.forEach((img) => {
  462. // console.log("img", img);
  463. img.touchLines.children.forEach((line) => {
  464. if (line.visible) {
  465. line.visible = false;
  466. }
  467. });
  468. });
  469. }
  470. }
  471. }
  472. getDrawData() {
  473. let data;
  474. if (this.scene.sceneType === 1) {
  475. data = {
  476. hor_lines: this.renderLines,
  477. hor_activeEdges: this.activeEdges,
  478. hor_markers: this.renderMarkers,
  479. vir_lines: [],
  480. vir_activeEdges: [],
  481. vir_markers: [],
  482. };
  483. } else {
  484. data = {
  485. hor_lines: [],
  486. hor_activeEdges: [],
  487. hor_markers: [],
  488. vir_lines: this.renderLines,
  489. vir_activeEdges: this.activeEdges,
  490. vir_markers: this.renderMarkers,
  491. };
  492. }
  493. // console.log("sceneType", this.scene.sceneType);
  494. return data;
  495. }
  496. syncDrawData() {
  497. const data = this.getDrawData();
  498. this.scene.emit("data", data);
  499. }
  500. load(type, data) {
  501. if (type === 1) {
  502. console.log("data1", data);
  503. const { hor_activeEdges, hor_lines, hor_markers } = data;
  504. hor_activeEdges && (this.activeEdges = hor_activeEdges);
  505. if (hor_lines && Array.isArray(hor_lines)) {
  506. this.renderLines = hor_lines;
  507. hor_lines.forEach((line) => {
  508. const finishLine = new LinePoints(line, 0, this.matLine);
  509. this.scene.scene.add(finishLine);
  510. });
  511. }
  512. if (hor_markers && Array.isArray(hor_markers)) {
  513. this.renderMarkers = hor_markers;
  514. hor_markers.forEach((pos) => {
  515. console.log("pos");
  516. const p = new THREE.Vector3().fromArray(pos.point);
  517. const marker = new Marker(p);
  518. this.scene.scene.add(marker);
  519. });
  520. }
  521. }
  522. if (type === 2) {
  523. const { vir_activeEdges, vir_lines, vir_markers } = data;
  524. vir_activeEdges && (this.activeEdges = vir_activeEdges);
  525. if (vir_lines && Array.isArray(vir_lines)) {
  526. this.renderLines = vir_lines;
  527. vir_lines.forEach((line) => {
  528. const finishLine = new LinePoints(line, 0, this.matLine);
  529. this.scene.scene.add(finishLine);
  530. });
  531. }
  532. if (vir_markers && Array.isArray(vir_markers)) {
  533. this.renderMarkers = vir_markers;
  534. vir_markers.forEach((pos) => {
  535. const p = new THREE.Vector3().fromArray(pos.point);
  536. const marker = new Marker(p);
  537. this.scene.scene.add(marker);
  538. });
  539. }
  540. }
  541. this.syncDrawData();
  542. }
  543. reset() {
  544. if (this.marker) {
  545. this.scene.scene.remove(this.marker);
  546. this.marker = null;
  547. }
  548. if (this.drawLine) {
  549. this.scene.scene.remove(this.drawLine);
  550. this.drawLine = null;
  551. }
  552. if (this.touchImg) {
  553. this.touchImg = null;
  554. }
  555. if (this.activeEdge) {
  556. this.activeEdge = null;
  557. }
  558. this.drawing = false;
  559. }
  560. clear() {
  561. this.activeEdges = [];
  562. this.renderLines = [];
  563. this.renderMarkers = [];
  564. this.reset();
  565. this.scene.clearDrawScene();
  566. this.syncDrawData();
  567. }
  568. update = () => {
  569. if (this.floorplanControls.enabled) {
  570. this.floorplanControls && this.floorplanControls.update();
  571. this.scene.boxManager && this.showAllActiveEdges();
  572. }
  573. };
  574. }