123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582 |
- import { scene, camera, controls, renderer } from './common/scene';
- 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();
- d3.json('data/world.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 countryObj;
-
-
- // Setup cache for country textures
- var countries = topojson.feature(data, data.objects.countries);
- var geo = geodecoder(countries.features);
- var textureCache = memoize(function (cntryID, color) {
- var country = geo.find(cntryID);
- return mapTexture(country, color);
- });
- 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/newEarth3.jpg"/* ,function(t){earthMap = t;} */);//newEarth.png
-
- let mapMat0 = new THREE.MeshPhongMaterial({map: earthMap,/* alphaMap:alphaGrayMap, */transparent: true});
- var outerLayer = new THREE.Mesh(new THREE.SphereGeometry(400, segments, segments), mapMat0);
- outerLayer.rotation.y = Math.PI;
- outerLayer.addEventListener('click', onGlobeClick);
- outerLayer.addEventListener('mousemove', onGlobeMousemove);
-
-
-
- //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(400, segments, segments), mapMaterial);
- baseMap.rotation.y = Math.PI; */
- // create a container node and add the two meshes
- root = new THREE.Object3D();
- root.scale.set(1.2, 1.2, 1.2);
- //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);
-
-
-
- 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;
- // Get new camera position
- var temp = new THREE.Mesh();
- temp.position.copy(convertToXYZ(latlng, 980));
- 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);
-
-
-
-
- }
- //document.title = "asas"
- function onGlobeMousemove(event,originEvent,_this) { //为什么mousedown的时候会立即触发mousemove?
- if(window.lastMouse.x){
- 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;
- d3.select("#introduce").select("h2").html(currentChName);
- d3.select("#introduce").select(".below").html(currentChosed);
- if(d3.select("#introduce").node().style.display === "none"){
- d3.select("#introduce").node().style.display = "";
- rePos({text:true,earth:true});
- }else{
- rePos({text:true});
- }
-
- //map = isMobile ? mapTexture(geo.find(country.code), '#FF0011'):textureCache(country.code, '#FF0011');
- //if(isMobile) document.title = "isMobile"
- map = textureCache(country.code, '#FF0000');
- material = new THREE.MeshPhongMaterial({map: map,opacity:.5, transparent: true});
- 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;
- }
- }
- if (!isMobile && country !== null && country.code !== currentCountry) {
- currentCountry = country.code;
- map = textureCache(country.code, '#FFFF00');
- //map = isMobile ? mapTexture(geo.find(country.code), '#FFF900') : textureCache(country.code, '#FFF900');
- material = new THREE.MeshPhongMaterial({map: map,opacity:.5, transparent: true});
- 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 && _this){
- d3.select("#introduce").node().style.display = "none";
-
- }
- }
- setEvents(camera,canvas, [outerLayer], 'click');
- setEvents(camera,canvas, [outerLayer], 'mousemove', 10);
-
-
-
- function rePos(o) {//introduce重新定位
- //var onlyTitle = (d3.select('#introMenu').node().style.display==="none");
- var intro = d3.select("#introduce").node();
- var infoH = intro.clientHeight;
- if(infoH){
- if(o.earth){
- var e = Math.min(window.innerWidth/2,window.innerHeight*0.95);
- var offset = Math.max(0, window.innerHeight - e)/2;
- canvas.style.top = offset + "px";
- renderer.setSize(e, e);
- }
- if(o.text){
- var infoH = intro.clientHeight;
- var earthH = canvas.clientHeight || window.innerWidth*0.3;//(onlyTitle?0.1:0.3)
- if(infoH){
- var f1 = parseFloat(intro.style["font-size"]);
- if(f1!=f1) f1 = 1; //NAN
- var ratio = earthH/infoH/1.2;
- var size = Math.min(Math.max(1, f1 * ratio ), 1.5);
- intro.style["font-size"] = size + "em";
- (size<1.1)?(addClass(intro,"weight")):(removeClass(intro,"weight"));
-
-
-
- }
-
- }
-
- }
-
- }
-
-
- var canvasToImg = function(canvas){
- var type = 'png';
- var imgData = canvas.toDataURL(type);
- return imgData;
- }
-
-
-
- d3.json('data/worldInfo.json', function (err, introData) {//和info跳转有关
- //跳转绑定:
- var intro = d3.select("#introduce").node();
- var menu = d3.select("#introMenu").node();
- var artifact = d3.select("#artifact").node();
-
- for(var i=0; i<3; i++){//三个菜单的点击
- bind(menu.children[i],"click",function(i){
- return function(){
-
- countryObj = introData.countries[currentChosed];
- if(!countryObj)return;//没有改国家的展览
- //if(state[state.length-1] == "earth")hangUpEarth();
- var type = getIndex(this);
- switch(type){
- /* case "countryIntro":
- showCountryIntro(); break;
- case "culture":
- showCultureIntro(); break; */
- case "artifact":
- showArtifactIntro(); break;
- /* case "artifactIntro":
- artifactIntro(); break; */
- /* case "interview":
- artifactInterview(); break;
- case "music":
- artifactMusic(); break; */
- default:
- console.log("其他");
- }
-
- }
- }(i))
- }
-
-
- var hangUpEarth = function(){
- renderer.render(scene, camera);
- var img = document.createElement('img');
- img.id = "ToEarth";
- img.src = canvasToImg(canvas);
- img.style.top = canvas.style.top;
- img.style.cursor = "pointer";
- img.style.height = img.style.width = canvas.style.height;
- img.className = "canvasArea";
- img.style['box-shadow'] = "none";
- canvas.parentElement.appendChild(img);
- canvas.style.display = "none";
- setTimeout(function(){
- img.style.width = img.style.height = "50px";
- img.style.top = "0";
- bind(img, "click", backToEarth);
-
- },30)
-
-
- }
- var dropDownEarth = function(){
- var img = d3.select('#ToEarth').node();
- unbind(img, "click", backToEarth);
- img.style.width = "";
-
-
- var e = Math.min(window.innerWidth/2,window.innerHeight*0.95);
- var offset = Math.max(0, window.innerHeight - e)/2;
-
- img.style.height = img.style.width = e + "px";
- img.style.top = offset + "px";
-
- setTimeout(function(){
- img.parentElement.removeChild(img);
- canvas.style.display = "";
- rePos({text:true,earth:true});
- },400)
- }
-
-
- var backBtn = d3.select("#back").node();
- bind(backBtn,"click",function(){
- var from = state[state.length-1];
- var to = state[state.length-2];
- if(!to) return;
- state.pop();
- switch(from){
- case "countryIntro":
- exitCountryIntro(); break;
- case "culture":
- exitCultureIntro(); break;
- case "artifact":
- exitArtifactIntro(); break;
-
- case "itemDisplay":
- exitItemDisplay(); break;
- /* case "artifactIntro":
- exitArtifactIntro(); break; */
- case "interview":
- exitArtifactInterview(); break;
- case "music":
- exitArtifactMusic(); break;
- default:
- console.log("其他");
- }
-
- switch(to){
- case "earth":
- backToEarth(); break;
- case "countryIntro":
- showCountryIntro(); break;
- case "culture":
- showCultureIntro(); break;
- case "artifact":
- showArtifactIntro(true); break;
- /* case "artifactIntro":
- artifactIntro(); break; */
- case "interview":
- artifactInterview(); break;
- case "music":
- artifactMusic(); break;
- default:
- console.log("其他");
-
-
- }
-
-
- })
-
-
-
- function backToEarth(){//确保清除所有,因为包括退了一级的和直接回到地球的
- state = ["earth"];
- artifact.style.display = "none";
- //intro.children[0].innerHTML = currentChName;
- menu.removeChild(menu.children[0])
- menu.children[0].innerHTML = '<span class="number">NO.1</span>国家背景<span class="EngPostfix">National Background</span>';
- menu.children[1].innerHTML = '<span class="number">NO.2</span>器物介绍<span class="EngPostfix">Instrument Introduction</span>';
- menu.children[2].innerHTML = '<span class="number">NO.3</span>文化传承<span class="EngPostfix">Cultural Heritage</span>';
- menu.children[2].style.display = "";
- menu.style.display = "";
- setIndex(menu.children[0],"countryIntro");
- setIndex(menu.children[1],"artifact");
- setIndex(menu.children[2],"culture");
- removeClass(intro,"largeBelow");
- intro.children[1].innerHTML = currentChosed;
- var modelArea = d3.select("#modelArea").node();//将模型和图片展示清除
- var imageArea = d3.select("#imageArea").node();
- if(modelArea){
- modelArea.parentElement.removeChild(modelArea);
- }
- if(imageArea){
- imageArea.parentElement.removeChild(imageArea);
- }
- dropDownEarth();
- }
- function exitItemDisplay(){//从单个展示到列表
- var modelArea = d3.select("#modelArea").node();
- var imageArea = d3.select("#imageArea").node();
- if(modelArea){
- modelArea.style.display = "none";
- }
- if(imageArea){
- imageArea.style.display = "none";
- }
- }
- function exitArtifactIntro(){//从文字介绍到 单个展示三个菜单
-
- }
-
- function showArtifactIntro(backHere){//back表示是从下一级后退到这里的,此时不用重新生成列表.
-
-
- menu.style.display = "none";
- //menu.innerHTML = '<span>乐器介绍</span><div index="artifactIntro"></div><a index="interview">专家访谈</a><a index="music">音频欣赏</a>';
-
- if(!backHere){
- //menu.children[0].innerHTML = "乐器介绍";
- hangUpEarth();
- var add = document.createElement('div'); //新增一个不可点击的选项:乐器介绍
- add.innerHTML = '<span class="title"><span class="point">·</span>乐器介绍<span class="EngPostfix">Instrument Introduction</span></span><span class="instrumentText" index="artifactIntro"></span>'
- menu.insertBefore(add,menu.children[0]);
- menu.children[1].innerHTML = '<span class="point">·</span>专家访谈<span class="EngPostfix">Experts Interview</span>';
- menu.children[2].innerHTML = '<span class="point">·</span>音频欣赏<span class="EngPostfix">Music Appreciation</span>';
- menu.children[3].style.display = "none";
- //setIndex(menu.children[0],"artifactIntro");
- setIndex(menu.children[1],"interview");
- setIndex(menu.children[2],"music");
- setIndex(menu.children[3],"");
- state.push("artifact");
- intro.children[1].innerHTML = "器物介绍";
- addClass(intro,"largeBelow");
- var len1 = countryObj.artifact.length;
- var len2 = artifact.children.length;
-
-
- for(var i=0; i<len1; i++){
- if(i>len2-1){
- 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)//绑定点击事件
-
- }
- else{
- item = artifact.children[i];
- }
- item.style.display = "";//解除隐藏
- var itemObj = countryObj.artifact[i];
- if(itemObj.type === "image"){
- item.children[0].style['background-image'] = "url(data/display/600/"+itemObj.name+".jpg)";
- }
- }
- if(len2>len1){//多余的隐藏
- for(var i=len1; i<len2; i++){
- artifact.children[i].style.display = "none";
- }
- }
- }
- artifact.style.display = "";
- }
- function clickItem(){//点击列表
- state.push('itemDisplay');
- var itemObj = countryObj.artifact[getIndex(this)];
- menu.style.display = "";
- getByIndex(menu,"artifactIntro").innerText = itemObj.intro;
- rePos({text:true})
- if(itemObj.type === "model"){
- 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){//虽已有,但展示的是别的模型,要删除重新创建
- 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/display/"+itemObj.name+".4dage", { root:modelArea, backgroundColor:[238/255,238/255,238/255],ifPlain:true, width: 800, height: 600, autoStart: true, fullFrame: true, pagePreset: false } );
- 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 = inner.style.height = "100%";
- }else{
- var inner = imageArea.children[0];
- imageArea.style.display = "";
- }
- inner.style["background-image"] = "url(data/display/2048/"+itemObj.name+".jpg"+")";
- }
-
- }
-
-
-
- });
-
-
-
-
-
-
-
-
-
-
-
-
-
- });
- function animate() {
- controls.update();
- if(root && rotate)root.rotation.y+=0.002;
- requestAnimationFrame(animate);
- renderer.render(scene, camera);
- }
- animate();
|