123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- import { scene, camera, light3, controls, renderer } from './common/scene2';
- import { setEvents } from './common/setEvents';
- import { convertToXYZ, getEventCenter, geodecoder } from './common/geoHelpers';
- import { mapTexture } from './common/mapTexture';
- import { getTween, memoize } from './common/utils';
- import topojson from 'topojson';
- import THREE from 'THREE';
- import d3 from 'd3';
- import fdage from 'fdage';
- var root,rotate;
- var getIndex = function(elem,index){
- index = index || 'index';
- return elem.getAttributeNode(index)&&elem.getAttributeNode(index).nodeValue;
- }
- var setIndex = function(elem,name,index){
- index = index || 'index';
- elem.setAttribute(index,name);
- }
- var getByIndex = function(elem,name,index){
- var result;
- for(var i=0; i<elem.children.length; i++){
- if(getIndex(elem.children[i],index)===name){
- result = elem.children[i];
- }
- }
- if(result) return result;
- else for(var i=0; i<elem.children.length; i++){
- result = result || getByIndex(elem.children[i],name,index);
- }
- return result;
- }
- var body = d3.select('body').node();
- var hint = d3.select("#hint").node()
- d3.json('data/world2.json', function (err, data) {
- d3.select("#loading").transition().duration(500)
- .style("opacity", 0).remove();
- var currentCountry,currentChosed,currentChName, overlay, chosedOverlay;
- var pointDown = 0;//鼠标按下为true,抬起为false
- var draged = 0; //是否才拖拽过
-
- var segments = 155; // number of vertices. Higher = better mouse accuracy
- var isMobile = /Android|iPhone|iPod|iPad|Windows Phone|IEMobile|BlackBerry|webOS/.test(navigator.userAgent);
- var regionObj;
-
-
- // Setup cache for country textures
- var countries = topojson.feature(data, data.objects.countries);
- var geo = geodecoder(countries.features);
- var textureCache = memoize(function (cntryID, color, lineWidth, lineColor) {
- var country = geo.find(cntryID);
- if(cntryID == "India"){
- /* for(var i=8; i<17; i++){
- country.geometry.coordinates[0][i][1] -=2;
- } */
-
- country.geometry.coordinates[0][8] = [92, 26.4]//92.07921,27.447946
- country.geometry.coordinates[0][9] = [92.27524,26.6]//[91.683,27.76053]
- country.geometry.coordinates[0][10] = [92.47524,26.6]//[92.47524,27.8821024]
- country.geometry.coordinates[0][11] = [93.41134113,26.628851]//[93.41134113,28.628851]
- country.geometry.coordinates[0][12] = [94.5634563,27.27140242]//[94.5634563,29.27140242]
- country.geometry.coordinates[0][13] = [95.39153,27.0282749]//[95.39153,29.0282749]
- country.geometry.coordinates[0][14] = [96.111611,27.445064]//[96.111611,29.445064]
- country.geometry.coordinates[0][15] = [96.579657,27.4]//[96.579657,28.819879933]
- country.geometry.coordinates[0][16] = [96.21962,27.903089]//[96.21962,28.403089]
- country.geometry.coordinates[0][17] = [96.3,27]
-
- }
- return mapTexture(country, color, lineWidth, lineColor);
- });
- window.mapTexture = mapTexture;
- // Base globe with blue "water"
- /* let blueMaterial = new THREE.MeshPhongMaterial({color: '#0889d5', transparent: true}); //2B3B59
- let sphere = new THREE.SphereGeometry(400, segments, segments);
- let baseGlobe = new THREE.Mesh(sphere, blueMaterial);
- baseGlobe.rotation.y = Math.PI;
- baseGlobe.addEventListener('click', onGlobeClick);
- baseGlobe.addEventListener('mousemove', onGlobeMousemove); */
- //baseGlobe.addEventListener('mousemove', onGlobeMousemove);
- var texture2DLoader = new THREE.TextureLoader();
- var earthMap, alphaGrayMap;
- earthMap=texture2DLoader.load("data/newEarth4.jpg");//newEarth.png
-
- let mapMat0 = new THREE.MeshPhongMaterial({map: earthMap, lights: true, transparent: true});
- mapMat0.specular = new THREE.Color(1,0.96,0.9);
- mapMat0.shininess = 1 ;
- //mapMat0.reflectivity = 10;
-
- var outerLayer = new THREE.Mesh(new THREE.SphereGeometry(400, segments, segments), mapMat0);
- outerLayer.rotation.y = Math.PI;
-
-
-
-
- //add base map layer with all countries
- /* let worldTexture = mapTexture(countries, '#647089');
- let mapMaterial = new THREE.MeshPhongMaterial({map: worldTexture,transparent: true});
- var baseMap = new THREE.Mesh(new THREE.SphereGeometry(401, segments, segments), mapMaterial);
- baseMap.rotation.y = Math.PI;
- mapMaterial.shininess = 1; */
- // create a container node and add the two meshes
- root = new THREE.Object3D();
- root.scale.set(1.5, 1.5, 1.5);
- //root.add(baseGlobe);
- //root.add(baseMap);
- root.add(outerLayer);
-
- scene.add(root);
-
-
-
-
-
-
- var bind = function(elem, event, func, bool) {
- bool = bool || false;
- if (elem.addEventListener)
- elem.addEventListener(event, func, bool);
- else if (elem.attachEvent)
- elem.attachEvent('on' + event, func);
- }
- var unbind = function(elem, event, func, bool) {
- bool = bool || false;
- if (elem.removeEventListener)
- elem.removeEventListener(event, func, bool);
- else if (elem.detachEvent)
- elem.detachEvent('on' + event, func);
- }
-
- var canvas = d3.select("#canvas").node();
- //地球滑动绑定:
- window.lastMouse = {};
- bind(canvas,"mousedown",function(event){
- window.lastMouse.x = event.offsetX;
- window.lastMouse.y = event.offsetY;
- })
-
- //地球初始转动绑定:
- rotate = true;
- var endRotate = function(){
- rotate = false;
- unbind(canvas,"mousedown",endRotate);
- }
- bind(canvas,"mousedown",endRotate);
-
- setEvents(camera,canvas, [outerLayer], 'click');
- setEvents(camera,canvas, [outerLayer], 'mousemove', 10);
-
- function rePos(o) { //重新定位
-
- var introOverlay = introduce.parentElement;
-
- if(layer<2){
-
- var ratio = 320/365;//横高比
- var h = window.innerHeight;
- var w = h * ratio;
- camera.aspect = w/h;
- camera.updateProjectionMatrix();
- renderer.setSize(w, h);
- introOverlay.style.left = w + "px";
- }else{
- introOverlay.style.left = "";
- }
- /* if(layer == 2){//intro要往左边来点
-
- } */
- }
-
-
- var canvasToImg = function(canvas){
- var type = 'png';
- var imgData = canvas.toDataURL(type);
- return imgData;
- }
- /* var artifactDiv = d3.select("#introduce").select("#artifact").node();
- for(var i=0; i<10; i++){
- var item = document.createElement('div');
- addClass(item,"item");
- artifactDiv.appendChild(item);
-
- } */
-
-
-
- d3.json('data/worldInfo2.json', function (err, introData) {//和info跳转有关
-
- outerLayer.addEventListener('click', onGlobeClick);
- outerLayer.addEventListener('mousemove', onGlobeMousemove);
-
- //跳转绑定:
- var i = d3.select("#introduce");
- var introduce = i.node();
- var artifact = i.select("#artifact").node();
- var introTitle = i.select(".introTitle").node();
- var introText = i.select(".introText").node();
- var backBtn = i.select("#back").node();
- var introBanner = i.select("#introBanner").node();
- var music = i.select("#music").node();
-
-
- bind(backBtn,"click",function(){//从第二层返回地球层
- layer = 1;
- removeClass(introduce,"layer2");
- //removeClass(introduce,"false3d");
- showIntroWithBannerAnima({animate:true});
- artifact.style.display = "";
- canvas.style.display = "";
- backBtn.style.display = "none";
- music.innerHTML = "";
- music.style.display = "none";
- regionObj = introData.region[currentChosed];
- introTitle.innerHTML = currentChName;
- introText.innerHTML = regionObj.regionIntro;
- rePos();
-
- var modelArea = d3.select("#modelArea").node();
- var imageArea = d3.select("#imageArea").node();
- if(modelArea){
- modelArea.style.display = "none";
- //if(isMobile){
- modelArea.children[0].src = "about:blank";//如果是手机就关闭释放内存
- modelArea.parentElement.removeChild(modelArea);
- modelArea = null;
- //}
-
- }
- if(imageArea){
- imageArea.style.display = "none";
- }
-
- })
-
- function showArtifactList(){
- var len = regionObj.artifact.length;
- for(var i=0; i<len; i++){
-
- var item = document.createElement('div');
- var inner = document.createElement('div');
- addClass(item,"item");
- artifact.appendChild(item);
- item.appendChild(inner);
- setIndex(item,i);
- bind(item,"click",clickItem)//绑定点击事件
- var itemObj = regionObj.artifact[i];
- //if(itemObj.type === "image"){
- item.children[0].style['background-image'] = "url(data/display/600/"+itemObj.name+".jpg)";
- //}
-
- }
-
- }
- function clickItem(){//点击列表
- layer = 2;
- hint.style.display = "none";
- addClass(introduce,"layer2");
- artifact.style.display = "none";
- backBtn.style.display = "block";
- canvas.style.display = "none";
- //getByIndex(menu,"artifactIntro").innerText = itemObj.introduce;
- rePos()
- showIntroWithBannerAnima({animate:true})
- var itemObj = regionObj.artifact[getIndex(this)];
- introTitle.innerHTML = itemObj.title || "";
- introText.innerHTML = itemObj.intro || "";
- if(itemObj.music){
- music.innerHTML += '<label>音频</label>';
- for(var i in itemObj.music){//elem.setAttribute('index',name); autoplay="autoplay"
- music.innerHTML += ('<audio loop="loop" controls="true"><source src="data/music/'+itemObj.music[i]+'" type="audio/mp3"></audio>');
- }
- music.style.display = "";
- }
-
- if(itemObj.type === "true3d" || itemObj.type === "false3d" ){
- //(itemObj.type === "false3d")&& addClass(introduce,"false3d");
- var modelArea = d3.select("#modelArea").node();
- if(!modelArea){
- modelArea = document.createElement("div");
- addClass(modelArea,"canvasArea");
- modelArea.id = "modelArea";
- body.appendChild(modelArea);
- }else{
- if(getIndex(modelArea)!==itemObj.name){//虽已有,但展示的是别的模型,要删除重新创建
- if(modelArea.children&&modelArea.children[0].src) modelArea.children[0].src = "about:blank";
- modelArea.parentElement.removeChild(modelArea);
- modelArea = document.createElement("div");
- addClass(modelArea,"canvasArea");
- modelArea.id = "modelArea";
- body.appendChild(modelArea);
- }
- modelArea.style.display = "";
- }
- if(getIndex(modelArea)!==itemObj.name){
- //fdage.embed( "data/ture3d/model/"+itemObj.name+".4dage", { root:modelArea, backgroundColor:[238/255,238/255,238/255],ifPlain:true, width: 800, height: 600, autoStart: true, fullFrame: true, pagePreset: false } );
- var page = document.createElement("iframe");
- page.src = "data/"+itemObj.type+"/"+itemObj.name+".html";
- modelArea.appendChild(page);
- setIndex(modelArea,itemObj.name);
-
- }
-
- }else{
- var imageArea = d3.select("#imageArea").node();
- if(!imageArea){
- imageArea = document.createElement("div");
- addClass(imageArea,"canvasArea");
- imageArea.id = "imageArea";
- body.appendChild(imageArea);
- var inner = document.createElement("div");
- imageArea.appendChild(inner);
- inner.style.width = "100%";
- inner.style.height = "94%";
- inner.style['margin-top'] = "2%";
- }else{
- var inner = imageArea.children[0];
- imageArea.style.display = "";
- }
- inner.style["background-image"] = "url(data/display/2048/"+itemObj.name+".jpg"+")";
- }
-
- }
-
-
-
- function showIntroWithBannerAnima(o){
-
- if(o.animateOrnot && introduce.style.display == "none"){//如果之前introduce消失,则要有动画,如果不小时,就无动画
-
- introduce.style.display = "";
- removeClass(introBanner,"show");
- setTimeout(function(){
- addClass(introBanner,"show");
- },100)
-
- }else if(o.show){
- introduce.style.display = "";
- }else if(o.hide){
- introduce.style.display = "none";
- removeClass(introBanner,"show");
- }
- if(o.animate){
- removeClass(introBanner,"show");
- setTimeout(function(){
- addClass(introBanner,"show");
- },100)
- }
-
-
- }
-
-
-
- function onGlobeMousemove(event,originEvent,_this) { //为什么mousedown的时候会立即触发mousemove?
- if(window.lastMouse.x){
- hint.style.display = "none"
- return;
- }
- var map, material;
- // Get pointc, convert to latitude/longitude
- var latlng = getEventCenter.call(this||_this, event, 400);
-
- // Look for country at that latitude/longitude
- var country = geo.search(latlng[0], latlng[1]);
- if(country && _this && country.code !== currentChosed){//点击的区域 _this表明是由click的触发的
-
- currentChosed = country.code;
- currentChName = country.chName;
- var imgName;
- switch(currentChosed){
- case "Germany":
- imgName = "Austria"; break; //共用一张
- case "Liang Yi":
- case "Yunnan Yi":
- imgName = "Yi"; break;
-
- case "England":
- case "United Kingdom":
- case "Belarus":
- imgName = "flower"; break;
- case "Indonesia":
- imgName = "Bali"; break;
- default:
- imgName = currentChosed;
- }
-
- introBanner.style["background-image"] = 'url("data/bannerImg/'+imgName+'.png")';
- //出现该地区的介绍和器物列表
- regionObj = introData.region[currentChosed];
- layer = 1;
- introTitle.innerHTML = currentChName;
- introText.innerHTML = "";
- artifact.innerHTML = "";
- if(regionObj){
- introText.innerHTML = regionObj.regionIntro;
- showArtifactList();
- }
- map = textureCache(country.code, 'rgba(180,36,1,1)');
- material = new THREE.MeshPhongMaterial({map: map,opacity:.5, transparent: true});
- material.shininess = 1 ;
- if (!chosedOverlay) {
- chosedOverlay = new THREE.Mesh(new THREE.SphereGeometry(405, 30, 30), material);
- chosedOverlay.rotation.y = Math.PI;
- root.add(chosedOverlay);
- }else{
- chosedOverlay.material = material;
- }
- }/* else if(country == null && _this){
- introduce.style.display = "none";
- BannerAnima(false);
- }else if(country&& _this){
- introduce.style.display = "";
- BannerAnima(true)
-
- } */
- if(!isMobile && country !== null){
- hint.style.display = "block";
- if(originEvent){
- hint.innerHTML = country.chName;
- hint.style.left = Math.min(originEvent.clientX + 10, window.innerWidth - hint.clientWidth)+ "px";
- hint.style.top = Math.min(originEvent.clientY + 10, window.innerHeight - hint.clientHeight)+ "px";
- }
- }
-
- if (!isMobile && country !== null && country.code !== currentCountry) { //滑动到的区域
- currentCountry = country.code;
- map = textureCache(country.code, 'rgba(255,255,255,0.4)', '2', '#FFFFFF');
- //map = isMobile ? mapTexture(geo.find(country.code), '#FFF900') : textureCache(country.code, '#FFF900');
- material = new THREE.MeshPhongMaterial({map: map,transparent: true});
- material.shininess = 1 ;
- if (!overlay) {
- overlay = new THREE.Mesh(new THREE.SphereGeometry(405, 30, 30), material);
- overlay.rotation.y = Math.PI;
- root.add(overlay);
- } else {
-
- overlay.material = material;
- }
- }else if(country == null){
- hint.style.display = "none";
- }
-
-
- if(country == null && _this){
- showIntroWithBannerAnima({hide:true})
- }else if(country&& _this){
- showIntroWithBannerAnima({show:true,animateOrnot:true})
-
- }
-
-
- }
- function onGlobeClick(event,originEvent) {//mouseup 在canvas上mouseup不一定会执行这个
-
- if(lastMouse.x){
- var x = originEvent.offsetX;
- var y = originEvent.offsetY;
- if((Math.abs(window.lastMouse.x - x)+Math.abs(window.lastMouse.y - y))>10){
- window.lastMouse.x = null;
- window.lastMouse.y = null;
- return;
- }
- }
- window.lastMouse.x = null;
- window.lastMouse.y = null;
-
-
- // Get pointc, convert to latitude/longitude
- var latlng = getEventCenter.call(this, event,400);//radius = 150
- latlng[1]+=(root.rotation.y*180/Math.PI -15); //因为一开始地球在旋转,所以要加上这个offset。另外地球左移后观察的中心点右移,所以也要改。
- // Get new camera position
- var temp = new THREE.Mesh();
- temp.position.copy(convertToXYZ(latlng, 1000));
- temp.lookAt(root.position);
- temp.rotateY(Math.PI);
- for (let key in temp.rotation) {
- if (temp.rotation[key] - camera.rotation[key] > Math.PI) {
- temp.rotation[key] -= Math.PI * 2;
- } else if (camera.rotation[key] - temp.rotation[key] > Math.PI) {
- temp.rotation[key] += Math.PI * 2;
- }
- }
- var tweenPos = getTween.call(camera, 'position', temp.position);
- d3.timer(tweenPos);
- var tweenRot = getTween.call(camera, 'rotation', temp.rotation);
- d3.timer(tweenRot);
-
-
-
- onGlobeMousemove(event,null,this);
-
- }
- });
- });
- function animate() {
- controls.update();
- light3.position.set(camera.position.x,camera.position.y,camera.position.z);
- light3.position.applyAxisAngle(new THREE.Vector3(0,1,0),0.9)
- if(root && rotate)root.rotation.y+=0.002;
- requestAnimationFrame(animate);
- renderer.render(scene, camera);
- }
- animate();
- window.cc = function(lon,lat){
- var scale = [0.03600360036003601,0.017366249624962495];
- var translate = [-180,-90];
- return [parseInt((lon-translate[0])/scale[0]), parseInt((lat-translate[1])/scale[1])];
- }
- window.vv = function(x,y){
- var scale = [0.03600360036003601,0.017366249624962495];
- var translate = [-180,-90];
- return [x*scale[0]+translate[0], y*scale[1]+translate[1]];
- }
|