tpanorama.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. 'use strict';
  2. var _three = require('three');
  3. var t = _interopRequireWildcard(_three);
  4. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
  5. var Vector2 = t.Vector2,
  6. PerspectiveCamera = t.PerspectiveCamera,
  7. Vector3 = t.Vector3,
  8. OrthographicCamera = t.OrthographicCamera,
  9. Scene = t.Scene,
  10. SphereGeometry = t.SphereGeometry,
  11. Mesh = t.Mesh,
  12. MeshBasicMaterial = t.MeshBasicMaterial,
  13. Raycaster = t.Raycaster,
  14. ImageUtils = t.ImageUtils,
  15. WebGLRenderer = t.WebGLRenderer,
  16. Texture = t.Texture,
  17. SpriteMaterial = t.SpriteMaterial,
  18. Sprite = t.Sprite,
  19. TextureLoader = t.TextureLoader,
  20. tMath = t.Math;
  21. var _camera, _scene, _renderer;
  22. var _cameraOrtho, _sceneOrtho;
  23. var _fov = 75;
  24. var _pRadius = 1000;
  25. var _raycaster;
  26. var _container;
  27. var _isUserInteracting = false;
  28. var _lon = 0,
  29. _lat = 0;
  30. var _onPointerDownLon = 0,
  31. _onPointerDownLat = 0;
  32. var _onPointerDownPointerX = 0,
  33. _onPointerDownPointerY = 0;
  34. var _mouse = new Vector2();
  35. var _clickableObjects = [];
  36. var _sprites = [];
  37. var _lables = [];
  38. var options = {
  39. container: 'panoramaConianer', //容器
  40. url: 'resources/img/panorama/pano-7.jpg', //全景图路径
  41. lables: [], //标记 {position:{lon:114,lat:38},logoUrl:'lableLogo.png',text:'我是一个标记'}
  42. widthSegments: 60, //水平切段数
  43. heightSegments: 40, //垂直切段数(值小粗糙速度快,值大精细速度慢)
  44. pRadius: 1000, //全景球的半径,推荐使用默认值
  45. minFocalLength: 1, //镜头最小拉近距离
  46. maxFocalLength: 100, //镜头最大拉近距离
  47. sprite: 'label', // label,icon
  48. onClick: function onClick() {}
  49. };
  50. function tpanorama(opt) {
  51. this.render(opt);
  52. }
  53. tpanorama.prototype = {
  54. constructor: undefined,
  55. def: {},
  56. render: function render(opt) {
  57. var _this = this;
  58. this.def = extend(options, opt, true);
  59. document.getElementById(this.def.container).innerHTML = '';
  60. _lables = [];
  61. initContainer(this.def.container);
  62. initCamera();
  63. initRaycaster();
  64. makePanorama(this.def.pRadius, this.def.widthSegments, this.def.heightSegments, this.def.url);
  65. initRenderer();
  66. initLable(this.def.lables, this.def.sprite);
  67. _container.addEventListener('mousedown', onDocumentMouseDown, false);
  68. _container.addEventListener('mousemove', onDocumentMouseMove, false);
  69. _container.addEventListener('mouseup', onDocumentMouseUp, false);
  70. _container.addEventListener('mousewheel', function (e) {
  71. onDocumentMouseWheel(e, _this.def.minFocalLength, _this.def.maxFocalLength);
  72. }, false);
  73. _container.addEventListener('DOMMouseScroll', function (e) {
  74. onDocumentMouseWheel(e, _this.def.minFocalLength, _this.def.maxFocalLength);
  75. }, false);
  76. _container.addEventListener('click', onDocumentMouseClick.bind(this), false);
  77. global.addEventListener('resize', onWindowResize, false);
  78. animate();
  79. }
  80. };
  81. function extend(o, n, override) {
  82. for (var key in n) {
  83. if (n.hasOwnProperty(key) && (!o.hasOwnProperty(key) || override)) {
  84. o[key] = n[key];
  85. }
  86. }
  87. return o;
  88. }
  89. function initContainer(c) {
  90. _container = document.getElementById(c);
  91. }
  92. function initCamera() {
  93. _camera = new PerspectiveCamera(_fov, window.innerWidth / window.innerHeight, 1, 1100);
  94. _camera.target = new Vector3(0, 0, 0);
  95. _cameraOrtho = new OrthographicCamera(-window.innerWidth / 2, window.innerWidth / 2, window.innerHeight / 2, -window.innerHeight / 2, 1, 10);
  96. _cameraOrtho.position.z = 10;
  97. _scene = new Scene();
  98. _sceneOrtho = new Scene();
  99. }
  100. function initRaycaster() {
  101. _raycaster = new Raycaster();
  102. }
  103. function makePanorama(pRadius, widthSegments, heightSegments, u) {
  104. var mesh = new Mesh(new SphereGeometry(pRadius, widthSegments, heightSegments), new MeshBasicMaterial({ map: ImageUtils.loadTexture(u) }));
  105. mesh.scale.x = -1;
  106. _scene.add(mesh);
  107. }
  108. function initRenderer() {
  109. _renderer = new WebGLRenderer();
  110. _renderer.setSize(window.innerWidth, window.innerHeight);
  111. _renderer.autoClear = false;
  112. _container.appendChild(_renderer.domElement);
  113. }
  114. function onDocumentMouseDown(event) {
  115. event.preventDefault();
  116. _isUserInteracting = true;
  117. _onPointerDownPointerX = event.clientX;
  118. _onPointerDownPointerY = event.clientY;
  119. _onPointerDownLon = _lon;
  120. _onPointerDownLat = _lat;
  121. }
  122. function onDocumentMouseMove(event) {
  123. if (_isUserInteracting) {
  124. _lon = (_onPointerDownPointerX - event.clientX) * 0.1 + _onPointerDownLon;
  125. _lat = (event.clientY - _onPointerDownPointerY) * 0.1 + _onPointerDownLat;
  126. }
  127. }
  128. function onDocumentMouseUp() {
  129. _isUserInteracting = false;
  130. }
  131. function onDocumentMouseClick(event) {
  132. _mouse.x = event.clientX / window.innerWidth * 2 - 1;
  133. _mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  134. _raycaster.setFromCamera(_mouse, _cameraOrtho);
  135. var intersects = _raycaster.intersectObjects(_clickableObjects);
  136. intersects.forEach(this.def.onClick);
  137. }
  138. function onDocumentMouseWheel(ev, minFocalLength, maxFocalLength) {
  139. var ev = ev || window.event;
  140. var down = true;
  141. var m = _camera.getFocalLength();
  142. down = ev.wheelDelta ? ev.wheelDelta < 0 : ev.detail > 0;
  143. if (down) {
  144. if (m > minFocalLength) {
  145. m -= m * 0.05;
  146. _camera.setFocalLength(m);
  147. }
  148. } else {
  149. if (m < maxFocalLength) {
  150. m += m * 0.05;
  151. _camera.setFocalLength(m);
  152. }
  153. }
  154. if (ev.preventDefault) {
  155. ev.preventDefault();
  156. }
  157. return false;
  158. }
  159. function onWindowResize() {
  160. _camera.aspect = window.innerWidth / window.innerHeight;
  161. _camera.projectionMatrix.makePerspective(_fov, _camera.aspect, 1, 1100);
  162. _camera.updateProjectionMatrix();
  163. _cameraOrtho.left = -window.innerWidth / 2;
  164. _cameraOrtho.right = window.innerWidth / 2;
  165. _cameraOrtho.top = window.innerHeight / 2;
  166. _cameraOrtho.bottom = -window.innerHeight / 2;
  167. _cameraOrtho.updateProjectionMatrix();
  168. _renderer.setSize(window.innerWidth, window.innerHeight);
  169. }
  170. function initLable(lables, sprite) {
  171. if (sprite == 'label') {
  172. for (var i = 0; i < lables.length; i++) {
  173. _lables.push(createLableSprite(_sceneOrtho, lables[i].text, lables[i].position));
  174. }
  175. } else if (sprite == 'icon') {
  176. for (var i = 0; i < lables.length; i++) {
  177. _sprites.push(createSprite(lables[i].position, lables[i].logoUrl, lables[i].text));
  178. }
  179. }
  180. }
  181. function createLableSprite(scene, name, position) {
  182. var canvas1 = document.createElement('canvas');
  183. var context1 = canvas1.getContext('2d');
  184. var metrics = context1.measureText(name);
  185. var width = metrics.width * 1.5;
  186. context1.font = "10px 宋体";
  187. context1.fillStyle = "rgba(0,0,0,0.95)";
  188. context1.fillRect(0, 0, width + 8, 20 + 8);
  189. context1.fillStyle = "rgba(0,0,0,0.2)";
  190. context1.fillRect(2, 2, width + 4, 20 + 4);
  191. context1.fillStyle = "rgba(255,255,255,0.95)";
  192. context1.fillText(name, 4, 20);
  193. var texture1 = new Texture(canvas1);
  194. texture1.needsUpdate = true;
  195. var spriteMaterial = new SpriteMaterial({ map: texture1 });
  196. var sprite1 = new Sprite(spriteMaterial);
  197. sprite1.scale.set(1.0, 1.0, 1.0);
  198. sprite1.position.set(0, 0, 0);
  199. sprite1.name = name;
  200. var lable = {
  201. name: name,
  202. pos: position,
  203. canvas: canvas1,
  204. context: context1,
  205. texture: texture1,
  206. sprite: sprite1
  207. };
  208. _sceneOrtho.add(lable.sprite);
  209. _clickableObjects.push(lable.sprite);
  210. return lable;
  211. }
  212. function createSprite(position, url, name) {
  213. var textureLoader = new TextureLoader();
  214. var ballMaterial = new SpriteMaterial({
  215. map: textureLoader.load(url)
  216. });
  217. var sp1 = {
  218. pos: position,
  219. name: name,
  220. sprite: new Sprite(ballMaterial)
  221. };
  222. sp1.sprite.scale.set(32, 32, 1.0);
  223. sp1.sprite.position.set(0, 0, 0);
  224. sp1.sprite.name = name;
  225. _sceneOrtho.add(sp1.sprite);
  226. _clickableObjects.push(sp1.sprite);
  227. return sp1;
  228. }
  229. function animate() {
  230. requestAnimationFrame(animate);
  231. render();
  232. }
  233. function render() {
  234. calPosition();
  235. addSprites();
  236. runRender();
  237. }
  238. function calPosition() {
  239. _lat = Math.max(-85, Math.min(85, _lat));
  240. var phi = tMath.degToRad(90 - _lat);
  241. var theta = tMath.degToRad(_lon);
  242. _camera.target.x = _pRadius * Math.sin(phi) * Math.cos(theta);
  243. _camera.target.y = _pRadius * Math.cos(phi);
  244. _camera.target.z = _pRadius * Math.sin(phi) * Math.sin(theta);
  245. _camera.lookAt(_camera.target);
  246. }
  247. function addSprites() {
  248. if (typeof _sprites != "undefined") {
  249. for (var i = 0; i < _sprites.length; i++) {
  250. var wp = geoPosition2World(_sprites[i].pos.lon, _sprites[i].pos.lat);
  251. var sp = worldPostion2Screen(wp, _camera);
  252. var test = wp.clone();
  253. test.project(_camera);
  254. if (test.x > -1 && test.x < 1 && test.y > -1 && test.y < 1 && test.z > -1 && test.z < 1) {
  255. _sprites[i].sprite.scale.set(32, 32, 32);
  256. _sprites[i].sprite.position.set(sp.x, sp.y, 1);
  257. } else {
  258. _sprites[i].sprite.scale.set(1.0, 1.0, 1.0);
  259. _sprites[i].sprite.position.set(0, 0, 0);
  260. }
  261. }
  262. }
  263. if (typeof _lables != "undefined") {
  264. for (var i = 0; i < _lables.length; i++) {
  265. var wp = geoPosition2World(_lables[i].pos.lon, _lables[i].pos.lat);
  266. var sp = worldPostion2Screen(wp, _camera);
  267. var test = wp.clone();
  268. test.project(_camera);
  269. if (test.x > -1 && test.x < 1 && test.y > -1 && test.y < 1 && test.z > -1 && test.z < 1) {
  270. var metrics = _lables[i].context.measureText(_lables[i].name);
  271. var width = metrics.width * 3.5;
  272. _lables[i].sprite.scale.set(400, 150, 1.0);
  273. _lables[i].sprite.position.set(sp.x + width, sp.y - 40, 1);
  274. } else {
  275. _lables[i].sprite.scale.set(1.0, 1.0, 1.0);
  276. _lables[i].sprite.position.set(0, 0, 0);
  277. }
  278. }
  279. }
  280. }
  281. function geoPosition2World(lon, lat) {
  282. lat = Math.max(-85, Math.min(85, lat));
  283. var phi = tMath.degToRad(90 - lat);
  284. var theta = tMath.degToRad(lon);
  285. var result = {
  286. x: _pRadius * Math.sin(phi) * Math.cos(theta),
  287. y: _pRadius * Math.cos(phi),
  288. z: _pRadius * Math.sin(phi) * Math.sin(theta)
  289. };
  290. return new Vector3(result.x, result.y, result.z);
  291. }
  292. function worldPostion2Screen(world_vector, camera) {
  293. var vector = world_vector.clone();
  294. vector.project(camera);
  295. var result = {
  296. x: Math.round((vector.x + 1) * window.innerWidth / 2 - window.innerWidth / 2),
  297. y: Math.round(window.innerHeight / 2 - (-vector.y + 1) * window.innerHeight / 2),
  298. z: 0
  299. };
  300. return new Vector3(result.x, result.y, result.z);
  301. }
  302. function runRender() {
  303. _renderer.render(_scene, _camera);
  304. _renderer.render(_sceneOrtho, _cameraOrtho);
  305. }
  306. module.exports = tpanorama;