Hot.js 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575
  1. //合并热点和展览
  2. window.initHot = function(model){
  3. var objLoader = new THREE.OBJLoader()
  4. var _planeGeometry = new THREE.PlaneGeometry(1,1)
  5. var _boxGeometry = new THREE.BoxBufferGeometry(1,1,1)
  6. {//ie的mesh 加了polygonOffset也是会重叠。所以去掉前面的face: (但是突然ie又播放不了videoTexture)
  7. var newIndex = [..._boxGeometry.index.array]
  8. newIndex.splice(4 * 6, 6)
  9. _boxGeometry.setIndex(new THREE.BufferAttribute(new Uint16Array(newIndex),1))
  10. }
  11. var originPhotoCount = photoLoaded = originModelCount = modelLoaded = 0;
  12. var defaultTex1 = Texture.load(g_HotImage.point);
  13. var defaultTex2 = Texture.load(g_HotImage.point2)
  14. /* var _boxMat = new THREE.MeshBasicMaterial({
  15. color: "#eeeeee",
  16. transparent: !0,
  17. opacity: 0.8
  18. }) */
  19. var _boxMat = new THREE.MeshPhongMaterial({
  20. color: "#eeeeee",
  21. transparent: !0,
  22. opacity: 0.8
  23. })
  24. var hotGroup = new THREE.Object3D; hotGroup.name = "hotGroup"
  25. model.add(hotGroup); model.hotGroup = hotGroup
  26. var animateTexSrcs = {}
  27. var getLink = function(link){
  28. var src = '';
  29. var r = link.substring(link.indexOf("html") + 4)
  30. , o = "en" == manage.number("lang") ? "&lang=" + manage.number("lang") : "";
  31. -1 == r.indexOf("?") ? src = link + "?time=" + randomTime().getTime() + "&id=" + window.number + o : src = link + "&time=" + randomTime().getTime() + "&id=" + window.number + o
  32. return src
  33. }
  34. var removeSrcPostMark = function(url){//去除texture.load时自动加上的'?'
  35. var index = url.indexOf('?')
  36. if(index>-1){
  37. return url.slice(0, index)
  38. }else return url
  39. }
  40. {//get plane Bound
  41. var planeBound = new THREE.Box3()
  42. var cornerPoint = [
  43. new THREE.Vector3(-0.5, 0.5, 0),
  44. new THREE.Vector3(0.5, 0.5, 0),
  45. new THREE.Vector3(0.5, -0.5, 0),
  46. new THREE.Vector3(-0.5, -0.5, 0),
  47. ]
  48. cornerPoint.forEach(e=>{
  49. planeBound.expandByPoint(e)
  50. })
  51. }
  52. var shineMats = [];
  53. var getShineMat = function(texture1, texture2){
  54. var mat = shineMats.find(e=>e.uniforms.texture1.value == texture1 && e.uniforms.texture2.value == texture2)
  55. if(mat) return mat
  56. else{
  57. var mat = new THREE.ShaderMaterial({
  58. uniforms: {
  59. color: {
  60. type: "c",
  61. value: new THREE.Color(16720384)
  62. },
  63. opac: {
  64. type: "f",
  65. value: 0
  66. },
  67. texture1: {
  68. type: "t",
  69. value: texture1
  70. },
  71. texture2: {
  72. type: "t",
  73. value: texture2
  74. }
  75. },
  76. vertexShader: "varying vec2 vUv;\n\nvoid main() {\n\n vUv = uv ;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n}\n",
  77. fragmentShader: "varying vec3 vNormal;\n\nvarying vec2 vUv;\n\nuniform float opac;\n\nuniform vec3 color;\n\nuniform sampler2D texture1;\n\nuniform sampler2D texture2;\n\nvoid main() {\n\nvec4 tcolor1 = texture2D( texture1, vUv );\n\nvec4 tcolor2 = texture2D( texture2, vUv );\n\ngl_FragColor = mix(tcolor1,tcolor2 ,opac) + tcolor2*0.2; }\n"
  78. ,transparent: !0
  79. })
  80. shineMats.push(mat)
  81. return mat
  82. }
  83. }
  84. var modelGeos = [];
  85. var getModelGeo = function(url){
  86. var geo = modelGeos.find(e=>e.url = url )
  87. if(geo) return geo
  88. else{
  89. var geo = null;
  90. geo.url = url
  91. }
  92. }
  93. class Hot extends THREE.Object3D{
  94. constructor(info, source){
  95. super()
  96. this.sid = info.sid;
  97. this.preDeal(info, source)// source:来源
  98. this.info = info
  99. this.cornerPoints = []
  100. this.build(info);
  101. this.name = "hot_" + this.sid ;
  102. model.hots[info.sid] = this
  103. }
  104. build(info) {
  105. /* this.changeMaterial(new THREE.MeshBasicMaterial({
  106. color: "#00c8af",
  107. opacity: 0.4,
  108. transparent: !0,
  109. polygonOffset: true,
  110. //是否开启多边形偏移 //ie不开启时blank也不会闪烁
  111. polygonOffsetFactor: -0.9,
  112. //多边形偏移因子
  113. polygonOffsetUnits: -4.0,
  114. //多边形偏移单位
  115. }))
  116. if(!info.objSrc){
  117. this.addPlane()
  118. if (info.hasBox) this.addBox(true)
  119. }else{
  120. this.addModel(new THREE.Mesh())//暂时创建个空的
  121. } */
  122. hotGroup.add(this)
  123. this.setTitleElem()
  124. this.setFromInfo(info)
  125. }
  126. setFromInfo(info, media, objObject) {
  127. //1 恢复到编辑之前 2 初始加载
  128. var plane = this.plane;
  129. /* var transformAtPanos = {}
  130. for(var i in info.transformAtPanos){
  131. transformAtPanos[i] = {//只保留一个位移,主要原因是大小变化和热点大小设置冲突了, isSprite和qutaernion衝突
  132. pos : info.transformAtPanos[i].pos && info.transformAtPanos[i].pos.clone(),
  133. //qua : info.transformAtPanos[i].qua && info.transformAtPanos[i].qua.clone(),
  134. }
  135. }
  136. this.transformAtPanos = transformAtPanos */
  137. //在每个漫游点独立设置的position。
  138. var curPanoTransform = this.info.transformAtPanos[ getTransformSid()] || {}
  139. //没有单独设置position的漫游点使用的position
  140. this.position.copy(curPanoTransform.pos || info.position)
  141. this.rotation.copy(info.rotation)
  142. this.scale.copy(info.scale)
  143. this.changeTexType(info.texType, media)
  144. if(!info.objSrc){
  145. this.addPlane()
  146. if (!!this.hasBox != !!info.hasBox) {
  147. this.addBox(!this.hasBox);
  148. }
  149. }else{
  150. this.addModel(objObject || new THREE.Mesh())//暂时创建个空的
  151. }
  152. this.updateMatrixWorld()
  153. /* if(!this.info.visiblePanos){//移到model.build时,在collider建好之后
  154. this.getVisiblePanos()
  155. } */
  156. {//gif
  157. if(this.animation){
  158. GifTexDeal.remove(this.animation)
  159. }
  160. if(this.info.animateInfo && this.material_.map){
  161. this.animation = GifTexDeal.addAnimation(this.material_.map, this, this.info.animateInfo, this.sid )
  162. this.visible && this.inSight() && GifTexDeal.start(this.animation)
  163. }
  164. }
  165. /* if(this.info.modelBound){
  166. this.mesh.updateMatrixWorld()
  167. this.mesh.boxHelper2 = new THREE.Box3Helper( new THREE.Box3().copy(this.info.modelBound.bound).applyMatrix4(this.mesh.matrixWorld), new THREE.Color("#00aaee"));
  168. model.add(this.mesh.boxHelper2)
  169. }else{
  170. var bound = new THREE.Box3()
  171. var cornerPoint = [
  172. new THREE.Vector3(-0.5, 0.5, 0),
  173. new THREE.Vector3(0.5, 0.5, 0),
  174. new THREE.Vector3(0.5, -0.5, 0),
  175. new THREE.Vector3(-0.5, -0.5, 0),
  176. ]
  177. cornerPoint.forEach(e=>{
  178. bound.expandByPoint(e)
  179. })
  180. this.mesh.updateMatrixWorld()
  181. this.mesh.boxHelper2 = new THREE.Box3Helper( bound.applyMatrix4(this.mesh.matrixWorld), new THREE.Color("#00aaee"));
  182. model.add(this.mesh.boxHelper2)
  183. } */
  184. }
  185. changeTexType(texType, media){
  186. var plane = this.plane;
  187. if( this.texType != texType || media == 'clear'){
  188. //删除旧的
  189. if(this.texType == 'shine'){
  190. /* this.material_.uniforms.texture1.value.dispose()
  191. this.material_.uniforms.texture2.value.dispose() */ //为了恢复 不删
  192. }else{
  193. //this.material_.map.dispose()
  194. if(this.texType == 'video'){
  195. this.texMedia && this.texMedia.pause()
  196. }else{
  197. }
  198. }
  199. if(this.material_ && !hotGroup.children.find(e=>e!=this && e.material_ == this.material_ )){
  200. this.material_.dispose()
  201. }
  202. //添加新的
  203. if(texType == 'shine'){
  204. }else{
  205. this.changeMaterial(new THREE.MeshBasicMaterial({
  206. color: "#00c8af",
  207. opacity: 0.4,
  208. transparent: !0,
  209. polygonOffset: true,
  210. //是否开启多边形偏移 //ie不开启时blank也不会闪烁
  211. polygonOffsetFactor: -0.9,
  212. //多边形偏移因子
  213. polygonOffsetUnits: -4.0,
  214. //多边形偏移单位
  215. }))
  216. if(texType == 'video'){
  217. }else{
  218. }
  219. }
  220. }
  221. this.texType = texType
  222. if(media == 'clear'){
  223. this.material_.opacity = 0.4;
  224. this.texMedia = null
  225. return
  226. }
  227. if(texType == 'video'){//视频不能共用一个,否则会一起播放暂停
  228. var video
  229. if(media){
  230. video = media
  231. }else{
  232. if(!this.info.texSrc)return
  233. var video = $(`<video controls="controls" loop autoplay x5-playsinline="" webkit-playsinline="true" playsinline="true" controlslist="nodownload"></video>`)[0]
  234. video.src = manage.dealURL(this.info.texSrc);
  235. video.name = this.info.fileName
  236. }
  237. video.setAttribute("crossOrigin", 'Anonymous')//要在src设置好前解决跨域
  238. $(video).on('contextmenu', function() {
  239. return false;
  240. });//禁止右键点击出
  241. this.texMedia = video;
  242. video.oncanplaythrough = ()=> {
  243. if(this.texMedia == video){
  244. this.material_.map.needsUpdate = !0
  245. video.play()
  246. }
  247. }
  248. //this.hasRequestLoad = true
  249. video.volume = 0
  250. video.muted = true
  251. this.material_.map = new THREE.VideoTexture(video)
  252. this.material_.map.wrapS = this.material_.map.wrapT = THREE.ClampToEdgeWrapping;
  253. this.material_.map.generateMipmaps = true;
  254. }else if(texType == 'photo'){
  255. if(media){
  256. this.texMedia = media;
  257. this.info.texSrc = media.src;
  258. this.material_.map = new THREE.Texture(); //texture也不能共用一个,因为有的会有动画,就不一样
  259. this.material_.map.image = media //image可以共用
  260. this.material_.map.needsUpdate = !0
  261. }else{
  262. if(!this.info.texSrc)return
  263. this._loadDones = []
  264. this.material_.opacity = 0.1;
  265. }
  266. }else if(texType == 'shine'){
  267. if(media){
  268. this.changeShineTex(media)
  269. }else{
  270. this.styleImg = /* this.styleImg || */ [];
  271. if(this.info.styleImg){
  272. this.styleImg = this.info.styleImg.map((src)=>{
  273. return {src:/* manage.dealURL( */src } //如果要dealURL,在predeal里
  274. })
  275. }
  276. this.changeShineTex(this.styleImg)
  277. }
  278. }
  279. if(this.material_.map){
  280. /* this.material_.map.minFilter = THREE.LinearFilter;
  281. this.material_.map.magFilter = THREE.LinearFilter; */
  282. dealMap(this.material_.map);
  283. this.material_.color.set("#FFFFFF");
  284. this.material_.opacity = 1
  285. this.material_.needsUpdate = true
  286. }
  287. }
  288. changeShineTex(styleImg){
  289. styleImg = styleImg || this.styleImg
  290. var tex1, tex2
  291. if(styleImg.length){
  292. tex1 = Texture.load(styleImg[0].src);
  293. tex2 = Texture.load(styleImg[1]&&styleImg[1].src || styleImg[0].src);
  294. }else{
  295. tex1 = defaultTex1;
  296. tex2 = defaultTex2;
  297. }
  298. this.changeMaterial(getShineMat(tex1, tex2))
  299. this.styleImg = styleImg
  300. }
  301. changeMaterial(mat){
  302. this.material_ = mat;
  303. this.mesh && this.mesh.traverse((mesh)=>{
  304. if(mesh.material && !(mesh instanceof THREE.Box3Helper)){
  305. mesh.material = this.material_;
  306. }
  307. })
  308. }
  309. /*
  310. actionType: "common"
  311. infoAttribute: {images: [], styleImg: [], model: [], video: [], bgName: "background", iframe: [], title: "11",…}
  312. bgName: "background"
  313. content: "111"
  314. iframe: []
  315. images: []
  316. model: []
  317. styleImg: []
  318. title: "11"
  319. video: []
  320. isSprite: 0
  321. link: "https://www.4dmodel.com/SuperTwo/hot_online1/index.html#/?m=EDwn769489868"
  322. linkType: "common"
  323. noAction: 0
  324. order: 4
  325. position: {x: -4.238, y: 1.32, z: -0.648}
  326. rotation: {x: 0, y: 0.018105110200249575, z: 0}
  327. transformAtPanos: {}
  328. IO4Kq7494332: {actionTy
  329. depth: 0.08
  330. file: "https://super.4dage.com/data/TEST/edit/20200805_172635119.mp4"
  331. hasBox: 1
  332. height: 0.7289
  333. media: ["video"]
  334. pos: [-5.562, 1.349, 1.994]
  335. qua: [0, 0.70672, 0, 0.70749]
  336. sid: "1596619585929"
  337. transformAtPanos: {,…} */
  338. preDeal(info, source){// source:来源
  339. var convertValue = function(v ,Type){
  340. var value;
  341. if(v instanceof Array){
  342. v.forEach((v1)=>{v1 = parseFloat(v1)})
  343. value = new Type().fromArray(v);
  344. }else{
  345. if(!(v instanceof Type)){
  346. for(let i in v){v[i] = parseFloat(v[i])}
  347. value = new Type().copy(v);
  348. }else{
  349. value = v
  350. }
  351. }
  352. return value
  353. }
  354. if (!info.transformAtPanos) info.transformAtPanos = {}
  355. if(source == 'byHot'){
  356. var infoAttribute = info.infoAttribute || {}
  357. info.title = infoAttribute.title || info.title
  358. info.model = infoAttribute.model || info.model || [] //模型链接
  359. info.images = infoAttribute.images || info.images || []
  360. info.video = infoAttribute.video || info.video || []
  361. info.bgName = infoAttribute.bgName || info.bgName
  362. info.backgroundMusic = info.backgroundMusic || info.backgroundMusic
  363. info.iframe = infoAttribute.iframe || info.iframe || []
  364. info.styleImg = infoAttribute.styleImg || info.styleImg || []
  365. info.content = infoAttribute.content || info.content
  366. {
  367. let action = CloneObject(settings.hotClickEvent.shine);
  368. if(info.actionType == 'noAction' || info.noAction){
  369. action.examine = false,
  370. action.openHot = false
  371. }else if(info.actionType == 'dontExam'){
  372. action.examine = false
  373. }
  374. info.actionType = action
  375. }
  376. if(info.quaternion){
  377. info.rotation = new THREE.Euler().setFromVector3(convertValue(info.quaternion, THREE.Quaternion ))
  378. }else{
  379. info.rotation = new THREE.Euler().setFromVector3(convertValue(info.rotation, THREE.Vector3 )) //热点的旧数据很多是字符串
  380. }
  381. var s = Hot.getDefaulScale(info.hotIconScale)
  382. info.scale = new THREE.Vector3(s,s,0.02)
  383. delete info.infoAttribute;
  384. /* for (let i in this.transformAtPanos) {
  385. info.transformAtPanos[i].pos = new THREE.Vector3().fromArray(info.transformAtPanos[i].pos)
  386. info.transformAtPanos[i].qua && (info.transformAtPanos[i].qua = new THREE.Quaternion().fromArray(info.transformAtPanos[i].qua))
  387. } */
  388. info.texType = "shine"
  389. }else{
  390. if(source == 'byOverlay'){
  391. info.texType = info.media[0]
  392. //info.title = info.texType == 'video'?'视频':'图片'
  393. info.texSrc = info.file
  394. info.actionType = CloneObject(settings.hotClickEvent[info.texType]);//给一个默认
  395. delete info.media
  396. info.rotation = new THREE.Euler().setFromQuaternion(convertValue(info.qua, THREE.Quaternion ))
  397. info.position = info.pos
  398. delete info.pos;
  399. delete info.qua;
  400. let a = info.texSrc.split('/');
  401. info.fileName = a.pop()
  402. info.scale = new THREE.Vector3(
  403. info.width,
  404. info.height,
  405. info.depth
  406. )
  407. delete info.width; delete info.height; delete info.depth;
  408. delete info.file
  409. }else{
  410. info.rotation = new THREE.Euler().fromArray(info.rotation)//.setFromVector3(info.rotation)
  411. }
  412. info.model = info.model || [] //模型链接
  413. info.images = info.images || []
  414. info.video = info.video || []
  415. info.iframe = info.iframe || []
  416. info.styleImg = info.styleImg || []
  417. }
  418. if(info.texSrc){
  419. info.texSrc = manage.removeSrcPostMark(info.texSrc)
  420. }
  421. //whole:
  422. //为了兼容旧数据,尽量和hot的数据靠近,最后保存在hot里
  423. info.position = convertValue(info.position, THREE.Vector3)
  424. info.scale = convertValue(info.scale, THREE.Vector3)
  425. delete info.quaternion
  426. info.linkType = info.linkType || "common"
  427. for (let i in info.transformAtPanos) {
  428. info.transformAtPanos[i].pos = new THREE.Vector3().fromArray(info.transformAtPanos[i].pos)
  429. //info.transformAtPanos[i].qua = new THREE.Quaternion().fromArray(info.transformAtPanos[i].qua)
  430. }
  431. }
  432. addBox(state) {
  433. if (state == !!this.hasBox) {
  434. return;
  435. }
  436. if (state) {
  437. var box = new THREE.Mesh(_boxGeometry,_boxMat)
  438. box.position.set(0, 0, 1 / 2);
  439. box.renderOrder = 3
  440. this.plane.position.set(0, 0, 1);
  441. this.add(box);
  442. this.box = box;
  443. } else {
  444. this.plane.position.set(0, 0, 0);
  445. this.remove(this.box);
  446. this.box = null;
  447. }
  448. this.hasBox = this.info.hasBox = state
  449. }
  450. /* getSizeByScale() {
  451. return {
  452. width: settings.defaultOverlaySize[0] * this.scale.x,
  453. height: settings.defaultOverlaySize[1] * this.scale.y
  454. }
  455. }
  456. getScaleBySize(width, height) {
  457. return {
  458. x: width / settings.defaultOverlaySize[0],
  459. y: height / settings.defaultOverlaySize[1],
  460. }
  461. }*/
  462. setVisiblePanos(visibleData){
  463. if(visibleData)this.info.visiblePanos = visibleData
  464. else if(!this.info.visiblePanos) this.getVisiblePanos()
  465. }
  466. getVisiblePanos(){//在不同点还不一样
  467. var depth = this.hasBox ? this.scale.z : 0;
  468. var width = this.scale.x, height = this.scale.y
  469. var cornerPoint
  470. if(this.plane){
  471. cornerPoint = [
  472. new THREE.Vector3(0, 0, depth),
  473. new THREE.Vector3(-width/2, height/2, depth),
  474. new THREE.Vector3(width/2, height/2, depth),
  475. new THREE.Vector3(width/2, -height/2, depth),
  476. new THREE.Vector3(-width/2, -height/2, depth),
  477. ]
  478. }else{
  479. var bound = new THREE.Box3().copy(this.info.modelBound.bound)
  480. var center = bound.center()
  481. cornerPoint = [
  482. new THREE.Vector3(center.x,center.y,center.z),
  483. new THREE.Vector3(bound.min.x, bound.min.y, bound.min.z ),
  484. new THREE.Vector3(bound.min.x, bound.min.y, bound.max.z ),
  485. new THREE.Vector3(bound.min.x, bound.max.y, bound.min.z ),
  486. new THREE.Vector3(bound.max.x, bound.min.y, bound.min.z ),
  487. new THREE.Vector3(bound.max.x, bound.max.y, bound.min.z ),
  488. new THREE.Vector3(bound.max.x, bound.min.y, bound.max.z ),
  489. new THREE.Vector3(bound.min.x, bound.max.y, bound.max.z ),
  490. new THREE.Vector3(bound.max.x, bound.max.y, bound.max.z ),
  491. ];
  492. }
  493. var getPos = (position)=>{//每个overlay位置对应5个坐标,plane中心和四个角的位置
  494. if(this.plane){
  495. return cornerPoint.map(e=>{
  496. return e.clone().applyEuler(this.info.rotation).add(position)
  497. })
  498. }else{
  499. var matrixWorld = new THREE.Matrix4().compose(position, this.quaternion, this.scale)
  500. matrixWorld.multiplyMatrices(matrixWorld, this.mesh.matrix)
  501. return cornerPoint.map(e=>{
  502. return e.clone().applyMatrix4(matrixWorld);
  503. })
  504. }
  505. }
  506. this.info.visiblePanos = []
  507. var customPositions = getPos(this.info.position )
  508. var posAtPanos = {}
  509. for(let panoId in this.info.transformAtPanos){
  510. if(panoId == 'outSide')continue;
  511. posAtPanos[panoId] = getPos(this.info.transformAtPanos[panoId].pos )
  512. }
  513. let maxCount = browser.isMobile() ? 2000 : 5000
  514. let c = model.panos.list.length * model.colliders.length
  515. if(settings.isEdit || c < maxCount){
  516. this.info.visiblePanos = common.getVisiblePano(customPositions, model.panos.list, {
  517. model: model.colliders , posAtPanos
  518. })
  519. }else{
  520. let start = 0
  521. let interval = setInterval(()=>{
  522. let end = start + Hot.visiPanosCountSlice;
  523. end = Math.min(end, model.panos.list.length)
  524. let i = start
  525. start = end
  526. let panos = model.panos.list.slice(i,end)
  527. this.info.visiblePanos = this.info.visiblePanos.concat( common.getVisiblePano(customPositions, panos, {
  528. model: model.colliders , posAtPanos
  529. }));
  530. if(end>=model.panos.list.length){
  531. console.log(window.hotsi ?(++window.hotsi): (window.hotsi = 1))
  532. clearInterval(interval)
  533. }
  534. }, Hot.visiEveryDurSlice )
  535. }
  536. }
  537. updateVisible(panos, visibility) {
  538. if(settings.isEdit && editTool.hotpoint.editSpot == this){
  539. return true
  540. }
  541. this.visible = visibility != void 0 ? visibility : (!this.info.visiblePanos || !!panos.find(pano=>this.info.visiblePanos.includes(pano.id)))
  542. if (this.texType == 'video'){
  543. //this.switchPlay(this.visible, this.visible ? null : 'stop' );//可见时不操作;不可见时停止
  544. this.update(player)
  545. }
  546. }
  547. getCornerPoint(){//获取在每个漫游点上的视觉边界点 可以打开boxHelper和addBall来观测是否准确
  548. if(this.cornerPoints[player.currentPano.id]){
  549. return this.cornerPoints[player.currentPano.id]
  550. }else{
  551. var boundPoint, cornerPoint
  552. if(this.plane){
  553. var center = this.plane.position.clone()
  554. boundPoint = [
  555. center,
  556. new THREE.Vector3(-0.5, 0.5, 0),
  557. new THREE.Vector3(0.5, 0.5, 0),
  558. new THREE.Vector3(0.5, -0.5, 0),
  559. new THREE.Vector3(-0.5, -0.5, 0),
  560. ]
  561. }else{
  562. var bound = new THREE.Box3().copy(this.info.modelBound.bound)
  563. boundPoint = [
  564. new THREE.Vector3(bound.min.x, bound.min.y, bound.min.z ),
  565. new THREE.Vector3(bound.min.x, bound.min.y, bound.max.z ),
  566. new THREE.Vector3(bound.min.x, bound.max.y, bound.min.z ),
  567. new THREE.Vector3(bound.max.x, bound.min.y, bound.min.z ),
  568. new THREE.Vector3(bound.max.x, bound.max.y, bound.min.z ),
  569. new THREE.Vector3(bound.max.x, bound.min.y, bound.max.z ),
  570. new THREE.Vector3(bound.min.x, bound.max.y, bound.max.z ),
  571. new THREE.Vector3(bound.max.x, bound.max.y, bound.max.z ),
  572. ];
  573. }
  574. var maxLon = -Infinity
  575. var minLon = +Infinity
  576. var maxLat = -Infinity
  577. var minLat = +Infinity
  578. var pos1 = player.currentPano.position.clone();
  579. var pos2 = this.position.clone()
  580. var dir = pos2.clone().sub(pos1).normalize()
  581. var centerDirInfo = { }
  582. player.cameraControls.controls.panorama.lookAt.call( centerDirInfo , null, dir )
  583. boundPoint.forEach(e=>{//lon左右
  584. var point = e.applyMatrix4(this.mesh.matrixWorld);
  585. var dir = point.clone().sub(pos1).normalize()
  586. var dirInfo = { }
  587. player.cameraControls.controls.panorama.lookAt.call( dirInfo , null, dir )
  588. var diffLon = (dirInfo.lon-centerDirInfo.lon) % 360
  589. if(Math.abs(diffLon)>180){//因为有时需要根据符号判断是在中心的左边还是右边,所以限制在180内
  590. diffLon += (diffLon>0 ? -360 : 360)
  591. }
  592. var diffLat = dirInfo.lat-centerDirInfo.lat
  593. maxLon = Math.max(diffLon, maxLon)
  594. minLon = Math.min(diffLon, minLon)
  595. maxLat = Math.max(diffLat, maxLat)
  596. minLat = Math.min(diffLat, minLat)
  597. })
  598. var diffLon = maxLon - minLon
  599. var diffLat = maxLat - minLat
  600. if(diffLat>180) {//可能是到了反面。不好算,直接返回所有boundPoint
  601. cornerPoint = boundPoint
  602. }else{
  603. //读取lon lat的最大最小值,勾勒出一个没有倾斜的矩形 。它比boundPoint看起来范围更大些
  604. maxLon = maxLon + centerDirInfo.lon
  605. maxLat = maxLat + centerDirInfo.lat
  606. minLon = minLon + centerDirInfo.lon
  607. minLat = minLat + centerDirInfo.lat
  608. var dirs = [
  609. math.getDirByLonLat(maxLon, maxLat),
  610. math.getDirByLonLat(minLon, minLat),
  611. math.getDirByLonLat(maxLon, minLat),
  612. math.getDirByLonLat(minLon, maxLat),
  613. ]
  614. cornerPoint = dirs.map(e=>{
  615. return e.clone().add(pos1)
  616. })
  617. }
  618. if(this.objObject){
  619. cornerPoint = [pos2, ...cornerPoint]
  620. }
  621. //addPoints(cornerPoint)
  622. this.cornerPoints[player.currentPano.id] = {cornerPoint, diffLon, diffLat}
  623. return this.cornerPoints[player.currentPano.id]
  624. }
  625. }
  626. inSight(){
  627. //return true
  628. if(settings.isEdit)return true // 太容易move了
  629. if(player.mode == 'panorama'){
  630. if(!player.camera) return
  631. var cornerPointInfo = this.getCornerPoint();
  632. var cornerPoint
  633. if(cornerPointInfo.diffLon < 15 && cornerPointInfo.diffLat < 15){//当很小的时候,只判断中心点即可
  634. cornerPoint = [cornerPointInfo.cornerPoint[0]];
  635. }else{
  636. cornerPoint = cornerPointInfo.cornerPoint
  637. }
  638. for(let i=0,j=cornerPoint.length;i<j;i++){//只要有一点可见就算看见
  639. var pos2d = math.getPos2d(cornerPoint[i], player.camera, $("#player")[0])
  640. if(pos2d.trueSide && pos2d.inSight) return true
  641. }
  642. }else{//飞出要判断模型阻挡,有点耗时就算了
  643. return true
  644. }
  645. }
  646. update(player){
  647. if(player.mode == 'panorama'){//实时监测播放
  648. if(this.texType == "video"){
  649. if(this.visible && !this.pausedByUser && this.inSight()){
  650. this.videoControl(true)
  651. }else{
  652. this.videoControl(false)
  653. }
  654. }else if(this.info.animateInfo){
  655. if(this.visible && this.inSight()){
  656. GifTexDeal.start(this.animation)
  657. }else{
  658. GifTexDeal.stop(this.animation)
  659. }
  660. }
  661. }
  662. if(this.info.isSprite){
  663. this.quaternion.copy(player.camera.quaternion)
  664. }
  665. }
  666. switchPlay(state){//手动播放暂停
  667. this.pausedByUser = !state
  668. this.videoControl(state)
  669. }
  670. videoControl(state){
  671. if(this.texType != "video" || !this.material_.map)return
  672. var video = this.material_.map.image
  673. if(!state || state == 'stop'){
  674. if(!video.paused){
  675. video.pause()
  676. console.log("pause " + this.sid)
  677. }
  678. if(state == 'stop'){
  679. video.currentTime = 0;
  680. }
  681. }else if(state){
  682. if(video.paused){
  683. video.play()
  684. console.log("play " + this.sid)
  685. }
  686. }
  687. }
  688. /* setDefaultHotScale = function(){//设置成默认热点大小
  689. var w = DATA.hotIconScale) * g_HotMeshSize.g_HotMeshWidth
  690. this.scale.set( w, w, this.scale.z)
  691. } */
  692. setTitleElem(){
  693. var root = $("#hot");
  694. var title = this.info.title;
  695. if(title){
  696. if(!this.titleElem){
  697. var elem = $(`<div></div>`)
  698. root.append(elem);
  699. this.titleElem = elem;
  700. }
  701. this.titleElem.text(title)
  702. }else{
  703. if(this.titleElem){
  704. this.titleElem.remove()
  705. this.titleElem = null;
  706. }
  707. }
  708. }
  709. showTitle(){
  710. if(!this.titleElem)return;
  711. var pos = math.getPos2d(this.position, player.camera, $("#player")[0])
  712. if(pos.trueSide){//inSight
  713. this.titleElem.css( { "left" : `${pos.pos.x}px`, "top": `${pos.pos.y}px ` });
  714. this.titleElem.css("display","block");
  715. }else{
  716. this.titleElem.css("display","none");
  717. }
  718. }
  719. hideTitle(){
  720. if(!this.titleElem)return;
  721. this.titleElem.css("display","none");
  722. }
  723. closestPanoTowardTag(e, t) {
  724. var i = []
  725. , n = []
  726. , r = this.mesh.getWorldPosition();
  727. if (e === "panorama") {
  728. var o = t.position.clone().sub(r).normalize();
  729. n.push(function(t, i) {//scoreFunctions.direction
  730. return function(e) {
  731. return e.position.clone().sub(t).normalize().dot(i) * window._settings.navigation.directionFactor
  732. }}(r, o)
  733. )
  734. }
  735. var a = new THREE.Vector3;
  736. i.push(function(e) {
  737. return Math.abs(e.position.x - r.x) > window._settings.tags.visibility.cameraClearance || Math.abs(e.position.z - r.z) > window._settings.tags.visibility.cameraClearance
  738. }, function(e) {
  739. a.copy(r).sub(e.position);
  740. var t = -THREE.Math.radToDeg(Math.atan(a.y / Math.sqrt(a.x * a.x + a.z * a.z)))
  741. , i = window._settings.tags.navigate.tiltTolerance
  742. return window._settings.insideLookLimitDown - i < t && t < window._settings.insideLookLimitUp + i
  743. },
  744. (pano)=>{ // add
  745. return player.checkHasNeighbor(pano)
  746. }
  747. ),
  748. n.push( function(t, i) {//scoreFunctions.distanceSquared
  749. return i = i || a.navigation.distanceFactor,
  750. function(e) {
  751. return t ? t.position.distanceToSquared(e.position) * i : 0
  752. }
  753. }(this, -2));
  754. var s = t.model.panos.sortByScore(i, n);
  755. /* if (s && window._settings.tags.navigate.lineOfSight) {
  756. for (var l = 0; l < s.length; l++) {
  757. var c = s[l].pano
  758. , h = c.position.distanceTo(r);
  759. p.set(c.position, r.clone().sub(c.position).normalize());
  760. var u = p.intersectObjects(t.model.colliders);
  761. if (0 === u.length || u[0].distance > h)
  762. return console.log(l),
  763. c
  764. }
  765. return null
  766. } */
  767. return s && 0 < s.length && s[0].pano
  768. }
  769. examine(options={}) {
  770. var openHot = this.info.link && this.info.actionType.openHot && !options.dontOpen
  771. var needExamine = options.examine || (!settings.dontExamHot && this.info.actionType.examine)
  772. if(!openHot && !needExamine)return;
  773. if(openHot && this.info.linkType!="common" && this.info.iframe && this.info.iframe[0]){
  774. var src = getLink(this.info.iframe[0]);
  775. if(this.info.linkType=="jumpLink"){
  776. var newPage = window.open(src, "_blank" );
  777. newPage.focus();
  778. }else if(this.info.linkType=="iframeDiv"){
  779. var div = document.createElement("div");
  780. div.style.position = 'fixed';
  781. div.style.width = div.style.height = "100%";
  782. div.style.left = div.style.top = '0';
  783. div.style["z-index"] = "999"
  784. var exit = document.createElement("div");
  785. exit.style["background-image"] = "url(images/vrOffImg.png)";
  786. exit.style.position = 'absolute';
  787. exit.style.width = exit.style.height = "50px";
  788. exit.style.left = '17px'; exit.style.top = "20px"
  789. exit.style.cursor = "pointer";
  790. exit.style["background-repeat"] = "no-repeat";
  791. exit.style["background-size"] = "25%";
  792. exit.style["background-position"] = "center center";
  793. exit.style["background-color"] = "rgba(0, 0, 0, 0.2)";
  794. exit.style["border-radius"] = "50%";
  795. exit.style["z-index"] = "3"
  796. exit.onclick = ()=>{
  797. $(div).remove()
  798. if(g_bgAudio && g_bgAudio.pauseByHot){
  799. manage.switchBgmState(true)
  800. }
  801. }
  802. var myElement = document.createElement("iframe");
  803. myElement.style.position = 'absolute';
  804. myElement.style.width = myElement.style.height = "100%";
  805. myElement.style.left = myElement.style.top = '0';
  806. myElement.src = src
  807. $("body").append(div);
  808. div.appendChild(exit);
  809. div.appendChild(myElement)
  810. if(g_bgAudio && !g_bgAudio.paused){
  811. manage.switchBgmState(false);
  812. g_bgAudio.pauseByHot = true
  813. }
  814. if(g_tourAudio)g_tourAudio.pause()
  815. }
  816. return;
  817. }
  818. if(!player.currentPano)return;
  819. var popup = document.getElementById("popup");
  820. if (openHot) {
  821. if(g_bgAudio && !g_bgAudio.paused){
  822. manage.switchBgmState(false);
  823. g_bgAudio.pauseByHot = true
  824. }
  825. if(g_tourAudio)g_tourAudio.pause()
  826. }
  827. var done = function() {
  828. player.flyingToTag = !1;
  829. openHot && window.player.emit('openHotspot', this.sid)
  830. openHot && popup.classList.remove("wait")
  831. }.bind(this);
  832. if(!needExamine){
  833. done()
  834. return;
  835. }
  836. var c = /* m.tags.navigate.nearestPano && */ this.closestPanoTowardTag(player.mode, player.currentPano) || player.currentPano
  837. , h = this.mesh.getWorldPosition();
  838. player.flyingToTag = !0;
  839. if (player.mode === 'panorama') {
  840. var d = {
  841. pano: c,
  842. lookAtPoint: h,
  843. duration: options.duration,
  844. maxDistanceOverride: null,
  845. skipWarpingCheck: !1,
  846. aimDuration: options.aimDuration,
  847. };
  848. player.flyToPano(d, done)
  849. } else {
  850. var p = {
  851. pano: c
  852. };
  853. if (h) {
  854. var f = (new THREE.Matrix4).lookAt(c.position, h, new THREE.Vector3(0,1,0));
  855. p.quaternion = (new THREE.Quaternion).setFromRotationMatrix(f)
  856. }
  857. p.callback = done,
  858. p.duration = options.duration || 1500,
  859. p.mode = 'panorama',
  860. p.aimDuration = options.aimDuration
  861. player.flyToNewMode(p)
  862. }
  863. }
  864. addModel(object){
  865. if(this.objObject){
  866. this.remove(this.objObject)
  867. }
  868. this.objObject = object;
  869. /* object.traverse((mesh)=>{
  870. if(mesh.material && mesh.type == "hotSprite"){
  871. mesh.material = this.material_;
  872. }
  873. }) */
  874. object.name = this.info.objName;
  875. object.src = this.info.objSrc
  876. this.info.hasBox = false
  877. this.addBox(false)
  878. this.remove(this.plane);
  879. this.plane = null;
  880. this.setMesh(this.objObject)
  881. //this.adjustModelAuto()
  882. if(this.info.modelBound){//应该不会改变
  883. var s = this.info.modelBound.scaleRatio
  884. this.mesh.scale.set(s,s,s)
  885. this.mesh.position.fromArray(this.info.modelBound.position)
  886. this.mesh.modelBound = this.info.modelBound
  887. }
  888. this.material_.side = THREE.FrontSide
  889. this.changeBoxHelperDisplay(false)
  890. //this.mesh.boxHelper.visible = true
  891. }
  892. addPlane(){//换成plane
  893. if(this.plane)return
  894. this.plane = new THREE.Mesh(_planeGeometry, this.material_)
  895. this.remove(this.objObject)
  896. this.objObject = null
  897. delete this.info.objSrc
  898. delete this.info.objName
  899. delete this.info.modelBound
  900. this.setMesh(this.plane)
  901. //this.material_.side = THREE.DoubleSide //双面的话飞出来会看到悬空的
  902. }
  903. setMesh(mesh){
  904. this.mesh = mesh
  905. this.add(this.mesh);
  906. this.mesh.renderOrder = 3
  907. this.changeMaterial(this.material_) //re applyTo every mesh
  908. this.mesh.traverse((mesh)=>{
  909. mesh.type = "hotSprite" //raycaster use
  910. })
  911. if(!this.mesh.boxHelper){
  912. var boxHelper = this.mesh.children.find(e=>e instanceof THREE.Box3Helper)
  913. if(boxHelper){
  914. this.mesh.boxHelper = boxHelper
  915. }else{
  916. var bound
  917. if(this.objObject){
  918. bound = new THREE.Box3().copy(this.info.modelBound.bound)
  919. }else{
  920. bound = planeBound
  921. }
  922. bound.expandByVector(new THREE.Vector3(0.0001,0.0001,0.0001))
  923. this.mesh.boxHelper = new THREE.Box3Helper( bound, new THREE.Color( "#00ffff"));
  924. this.mesh.add(this.mesh.boxHelper)
  925. this.mesh.boxHelper.material.depthTest = false;
  926. this.mesh.boxHelper.material.transparent = true
  927. this.mesh.boxHelper.visible = false
  928. }
  929. }
  930. }
  931. changeBoxHelperDisplay(show){
  932. this.visible_ = this.visible
  933. if(show){
  934. this.visible = true
  935. this.mesh.boxHelper.visible = true
  936. }else{
  937. this.visible = this.visible_
  938. this.mesh.boxHelper.visible = false
  939. }
  940. }
  941. /* addToLoadQueue() {
  942. if (this.texType == 'photo') {
  943. Hot.loadQueue.includes(this) || Hot.loadQueue.push(this)
  944. }
  945. } */
  946. requestDownload(type,callback) {
  947. var plane = this.plane;
  948. if(type == 'photo'){
  949. if(this.photoHasRequestLoad || this.texType != 'photo')return;
  950. console.log('overlay beginDownload : ' + this.sid)
  951. this.material_.map = Texture.load(this.info.texSrc, (tex)=>{
  952. callback && callback()
  953. if(!tex.image ){
  954. return //只是单纯用了相同src的tex,但image仍未加载完
  955. }
  956. if(!this._loadDones)return
  957. setTimeout(Hot.loadNext, 50)
  958. hotGroup.children.forEach(e=>{
  959. if(e.info.texSrc == this.info.texSrc){
  960. e.material_.color.set("#FFFFFF")
  961. e.material_.opacity = 1;
  962. console.log('overlay loaded: ' + e.sid)
  963. e.hasRequestLoad = true
  964. e.texMedia = tex.image
  965. {//animation不同致使的不能使用同一个texture
  966. if(settings.isEdit){
  967. if(animateTexSrcs[e.info.texSrc]){
  968. e.material_.map = new THREE.Texture(); //编辑动画直接不用一个texture, 故而animation也不同
  969. e.material_.map.image = tex.image
  970. e.material_.map.needsUpdate = true
  971. }else{
  972. animateTexSrcs[e.info.texSrc] = 1
  973. }
  974. }else{
  975. if(animateTexSrcs[e.info.texSrc]){//已有该texSrc
  976. let finded = false
  977. for(let i of animateTexSrcs[e.info.texSrc]){
  978. if(ifSame(i[0], e.info.animateInfo)){
  979. e.material_.map = i[1]; finded = true; break;
  980. }
  981. }
  982. if(!finded){
  983. let tex = new THREE.Texture()
  984. animateTexSrcs[e.info.texSrc].set(e.info.animateInfo, tex)
  985. e.material_.map = tex
  986. e.material_.map.image = tex.image
  987. }
  988. }else{
  989. let object = new Map();
  990. object.set(e.info.animateInfo, tex)
  991. animateTexSrcs[e.info.texSrc] = object//注册第一个texSrc
  992. }
  993. }
  994. }
  995. if(e.info.animateInfo && !e.animation){
  996. e.animation = GifTexDeal.addAnimation(e.material_.map, e, e.info.animateInfo, e.sid )
  997. e.visible && e.inSight() && GifTexDeal.start(e.animation)
  998. }
  999. if(++photoLoaded == originPhotoCount){//data2.js中的所有photo加载完毕
  1000. Hot.allPhotoLoaded = true;
  1001. Hot.whenAllFileLoaded && Hot.allModelLoaded && Hot.whenAllFileLoaded()
  1002. }
  1003. {
  1004. e._loadDones.forEach(a=>a())
  1005. e._loadDones = null
  1006. }
  1007. e.material_.needsUpdate = true
  1008. }
  1009. })
  1010. })
  1011. this.material_.map.wrapS = this.material_.map.wrapT = THREE.ClampToEdgeWrapping;
  1012. this.material_.map.minFilter = THREE.LinearFilter;
  1013. this.material_.map.magFilter = THREE.LinearFilter;
  1014. this.material_.map.generateMipmaps = true;
  1015. this.photoHasRequestLoad = true
  1016. }else if(type == 'model'){
  1017. if(this.modelHasRequestLoad || !this.info.objSrc)return;
  1018. //需要处理重复?
  1019. objLoader.load(this.info.objSrc, (object)=>{
  1020. this.remove(this.mesh)
  1021. this.addModel(object)
  1022. callback && callback()
  1023. if(++modelLoaded == originModelCount){//data2.js中的所有photo加载完毕
  1024. Hot.allModelLoaded = true;
  1025. Hot.whenAllFileLoaded && Hot.allPhotoLoaded && Hot.whenAllFileLoaded()
  1026. }
  1027. })
  1028. this.modelHasRequestLoad = true
  1029. }
  1030. }
  1031. }
  1032. Hot.updateVisibles = function(panos) {
  1033. if (panos === true) {
  1034. model.hotGroup.children.forEach(e=>e.updateVisible(null,true))
  1035. } else {
  1036. model.hotGroup.children.forEach(e=>e.updateVisible(panos))
  1037. }
  1038. }
  1039. Hot.beginShineHot = function(){
  1040. if(!settings.isEdit && shineMats.length == 0)return
  1041. transitions.trigger({
  1042. func: function(e) {
  1043. var opa = e <= .5 ? 2 * e : -2 * e + 2
  1044. shineMats.forEach(mat=>{
  1045. mat.uniforms.opac.value = opa;
  1046. })
  1047. },
  1048. cycling: !0,
  1049. duration: 3e3,
  1050. name: "hotShine"
  1051. })
  1052. }
  1053. Hot.getDefaulScale = function(hotIconScale){
  1054. return (hotIconScale || DATA.hotIconScale) * g_HotMeshSize.g_HotMeshWidth
  1055. }
  1056. var loadings = [];
  1057. Hot.loadQueue = []; //等待下载的overlay,目前只针对photo
  1058. Hot.maxLoadingCount = 3; //同时正在load图片的数量
  1059. Hot.loadNext = ()=>{//继续requestDownload loadQueue中前排的item
  1060. let count = Hot.maxLoadingCount - loadings.length
  1061. Hot.loadQueue.slice(0, count).forEach(e=>{
  1062. loadings.push(e)
  1063. //console.log(e)
  1064. e.hot.requestDownload(e.type, ()=>{
  1065. var i = loadings.indexOf(e)
  1066. loadings.splice(i,1)
  1067. })
  1068. })
  1069. Hot.loadQueue.splice(0, count)
  1070. }
  1071. Hot.getNeedLoad = function() {//计算获取loadQueue,每次都重新计算,覆盖旧的
  1072. if (!player || !player.domElement || !player.mode)
  1073. return;
  1074. var hots1, hots2
  1075. if (player.mode != 'panorama') {
  1076. if (Hot.loadQueue.length == 0) {
  1077. hots1 = model.hotGroup.children.filter(e=>e.texType == 'photo' && !e.photoHasRequestLoad )
  1078. hots2 = model.hotGroup.children.filter(e=>e.info.objSrc && !e.modelHasRequestLoad )
  1079. Hot.loadQueue = hots1.map(e=>{return {hot:e, type:"photo"}}).concat(
  1080. hots2.map(e=>{return {hot:e, type:"model"}})
  1081. )
  1082. }
  1083. return
  1084. }
  1085. //Hot.loadWhenOutside = true
  1086. hots1 = model.hotGroup.children.filter(e=>e.texType == 'photo' && !e.photoHasRequestLoad && (!e.info.visiblePanos || e.info.visiblePanos.includes(player.currentPano.id)))
  1087. hots2 = model.hotGroup.children.filter(e=>e.info.objSrc && !e.modelHasRequestLoad && (!e.info.visiblePanos || e.info.visiblePanos.includes(player.currentPano.id)))
  1088. if(hots1.length+hots2.length == 0){
  1089. hots1 = model.hotGroup.children.filter(e=>e.texType == 'photo' && !e.photoHasRequestLoad )
  1090. hots2 = model.hotGroup.children.filter(e=>e.info.objSrc && !e.modelHasRequestLoad )
  1091. }
  1092. var cameraDir = player.getDirection()
  1093. Hot.loadQueue = hots1.map(e=>{return {hot:e, type:"photo"}}).concat(
  1094. hots2.map(e=>{return {hot:e, type:"model"}})
  1095. )
  1096. var request = [(item)=>{
  1097. return true
  1098. }];
  1099. var rank = [(item)=>{
  1100. var dis = item.hot.mesh.getWorldPosition().distanceTo(player.position);
  1101. return -dis
  1102. }
  1103. , (item)=>{
  1104. var tagDir = item.hot.mesh.getWorldPosition().sub(player.position)
  1105. var angle = tagDir.angleTo(cameraDir)
  1106. return -angle * 20
  1107. }]
  1108. var result = common.sortByScore(Hot.loadQueue, request, rank);
  1109. //Hot.loadQueue = result ? result.slice(0, 5).map(e=>e.item) : model.hotGroup.children.filter(e=>e.texType == 'photo' && !e.hasRequestLoad).slice(0, 2);
  1110. Hot.loadQueue = result ? result.slice(0, 5).map(e=>e.item) : []
  1111. }
  1112. Hot.load = ()=>{//开始下载图片
  1113. Hot.getNeedLoad()
  1114. Hot.loadNext()
  1115. var hots1 = model.hotGroup.children.filter(e=>e.texType == 'photo' && !e.photoHasRequestLoad )
  1116. var hots2 = model.hotGroup.children.filter(e=>e.info.objSrc && !e.modelHasRequestLoad )
  1117. if (hots1.length+hots2.length > 0) {
  1118. setTimeout(Hot.load, 200)
  1119. } else {
  1120. Hot.allRequestLoad = true
  1121. console.log('allRequestLoad')
  1122. }
  1123. }
  1124. Hot.startLoad = ()=>{
  1125. originPhotoCount = hotGroup.children.filter(e=>e.texType == 'photo').length
  1126. originModelCount = hotGroup.children.filter(e=>!!e.info.objSrc).length
  1127. if(originPhotoCount == 0 )Hot.allPhotoLoaded = true
  1128. if(originModelCount == 0) Hot.allModelLoaded = true;
  1129. if(Hot.allModelLoaded && Hot.allPhotoLoaded) Hot.whenAllFileLoaded && Hot.whenAllFileLoaded()//所有加载完毕
  1130. else{
  1131. Hot.load()
  1132. }
  1133. }
  1134. window.Hot = Hot
  1135. /* var ball = new THREE.Mesh(new THREE.SphereBufferGeometry(0.01),new THREE.MeshBasicMaterial({color:"#f00",depthTest:false,transparent:true}))
  1136. var balls = []
  1137. var addPoint = function(point){
  1138. console.log(point)
  1139. var ball1 = ball.clone()
  1140. model.add(ball1);
  1141. ball1.position.copy(point)
  1142. balls.push(ball1)
  1143. }
  1144. var addPoints = function(points){
  1145. balls.forEach(e=>model.remove(e))
  1146. balls = []
  1147. points.forEach(e=>addPoint(e))
  1148. }
  1149. */
  1150. }
  1151. /*
  1152. 保存 JSON.stringify(editTool.hotpoint.getSavingInfo())
  1153. 最好后台有针对手机版的做一个压缩。压缩成几个档位。
  1154. 安卓手机firefox出现过视频mesh不可见或者闪烁的情况。
  1155. 视频最容易导致崩溃, 模型还好
  1156. 数据速率为4064kbps,1920*1080px 时测试部门电脑崩溃
  1157. 数据速率为1824kbps,720 *576px 时正常
  1158. 所以尽量降到2000以下 同时播放个数最好不超过2个 可能需要将src归零 并延迟加载、不自动播放
  1159. */