block by jeremycflin 5865fed4d1479c27828c

5865fed4d1479c27828c

Full Screen

script.js

var dataSet = [
  ["大陸地區",101,"上海交通大學",65,"http://www.sjtu.edu.cn/"],
  ["大陸地區",101,"北京大學",82,"http://www.pku.edu.cn/"],
  ["大陸地區",101,"廈門大學",40,"http://www.xmu.edu.cn/"],
  ["日本",101,"大阪大學",35,"http://www.osaka-u.ac.jp/"],
  ["日本",101,"立命館大學",32,"http://www.ritsumei.jp/index_j.html"],
  ["日本",101,"東北大學",30,"http://www.tohoku.ac.jp/en/"],
  ["美國",101,"加州大學柏克萊分校",63,"http://www.berkeley.edu/"],
  ["美國",101,"史丹福大學",56,"http://www.stanford.edu/"],
  ["美國",101,"西來大學",45,"http://www.uwest.edu/site/"],
  ["大韓民國(南韓)",101,"東亞大學",25,"http://www.donga.ac.kr/"],
  ["大韓民國(南韓)",101,"成均館大學",24,"http://www.skku.edu/index_pc.jsp"],
  ["大韓民國(南韓)",101,"又松大學",22,"http://www.wsu.ac.kr/site/main/intro/intro.html"],
  ["德意志聯邦共和國",101,"海德堡大學",51,"http://www.uni-heidelberg.de/"],
  ["德意志聯邦共和國",101,"漢堡大學",29,"http://www.uni-hamburg.de/"],
  ["德意志聯邦共和國",101,"柏林自由大學",19,"http://www.fu-berlin.de/"],
  ["法國",101,"里爾天主教大學",34,"http://www.univ-catholille.fr/"],
  ["法國",101,"里昂大三大學",23,"http://www.univ-lyon3.fr/"],
  ["法國",101,"特魯瓦高等商學院",11,"http://www.educations.com/study-abroad/groupe-esc-troyes-school-of-management/"],
  ["英國",101,"牛津大學哈福特學院",39,"http://www.ox.ac.uk/"],
  ["英國",101,"北安普頓大學",13,"http://www.northampton.ac.uk/"],
  ["英國",101,"愛丁堡大學",10,"http://www.ed.ac.uk/home"],
  ["荷蘭王國",101,"烏特列茲大學",25,"http://www.uu.nl/"],
  ["荷蘭王國",101,"葛洛寧恩大學",21,"http://www.rug.nl/"],
  ["荷蘭王國",101,"萊登大學",8,"http://www.leidenuniv.nl/"],
  ["捷克共和國",101,"布爾諾科技大學",18,"https://www.vutbr.cz/en/"],
  ["捷克共和國",101,"捷克科技大學",11,"http://www.cvut.cz/"],
  ["捷克共和國",101,"哈德克.卡爾威大學",8,"https://www.uhk.cz/en-GB/UHK"],
  ["加拿大",101,"漢堡學院",15,"http://www.humber.ca/"],
  ["加拿大",101,"布洛克大學",11,"http://www.brocku.ca/"],
  ["加拿大",101,"維多利亞大學",10,"http://www.uvic.ca/"],
  ["瑞典王國",101,"林雪平大學",20,"http://www.liu.se/?l=en"],
  ["瑞典王國",101,"皇家理工學院",12,"http://www.kth.se/"],
  ["瑞典王國",101,"查爾默大學",10,"http://www.chalmers.se/en/Pages/default.aspx"],
  ["澳大利亞",101,"迪肯大學",15,"http://www.deakin.edu.au/"],
  ["澳大利亞",101,"昆士蘭大學",10,"http://www.uq.edu.au/"],
  ["澳大利亞",101,"昆士蘭科技大學",8,"https://www.qut.edu.au/"],
  ["香港",101,"香港中文大學",26,"http://www.cuhk.edu.hk/chinese/"],
  ["香港",101,"香港城市大學",15,"http://www.cityu.edu.hk/cityu/index-tc.htm"],
  ["香港",101,"樹仁大學",12,"http://www.hksyu.edu/"],
  ["西班牙王國",101,"馬德里自治大學",9,"http://www.uam.es/ss/Satellite/es/home/"],
  ["西班牙王國",101,"納瓦拉大學",8,"http://www.unav.edu/web/biblioteca"],
  ["西班牙王國",101,"卡斯提亞拉曼查大學",7,"https://www.uclm.es/english/"],
  ["奧地利共和國",101,"林茲大學",20,"http://www.jku.at/content"],
  ["奧地利共和國",101,"茵斯堡大學",15,"http://www.uibk.ac.at/"],
  ["奧地利共和國",101,"維也納大學",8,"http://www.univie.ac.at/"],
  ["泰王國(泰國)",101,"湄州大學",7,"http://www.mju.ac.th/about/mju-about-2004/INDEX.html"],
  ["泰王國(泰國)",101,"曼谷大學",6,"http://www.bu.ac.th/tha/"],
  ["泰王國(泰國)",101,"清邁大學",6,"http://www.cmu.ac.th/"],
  ["新加坡共和國",101,"南洋理工大學",19,"http://www.ntu.edu.sg/Pages/home.aspx"],
  ["新加坡共和國",101,"新加坡國立大學",18,"http://www.nus.edu.sg/"],
  ["新加坡共和國",101,"新加坡管理大學",7,"http://www.smu.edu.sg/"],
  ["馬來西亞",101,"馬來亞大學",13,"https://www.um.edu.my/"],
  ["馬來西亞",101,"馬來西亞新紀元學院",7,"http://www.newera.edu.my/"],
  ["馬來西亞",101,"馬來西亞理工大學(UTM)",2,"http://www.utm.my/"],
  ["芬蘭共和國",101,"阿爾托大學",13,"http://www.aalto.fi/fi/"],
  ["芬蘭共和國",101,"拉瑞爾科技應用大學",4,"https://www.laurea.fi/"],
  ["芬蘭共和國",101,"坦佩利大學",3,"http://www.uta.fi/en/"],
  ["菲律賓共和國",101,"馬尼拉安特雷歐大學",14,"http://www.ateneo.edu/"],
  ["菲律賓共和國",101,"瑪布阿科學技術學院",10,"http://www.mapua.edu.ph/"],
  ["菲律賓共和國",101,"新英格蘭大學",10,"http://www.une.edu.au/"],
  ["大陸地區",102,"復旦大學",99,"http://www.fudan.edu.cn/index.html"],
  ["大陸地區",102,"同濟大學",93,"http://www.tongji.edu.cn/"],
  ["大陸地區",102,"南京大學",84,"http://www.nju.edu.cn/"],
  ["日本",102,"大阪大學",31,"http://www.osaka-u.ac.jp/"],
  ["日本",102,"早稻田大學",27,"http://www.waseda.jp/top/en"],
  ["日本",102,"同志社大學",23,"https://www.doshisha.ac.jp/"],
  ["日本",102,"東北大學",23,"http://www.tohoku.ac.jp/en/"],
  ["美國",102,"西來大學",35,"http://www.uwest.edu/site/"],
  ["美國",102,"天普大學",26,"http://www.temple.edu/"],
  ["美國",102,"波莫納加州州立理工大學",19,"http://www.cpp.edu/"],
  ["大韓民國(南韓)",102,"梨花女子大學",23,"http://www.ewha.ac.kr/mbs/ewhakr/index.jsp"],
  ["大韓民國(南韓)",102,"首爾教育大學",23,"http://www.snue.ac.kr/index_intro.jsp"],
  ["大韓民國(南韓)",102,"成均館大學",22,"http://www.skku.edu/index_pc.jsp"],
  ["德意志聯邦共和國",102,"杜賓根大學",21,"http://www.uni-tuebingen.de/"],
  ["德意志聯邦共和國",102,"慕尼黑工業大學",16,"http://www.tum.de/"],
  ["德意志聯邦共和國",102,"曼漢姆大學",11,"http://www.uni-mannheim.de/1/"],
  ["法國",102,"里昂第三大學",21,"http://www.univ-lyon3.fr/"],
  ["法國",102,"法國雷恩商學院",18,"https://www.esc-rennes.fr/"],
  ["法國",102,"巴黎高等政治學院",10,"http://www.sciencespo.fr/"],
  ["英國",102,"英國劍橋大學",25,"http://www.cam.ac.uk/"],
  ["英國",102,"曼徹斯特大學",12,"http://www.manchester.ac.uk/"],
  ["英國",102,"英國女皇大學",8,"http://www.qub.ac.uk/"],
  ["荷蘭王國",102,"荷蘭萊頓大學",21,"http://www.leidenuniv.nl/"],
  ["荷蘭王國",102,"葛洛寧恩大學",18,"http://www.rug.nl/"],
  ["荷蘭王國",102,"鹿特丹管理學院",7,"http://www.rsm.nl/home/"],
  ["泰國",102,"湄州大學",6,"http://www.mju.ac.th/about/mju-about-2004/INDEX.html"],
  ["泰國",102,"清邁皇家大學",4,"http://www.satitschool.cmru.ac.th/"],
  ["泰國",102,"曼谷大學",3,"http://www.bu.ac.th/tha/"],
  ["西班牙",102,"胡安卡洛斯國王大學",7,"http://www.urjc.es/"],
  ["西班牙",102,"瓦倫西亞科技大學",7,"http://www.upv.es/"],
  ["西班牙",102,"哈恩大學",6,"http://www10.ujaen.es/"],
  ["芬蘭",102,"阿爾托大學",18,"http://www.aalto.fi/fi/"],
  ["芬蘭",102,"拉瑞爾科技應用大學",6,"https://www.laurea.fi/"],
  ["芬蘭",102,"育華斯基里拉大學       ",4,"https://www.jyu.fi/en/"],
  ["香港",102,"香港中文大學",23,"http://www.cuhk.edu.hk/chinese/"],
  ["香港",102,"香港城市大學",17,"http://www.cityu.edu.hk/cityu/index-tc.htm"],
  ["香港",102,"香港大學",16,"https://www.hku.hk/c_index.html"],
  ["捷克共和國",102,"捷克科技大學",18,"http://www.cvut.cz/"],
  ["捷克共和國",102,"奧斯特拉瓦科技大學",11,"https://www.vsb.cz/en"],
  ["捷克共和國",102,"布爾諾科技大學",10,"https://www.vutbr.cz/en/"],
  ["比利時",102,"天主教魯汶大學",11,"http://www.uclouvain.be/index.html"],
  ["比利時",102,"布魯塞爾自由大學",8,"http://www.ulb.ac.be/"],
  ["比利時",102,"安特衛普大學",6,"https://www.uantwerpen.be/nl/"],
  ["加拿大",102,"漢堡學院",15,"http://www.humber.ca/"],
  ["加拿大",102,"紐芬蘭紀念大學",13,"http://www.mun.ca/"],
  ["加拿大",102,"不列顛哥倫比亞大學",12,"http://www.ubc.ca/"],
  ["馬來西亞",102,"馬來亞大學",26,"https://www.um.edu.my/"],
  ["馬來西亞",102,"雙威大學",12,"http://www.sunway.edu.my/"],
  ["馬來西亞",102,"新紀元學院",7,"http://www.newera.edu.my/"],
  ["奧地利",102,"林茲大學",20,"http://www.jku.at/content"],
  ["奧地利",102,"茵斯堡大學",17,"http://www.uibk.ac.at/"],
  ["奧地利",102,"約翰克卜勒大學",5,"http://www.jku.at/content"],
  ["新加坡共和國",102,"南洋理工大學",22,"http://www.ntu.edu.sg/Pages/home.aspx"],
  ["新加坡共和國",102,"新加坡國立大學",19,"http://www.nus.edu.sg/"],
  ["新加坡共和國",102,"新加坡管理大學",9,"http://www.smu.edu.sg/"],
  ["瑞典",102,"林雪平大學",22,"http://www.liu.se/?l=en"],
  ["瑞典",102,"查默斯理工大學",18,"http://www.chalmers.se/en/Pages/default.aspx"],
  ["瑞典",102,"哈勒姆斯塔德大學",7,"http://www.hh.se/"],
  ["澳大利亞",102,"昆士蘭科技大學",13,"https://www.qut.edu.au/"],
  ["澳大利亞",102,"新南威爾斯大學",13,"https://www.unsw.edu.au/"],
  ["澳大利亞",102,"格里菲斯大學",10,"https://www.griffith.edu.au/"],
  ["大陸地區",103,"復旦大學",67,"http://www.fudan.edu.cn/index.html"],
  ["大陸地區",103,"南京大學",56,"http://www.nju.edu.cn/"],
  ["大陸地區",103,"北京大學",47,"http://www.pku.edu.cn/"],
  ["日本",103,"東北大學",22,"http://www.tohoku.ac.jp/en/"],
  ["日本",103,"大阪大學",21,"http://www.osaka-u.ac.jp/ja"],
  ["日本",103,"北海道大學",17,"http://www.hokudai.ac.jp/"],
  ["美國",103,"西來大學",18,"http://www.uwest.edu/site/"],
  ["美國",103,"印第安纳大學-普渡大學維恩堡分校",14,"https://www.ipfw.edu/"],
  ["美國",103,"天普大學",13,"http://www.temple.edu/"],
  ["南韓",103,"梨花女子大學",19,"http://www.ewha.ac.kr/mbs/ewhakr/index.jsp"],
  ["南韓",103,"中央大學",13,"http://www.cau.ac.kr/index.php"],
  ["南韓",103,"東亞大學",12,"http://www.donga.ac.kr/"],
  ["德國",103,"曼漢姆大學",16,"http://www.uni-mannheim.de/1/"],
  ["德國",103,"杜賓根大學",12,"http://www.uni-tuebingen.de/"],
  ["德國",103,"福茲堡應用科技大學",7,"http://www.fhws.de/"],
  ["法國",103,"里昂第三大學",15,"http://www.univ-lyon3.fr/"],
  ["法國",103,"里爾天主教大學",12,"http://www.univ-catholille.fr/"],
  ["法國",103,"特魯瓦高等商學院",9,"http://www.utt.fr/fr/index.html"],
  ["加拿大",103,"曼尼托巴大學",15,"http://umanitoba.ca/"],
  ["加拿大",103,"漢堡學院",10,"http://www.humber.ca/"],
  ["加拿大",103,"西門菲沙大學",6,"http://www.sfu.ca/"],
  ["荷蘭",103,"葛洛寧恩大學",10,"http://www.rug.nl/gradschooleb/index"],
  ["荷蘭",103,"萊登大學",9,"http://www.leidenuniv.nl/"],
  ["荷蘭",103,"漢斯應用科技大學",5,"https://www.hanze.nl/eng/"],
  ["英國",103,"蘭卡斯特大學",5,"http://www.lancaster.ac.uk/"],
  ["英國",103,"倫敦政經學院",4,"http://www.lse.ac.uk/home.aspx"],
  ["英國",103,"桑德蘭大學",4,"http://www.sunderland.ac.uk/"],
  ["西班牙",103,"瓦倫西亞科技大學",6,"http://www.upv.es/"],
  ["西班牙",103,"薩拉曼卡大學",6,"http://www.usal.es/webusal/"],
  ["西班牙",103,"哈恩大學",5,"http://www10.ujaen.es/"],
  ["香港",103,"香港城市大學",14,"http://www.cityu.edu.hk/cityu/index-tc.htm"],
  ["香港",103,"香港中文大學",12,"http://www.cuhk.edu.hk/chinese/"],
  ["香港",103,"香港大學",9,"https://www.hku.hk/c_index.html"],
  ["奧地利共和國",103,"林茲大學",11,"http://www.jku.at/content"],
  ["奧地利共和國",103,"茵斯堡大學",7,"http://www.uibk.ac.at/"],
  ["奧地利共和國",103,"維也納大學",6,"http://www.univie.ac.at/"],
  ["瑞典",103,"林雪平大學",11,"http://www.liu.se/?l=en"],
  ["瑞典",103,"哈勒姆斯塔德",7,"http://www.hh.se/"],
  ["瑞典",103,"查默斯理工大學",6,"http://www.chalmers.se/en/Pages/default.aspx"],
  ["澳大利亞",103,"昆士蘭科技大學",10,"https://www.qut.edu.au/"],
  ["澳大利亞",103,"南天大學",4,"http://www.nantien.edu.au/"],
  ["澳大利亞",103,"昆士蘭大學",3,"http://www.uq.edu.au/"],
  ["新加坡共和國",103,"新加坡國立大學",11,"http://www.nus.edu.sg/"],
  ["新加坡共和國",103,"南洋理工大學",9,"http://www.ntu.edu.sg/Pages/home.aspx"],
  ["新加坡共和國",103,"新加坡管理大學",7,"http://www.smu.edu.sg/"],
  ["波蘭",103,"華沙經濟大學",5,"http://www.sgh.waw.pl/index_en.html"],
  ["波蘭",103,"華沙大學",4,"http://www.uw.edu.pl/"],
  ["波蘭",103,"亞捷隆大學",4,"http://www.uj.edu.pl/"],
  ["芬蘭",103,"阿爾托大學",6,"http://www.aalto.fi/fi/"],
  ["芬蘭",103,"JAMK應用科技大學",3,"www.jamk.fi/fi/Etusivu"],
  ["芬蘭",103,"于韋斯屈萊大學",3,"https://www.jyu.fi/"],
  ["瑞士",103,"蘇黎世應用科學大學",8,"http://www.sml.zhaw.ch/en"],
  ["瑞士",103,"聖加崙大學",4,"http://www.unisg.ch/"],
  ["瑞士",103,"蘇黎世大學",3,"http://www.uzh.ch/index.html"],
  ["瑞士",103,"洛桑大學",3,"http://www.unil.ch/index.html"],
  ["馬來西亞",103,"馬來亞大學",21,"https://www.um.edu.my/"],
  ["馬來西亞",103,"拉曼大學",1,"http://www.tarc.edu.my/"]
];

$(document).ready(function() {
    $('#example').DataTable( {
        data: dataSet,
        "columnDefs": [
            { "visible": false }
        ],
        "scrollY":        "600px",
        "scrollCollapse": true,
        "paging":         false,
        "order": [[ 2, 'asc' ]],
        columns: [
            { title: "國家" },
            { title: "年度" },
            { title: "學校" },
            { title: "人數" },
            { title: "網址" }
        ]
    } );
} );

index.html

<!DOCTYPE html>
<meta charset='utf-8'>
<html>
<style>

body{
  font-family: "Helvetica Neue";
}

.baseMap{
  stroke-width:0.8px;
  stroke:#555;
  fill:#555;
  opacity:0.5;
}

.globe {
  fill: #000;
}


.cities_end{
  /*fill:rgba(29, 168, 183, .5);*/
  fill:rgba(230, 255, 0, 0.5);
/*  254*/
/*  fill:none;*/
  stroke-width: 1;
  stroke: white;
 /* fill:none;*/
  }

.line{
  stroke:rgba(230, 255, 0, 0.8);
/*  stroke:rgba(253,141,3,.3);*/
  stroke-width:1.5px;
  fill:none;

}

.geo-globe {
  fill: rgba(236,249,255,0.8);
/*  fill:white;*/
    }

.years{
  font-size:18px;
  font-weight: 600;
  font-family: "Helvetica Neue";
  fill:black;
  opacity: 0.8;
}

.country{
  font-size:15px;
  font-family: "Helvetica Neue";
  fill:black;
  opacity: 0.7;
}



.maps{

  width: 100%;
  max-width: 400px;
  position: relative;
  display: inline-block;
  text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
  margin-left: 50px;
}

@media (max-width: 600px) {
  .maps {
    margin-left: 0px;
  }
}

table{
   font-family: "新細明體";
}

/*div {
  outline: 1px solid black;
}

svg {
  outline: 1px solid orange;
  position: absolute;
  top: 0;
  left: 0;
}

g {
  outline: 1px solid red;
}*/

.title{
  text-align: center;
}

h1{
  font-size: 50px;
  margin-top: 10px;
/*  color:rgb(33, 113, 181);*/
  color:#333333;
}

h3{ 
  font-weight: 500;
  margin-top: -20px;
  color:#333333;
  opacity:0.8;
  font-size: 15px;


}

.table{
  max-width: 1200px;
  margin:auto;
  font-size: .9em;
  color:#333333;
}

a{
 background-color: rgba(230, 255, 0, 0.5);
 text-decoration: none;
 color:black;
}

a:hover{
  background-color: rgba(255,179,213,0.4); 
    -webkit-transition: background-color 300ms linear;
    -moz-transition: background-color 300ms linear;
    -o-transition: background-color 300ms linear;
    -ms-transition: background-color 300ms linear;
    transition: background-color 300ms linear;
}



</style>
<body>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js'></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src='https://api.mapbox.com/mapbox.js/plugins/arc.js/v0.1.0/arc.js'></script>
<!-- Latest compiled and minified Bootstrap JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/1.10.9/js/jquery.dataTables.min.js"></script>
<script src="script.js"></script>
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.9/css/jquery.dataTables.min.css" />
<h1 class = "title">台灣交換學生資料庫</h1>
<h3 class = "title">民國101至103年台灣交換學生資料,使用者可以移動滑鼠與拖曳地球儀查看詳細資料,<br>也可以利用下方資料庫內進行進階搜尋。資料來源來自教育部。製作人<a href="https://twitter.com/Jeremy_CF_Lin" target="_blank">Jeremy C.F. Lin</a><br>與台灣<a href="//comm.nccu.edu.tw/index.php" target="_blank">政治大學傳播學院</a>一同合作。</h3>
<div id="main-wrapper" class="">
        <div id="main-content" class="container">
            <div class="row">
            <div id ='map' class="maps col-lg-2"></div>
            <div id ='map2' class="maps col-lg-2"></div>
            <div id ='map3' class="maps col-lg-2"></div>
            </div>
            <div class ="row">
            <div class="table">
              <table id="example" class="display " width="100%"></table>
            </div>
            </div>
        </div>
</div>



<script>



  $(".maps").css("height", $("#map").outerWidth() + "px");

  var margin = {
        top: 15,
        right: 20,
        bottom: 15,
        left: 0
    },
    width = $(".maps").outerWidth() - margin.left - margin.right,
    height = $(".maps").outerHeight() - margin.top - margin.bottom;

  //This is the project for the globe 
  var projection = d3.geo.orthographic()
      .scale(height / 2)
      .translate([width / 2, height / 2])
      .clipAngle(90)
      .precision(0.5);

  var path = d3.geo.path()
    .projection(projection)
    .pointRadius(function(d) {
        //This is where we set circle radius to show count of attendees
        if (d.count) {
            return Math.sqrt(d.count / Math.PI) * 1.3;
        }
    });

  var svg =  d3.select("#map").append('svg')
  // d3.select('#map').append('svg')
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .attr('class', 'graph-svg-component')
    .call(responsivefy) // Call function responsivefy to make the graphic reponsive according to the window width/height
    .append('g')
    .attr("class", "globe-g")
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

  var svg2 =  d3.select("#map2").append('svg')
  // d3.select('#map').append('svg')
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .attr('class', 'graph-svg-component')
    .call(responsivefy) // Call function responsivefy to make the graphic reponsive according to the window width/height
    .append('g')
    .attr("class", "globe-g")
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

  var svg3 =  d3.select("#map3").append('svg')
  // d3.select('#map').append('svg')
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .attr('class', 'graph-svg-component')
    .call(responsivefy) // Call function responsivefy to make the graphic reponsive according to the window width/height
    .append('g')
    .attr("class", "globe-g")
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');



  var globe = svg.selectAll('path.globe').data([{
        type: 'Sphere'
    }])
    .enter().append('path')
    .attr('class', 'globe')
    .attr('d', path);

  var globe2 = svg2.selectAll('path.globe').data([{
        type: 'Sphere'
    }])
    .enter().append('path')
    .attr('class', 'globe')
    .attr('d', path);

  var globe3 = svg3.selectAll('path.globe').data([{
        type: 'Sphere'
    }])
    .enter().append('path')
    .attr('class', 'globe')
    .attr('d', path);

  queue()
      .defer(d3.json, 'world_countries.json')// load geojson/topojson data
      .defer(d3.csv, 'exchange_student.csv')
      .await(ready);


  function ready(error, world, data) {
    if (error) throw error;

    data.forEach(
        function(d) {

             d.end_lat = +d.end_lat;
             d.end_long = +d.end_long;
             d.start_lat = +d.start_lat;
             d.start_long = +d.start_long;

             d.greatcircle = new arc.GreatCircle({
                    x: d.start_long,
                    y: d.start_lat
                }, {
                    x: d.end_long,
                    y: d.end_lat
                });
                d.line = d.greatcircle.Arc(100, {
                    offset: 10
                });
                d.arc = d.line.json();
              }
     );

    data = data.filter(function(d) {
        if (isNaN(d.end_lat) || isNaN(d.end_long)) {
            //Do nothing.
        } else {
            return d;
        }
    });

    svg.selectAll('baseMap')
        .data(world.features)
        .enter()
        .append('path')
        .attr('d', path)
    // .append("g")
    .attr('class', 'baseMap');

    svg2.selectAll('baseMap')
        .data(world.features)
        .enter()
        .append('path')
        .attr('d', path)
    // .append("g")
    .attr('class', 'baseMap');

    svg3.selectAll('baseMap')
        .data(world.features)
        .enter()
        .append('path')
        .attr('d', path)
    // .append("g")
    .attr('class', 'baseMap');

    svg.append("text")
    .attr("class","country")
    .attr("x", width * 0.70)
    .attr("y", height * 0.87)
    .text("");

    svg2.append("text")
        .attr("class","country svg2")
        .attr("x", width * 0.70)
        .attr("y", height * 0.87)
        .text("");

    svg3.append("text")
        .attr("class","country svg3")
        .attr("x", width * 0.70)
        .attr("y", height * 0.87)
        .text("");

    svg.append("text")
        .attr("class","country count1")
        .attr("x", width * 0.70)
        .attr("y", height * 0.93)
        .text("");

    svg2.append("text")
        .attr("class","country count2")
        .attr("x", width * 0.70)
        .attr("y", height * 0.93)
        .text("");

    svg3.append("text")
        .attr("class","country count3")
        .attr("x", width * 0.70)
        .attr("y", height * 0.93)
        .text("");



    svg.selectAll('.cities_end')
        .data(data.filter(function(d) { return d.year === "101"  }))
        .enter().append("path")
        .datum(function(d) {
            return {
                type: "Point",
                coordinates: [d.end_long, d.end_lat],
                count: +d.count,
                country: d.end_country
            };
        })
        .attr("d", path)
        .attr('class', 'cities_end')
        .on('mouseover',function(d){
          d3.select(".country")
            .text(d.country)

          d3.select(".count1")
            .text(d.count + " 名學生")
        });


    svg2.selectAll('.cities_end')
        .data(data.filter(function(d) { return d.year === "102"  }))
        .enter().append("path")
        .datum(function(d) {
            return {
                type: "Point",
                coordinates: [d.end_long, d.end_lat],
                count: +d.count,
                country: d.end_country
            };
        })
        .attr("d", path)
        .attr('class', 'cities_end')
        .on('mouseover',function(d){
          d3.select(".svg2")
            .text(d.country)

          d3.select(".count2")
            .text(d.count+ " 名學生")
        });

    svg3.selectAll('.cities_end')
        .data(data.filter(function(d) { return d.year === "103"  }))
        .enter().append("path")
        .datum(function(d) {
            return {
                type: "Point",
                coordinates: [d.end_long, d.end_lat],
                count: +d.count,
                country: d.end_country
            };
        })
        .attr("d", path)
        .attr('class', 'cities_end')
        .on('mouseover',function(d){
          d3.select(".svg3")
            .text(d.country)

           d3.select(".count3")
            .text(d.count+ " 名學生")
        });

        // console.log(data)

    svg.append("g")
        .attr("class", "line")
        .selectAll(".arc")
        .data(data.filter(function(d) { return d.year === "101"  })
          .map(function(d) {
            return d.arc;
        }))
        .enter()
        .append("path")
        .attr("class", "arc")
        .attr("d", path);

    svg.append("text")
      .attr("class","years")
      .attr("x", width * 0.70)
      .attr("y", height * 0.80)
      .text('101年');

    svg2.append("text")
      .attr("class","years")
      .attr("x", width * 0.70)
      .attr("y", height * 0.80)
      .text('102年');

    svg3.append("text")
      .attr("class","years")
      .attr("x", width * 0.70)
      .attr("y", height * 0.80)
      .text('103年 (上半年)');

    svg2.append("g")
        .attr("class", "line")
        .selectAll(".arc")
        .data(data.filter(function(d) { return d.year === "102"  }).map(function(d) {
            return d.arc;
        }))
        .enter()
        .append("path")
        .attr("class", "arc")
        .attr("d", path);

        // console.log(data);

    svg3.append("g")
        .attr("class", "line")
        .selectAll(".arc")
        .data(data.filter(function(d) { return d.year === "103"  }).map(function(d) {
            return d.arc;
        }))
        .enter()
        .append("path")
        .attr("class", "arc")
        .attr("d", path);
  }

  d3.selectAll(".maps").call( //drag on the svg element
    d3.behavior.drag()
    .origin(function() {
        var r = projection.rotate();
        return {
            x: r[0],
            y: -r[1]
        }; //starting point
    })
    .on("drag", function() {
        var r = projection.rotate();
        /* update retation angle */
        projection.rotate([d3.event.x, -d3.event.y, r[2]]);

        /* redraw the map and circles after rotation */
        svg.selectAll(".baseMap").attr("d", path);
        svg.selectAll(".arc").attr("d", path);
        svg.selectAll('.cities_end')
            .attr("d", path);

        svg2.selectAll(".baseMap").attr("d", path);
        svg2.selectAll(".arc").attr("d", path);
        svg2.selectAll('.cities_end')
            .attr("d", path);

        svg3.selectAll(".baseMap").attr("d", path);
        svg3.selectAll(".arc").attr("d", path);
        svg3.selectAll('.cities_end')
            .attr("d", path);

    })
);

  function responsivefy(svg) {
    var container = d3.select(svg.node().parentNode),
        width = parseInt(svg.style('width')),
        height = parseInt(svg.style('height')),
        aspect = width / height;

    svg.attr('viewBox', '0 0 ' + width + ' ' + height)
        .attr('perserveAspectRatio', 'xMinYMid')
        .call(resize);

    d3.select(window).on('resize', resize);

    function resize() {
        var targetWidth = parseInt(container.style('width'));
        svg.attr('width', targetWidth);
        svg.attr('height', Math.round(targetWidth / aspect));
    }
  }

</script>

</body>
</html>

arc.js

'use strict';

var D2R = Math.PI / 180;
var R2D = 180 / Math.PI;

var Coord = function(lon,lat) {
    this.lon = lon;
    this.lat = lat;
    this.x = D2R * lon;
    this.y = D2R * lat;
};

Coord.prototype.view = function() {
    return String(this.lon).slice(0, 4) + ',' + String(this.lat).slice(0, 4);
};

Coord.prototype.antipode = function() {
    var anti_lat = -1 * this.lat;
    var anti_lon = (this.lon < 0) ? 180 + this.lon : (180 - this.lon) * -1;
    return new Coord(anti_lon, anti_lat);
};

var LineString = function() {
    this.coords = [];
    this.length = 0;
};

LineString.prototype.move_to = function(coord) {
    this.length++;
    this.coords.push(coord);
};

var Arc = function(properties) {
    this.properties = properties || {};
    this.geometries = [];
};

Arc.prototype.json = function() {
    if (this.geometries.length <= 0) {
        return {'geometry': { 'type': 'LineString', 'coordinates': null },
                'type': 'Feature', 'properties': this.properties
               };
    } else if (this.geometries.length == 1) {
        return {'geometry': { 'type': 'LineString', 'coordinates': this.geometries[0].coords },
                'type': 'Feature', 'properties': this.properties
               };
    } else {
        var multiline = [];
        for (var i = 0; i < this.geometries.length; i++) {
            multiline.push(this.geometries[i].coords);
        }
        return {'geometry': { 'type': 'MultiLineString', 'coordinates': multiline },
                'type': 'Feature', 'properties': this.properties
               };
    }
};

// TODO - output proper multilinestring
Arc.prototype.wkt = function() {
    var wkt_string = '';
    var wkt = 'LINESTRING(';
    var collect = function(c) { wkt += c[0] + ' ' + c[1] + ','; };
    for (var i = 0; i < this.geometries.length; i++) {
        if (this.geometries[i].coords.length === 0) {
            return 'LINESTRING(empty)';
        } else {
            var coords = this.geometries[i].coords;
            coords.forEach(collect);
            wkt_string += wkt.substring(0, wkt.length - 1) + ')';
        }
    }
    return wkt_string;
};

/*
 * http://en.wikipedia.org/wiki/Great-circle_distance
 *
 */
var GreatCircle = function(start,end,properties) {
    if (!start || start.x === undefined || start.y === undefined) {
        throw new Error("GreatCircle constructor expects two args: start and end objects with x and y properties");
    }
    if (!end || end.x === undefined || end.y === undefined) {
        throw new Error("GreatCircle constructor expects two args: start and end objects with x and y properties");
    }
    this.start = new Coord(start.x,start.y);
    this.end = new Coord(end.x,end.y);
    this.properties = properties || {};

    var w = this.start.x - this.end.x;
    var h = this.start.y - this.end.y;
    var z = Math.pow(Math.sin(h / 2.0), 2) +
                Math.cos(this.start.y) *
                   Math.cos(this.end.y) *
                     Math.pow(Math.sin(w / 2.0), 2);
    this.g = 2.0 * Math.asin(Math.sqrt(z));

    if (this.g == Math.PI) {
        throw new Error('it appears ' + start.view() + ' and ' + end.view() + " are 'antipodal', e.g diametrically opposite, thus there is no single route but rather infinite");
    } else if (isNaN(this.g)) {
        throw new Error('could not calculate great circle between ' + start + ' and ' + end);
    }
};

/*
 * http://williams.best.vwh.net/avform.htm#Intermediate
 */
GreatCircle.prototype.interpolate = function(f) {
    var A = Math.sin((1 - f) * this.g) / Math.sin(this.g);
    var B = Math.sin(f * this.g) / Math.sin(this.g);
    var x = A * Math.cos(this.start.y) * Math.cos(this.start.x) + B * Math.cos(this.end.y) * Math.cos(this.end.x);
    var y = A * Math.cos(this.start.y) * Math.sin(this.start.x) + B * Math.cos(this.end.y) * Math.sin(this.end.x);
    var z = A * Math.sin(this.start.y) + B * Math.sin(this.end.y);
    var lat = R2D * Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
    var lon = R2D * Math.atan2(y, x);
    return [lon, lat];
};



/*
 * Generate points along the great circle
 */
GreatCircle.prototype.Arc = function(npoints,options) {
    var first_pass = [];
    if (!npoints || npoints <= 2) {
        first_pass.push([this.start.lon, this.start.lat]);
        first_pass.push([this.end.lon, this.end.lat]);
    } else {
        var delta = 1.0 / (npoints - 1);
        for (var i = 0; i < npoints; ++i) {
            var step = delta * i;
            var pair = this.interpolate(step);
            first_pass.push(pair);
        }
    }
    /* partial port of dateline handling from:
      gdal/ogr/ogrgeometryfactory.cpp

      TODO - does not handle all wrapping scenarios yet
    */
    var bHasBigDiff = false;
    var dfMaxSmallDiffLong = 0;
    // from http://www.gdal.org/ogr2ogr.html
    // -datelineoffset:
    // (starting with GDAL 1.10) offset from dateline in degrees (default long. = +/- 10deg, geometries within 170deg to -170deg will be splited)
    var dfDateLineOffset = options && options.offset ? options.offset : 10;
    var dfLeftBorderX = 180 - dfDateLineOffset;
    var dfRightBorderX = -180 + dfDateLineOffset;
    var dfDiffSpace = 360 - dfDateLineOffset;

    // https://github.com/OSGeo/gdal/blob/7bfb9c452a59aac958bff0c8386b891edf8154ca/gdal/ogr/ogrgeometryfactory.cpp#L2342
    for (var j = 1; j < first_pass.length; ++j) {
        var dfPrevX = first_pass[j-1][0];
        var dfX = first_pass[j][0];
        var dfDiffLong = Math.abs(dfX - dfPrevX);
        if (dfDiffLong > dfDiffSpace &&
            ((dfX > dfLeftBorderX && dfPrevX < dfRightBorderX) || (dfPrevX > dfLeftBorderX && dfX < dfRightBorderX))) {
            bHasBigDiff = true;
        } else if (dfDiffLong > dfMaxSmallDiffLong) {
            dfMaxSmallDiffLong = dfDiffLong;
        }
    }

    var poMulti = [];
    if (bHasBigDiff && dfMaxSmallDiffLong < dfDateLineOffset) {
        var poNewLS = [];
        poMulti.push(poNewLS);
        for (var k = 0; k < first_pass.length; ++k) {
            var dfX0 = parseFloat(first_pass[k][0]);
            if (k > 0 &&  Math.abs(dfX0 - first_pass[k-1][0]) > dfDiffSpace) {
                var dfX1 = parseFloat(first_pass[k-1][0]);
                var dfY1 = parseFloat(first_pass[k-1][1]);
                var dfX2 = parseFloat(first_pass[k][0]);
                var dfY2 = parseFloat(first_pass[k][1]);
                if (dfX1 > -180 && dfX1 < dfRightBorderX && dfX2 == 180 &&
                    k+1 < first_pass.length &&
                   first_pass[k-1][0] > -180 && first_pass[k-1][0] < dfRightBorderX)
                {
                     poNewLS.push([-180, first_pass[k][1]]);
                     k++;
                     poNewLS.push([first_pass[k][0], first_pass[k][1]]);
                     continue;
                } else if (dfX1 > dfLeftBorderX && dfX1 < 180 && dfX2 == -180 &&
                     k+1 < first_pass.length &&
                     first_pass[k-1][0] > dfLeftBorderX && first_pass[k-1][0] < 180)
                {
                     poNewLS.push([180, first_pass[k][1]]);
                     k++;
                     poNewLS.push([first_pass[k][0], first_pass[k][1]]);
                     continue;
                }

                if (dfX1 < dfRightBorderX && dfX2 > dfLeftBorderX)
                {
                    // swap dfX1, dfX2
                    var tmpX = dfX1;
                    dfX1 = dfX2;
                    dfX2 = tmpX;
                    // swap dfY1, dfY2
                    var tmpY = dfY1;
                    dfY1 = dfY2;
                    dfY2 = tmpY;
                }
                if (dfX1 > dfLeftBorderX && dfX2 < dfRightBorderX) {
                    dfX2 += 360;
                }

                if (dfX1 <= 180 && dfX2 >= 180 && dfX1 < dfX2)
                {
                    var dfRatio = (180 - dfX1) / (dfX2 - dfX1);
                    var dfY = dfRatio * dfY2 + (1 - dfRatio) * dfY1;
                    poNewLS.push([first_pass[k-1][0] > dfLeftBorderX ? 180 : -180, dfY]);
                    poNewLS = [];
                    poNewLS.push([first_pass[k-1][0] > dfLeftBorderX ? -180 : 180, dfY]);
                    poMulti.push(poNewLS);
                }
                else
                {
                    poNewLS = [];
                    poMulti.push(poNewLS);
                }
                poNewLS.push([dfX0, first_pass[k][1]]);
            } else {
                poNewLS.push([first_pass[k][0], first_pass[k][1]]);
            }
        }
    } else {
        // add normally
        var poNewLS0 = [];
        poMulti.push(poNewLS0);
        for (var l = 0; l < first_pass.length; ++l) {
            poNewLS0.push([first_pass[l][0],first_pass[l][1]]);
        }
    }

    var arc = new Arc(this.properties);
    for (var m = 0; m < poMulti.length; ++m) {
        var line = new LineString();
        arc.geometries.push(line);
        var points = poMulti[m];
        for (var j0 = 0; j0 < points.length; ++j0) {
            line.move_to(points[j0]);
        }
    }
    return arc;
};

if (typeof window === 'undefined') {
  // nodejs
  module.exports.Coord = Coord;
  module.exports.Arc = Arc;
  module.exports.GreatCircle = GreatCircle;

} else {
  // browser
  var arc = {};
  arc.Coord = Coord;
  arc.Arc = Arc;
  arc.GreatCircle = GreatCircle;
}

exchange_student.csv

end_lat,end_long,start_lat,start_long,end_country,start_country,count,year
35.8592948,104.1361117,23.5,121,大陸地區,台灣,187,101
34.7857324,134.3756902,23.5,121,日本,台灣,97,101
37.6,-95.665,23.5,121,美國,台灣,164,101
35.8615124,127.096405,23.5,121,大韓民國(南韓),台灣,71,101
51.1719674,10.4541194,23.5,121,德意志聯邦共和國,台灣,99,101
46.2157467,2.2088258,23.5,121,法國,台灣,68,101
55.3632592,-3.4433238,23.5,121,英國,台灣,62,101
52.2129919,5.2793703,23.5,121,荷蘭王國,台灣,54,101
49.8037633,15.4749126,23.5,121,捷克共和國,台灣,37,101
56,-96,23.5,121,加拿大,台灣,36,101
62.1983366,17.5652566,23.5,121,瑞典王國,台灣,42,101
-27.9210555,133.247866,23.5,121,澳大利亞,台灣,33,101
22.3576782,114.1210181,23.5,121,香港,台灣,53,101
40.2085,-3.713,23.5,121,西班牙王國,台灣,24,101
47.696472,13.3457348,23.5,121,奧地利共和國,台灣,43,101
13.03887,101.490104,23.5,121,泰王國(泰國),台灣,19,101
1.3147308,103.8470128,23.5,121,新加坡共和國,台灣,44,101
4.140634,109.6181485,23.5,121,馬來西亞,台灣,22,101
64.9146659,26.0672553,23.5,121,芬蘭共和國,台灣,20,101
11.6978351,122.6217542,23.5,121,菲律賓共和國,台灣,34,101
35.8592948,104.1361117,23.5,121,大陸地區,台灣,276,102
34.7857324,134.3756902,23.5,121,日本,台灣,81,102
37.6,-95.665,23.5,121,美國,台灣,80,102
35.8615124,127.096405,23.5,121,大韓民國(南韓),台灣,68,102
51.1719674,10.4541194,23.5,121,德意志聯邦共和國,台灣,48,102
46.2157467,2.2088258,23.5,121,法國,台灣,49,102
55.3632592,-3.4433238,23.5,121,英國,台灣,45,102
52.2129919,5.2793703,23.5,121,荷蘭王國,台灣,46,102
13.03887,101.490104,23.5,121,泰國,台灣,13,102
40.2085,-3.713,23.5,121,西班牙,台灣,20,102
64.9146659,26.0672553,23.5,121,芬蘭,台灣,28,102
22.3576782,114.1210181,23.5,121,香港,台灣,56,102
49.8037633,15.4749126,23.5,121,捷克共和國,台灣,39,102
50.5010789,4.4764594,23.5,121,比利時,台灣,25,102
56,-96,23.5,121,加拿大,台灣,40,102
4.140634,109.6181485,23.5,121,馬來西亞,台灣,45,102
47.696472,13.3457348,23.5,121,奧地利,台灣,42,102
1.3147308,103.8470128,23.5,121,新加坡共和國,台灣,50,102
62.1983366,17.5652566,23.5,121,瑞典,台灣,47,102
-27.9210555,133.247866,23.5,121,澳大利亞,台灣,36,102
35.8592948,104.1361117,23.5,121,大陸,台灣,170,103
34.7857324,134.3756902,23.5,121,日本,台灣,60,103
37.6,-95.665,23.5,121,美國,台灣,45,103
35.8615124,127.096405,23.5,121,南韓,台灣,44,103
51.1719674,10.4541194,23.5,121,德國,台灣,35,103
46.2157467,2.2088258,23.5,121,法國,台灣,36,103
56,-96,23.5,121,加拿大,台灣,31,103
52.2682651,5.5201215,23.5,121,荷蘭,台灣,24,103
55.3632592,-3.4433238,23.5,121,英國,台灣,13,103
40.2085,-3.713,23.5,121,西班牙,台灣,17,103
22.3576782,114.1210181,23.5,121,香港,台灣,35,103
47.696472,13.3457348,23.5,121,奧地利共和國,台灣,24,103
62.1983366,17.5652566,23.5,121,瑞典,台灣,24,103
-27.9210555,133.247866,23.5,121,澳大利亞,台灣,17,103
1.3147308,103.8470128,23.5,121,新加坡共和國,台灣,27,103
51.9189046,19.1343786,23.5,121,波蘭,台灣,13,103
64.9146659,26.0672553,23.5,121,芬蘭,台灣,12,103
46.8131873,8.2242101,23.5,121,瑞士,台灣,15,103
4.140634,109.6181485,23.5,121,馬來西亞,台灣,22,103