366 lines
18 KiB
HTML
366 lines
18 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
|
|
|
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js'></script>
|
|
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js'></script>
|
|
<script src='https://cdnjs.cloudflare.com/ajax/libs/angularjs-slider/5.4.0/rzslider.min.js'></script>
|
|
<script src='js/angular-simple-logger.min.js'></script>
|
|
<script src='js/angular-google-maps.min.js'></script>
|
|
<script src="js/angular-csv-service.min.js"></script>
|
|
<script src="js/angular-toggle-switch.min.js"></script>
|
|
<script src="js/q-spread.min.js"></script>
|
|
<script src='js/ui-bootstrap-2.0.0.min.js'></script>
|
|
<script src='js/app.js'></script>
|
|
<script src='js/services.js'></script>
|
|
<script src='js/controller.js'></script>
|
|
|
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/angularjs-slider/5.4.0/rzslider.min.css" rel="stylesheet">
|
|
<link href="css/angular-toggle-switch.css" rel="stylesheet">
|
|
<link href="https://fonts.googleapis.com/css?family=Cutive" rel="stylesheet">
|
|
<link href="css/quartermaester.css" rel="stylesheet">
|
|
|
|
<title>Interactive Game of Thrones Map</title>
|
|
<meta name="description" content="A map of Westeros and the rest of the known world in Game of Thrones and the Song of Ice & Fire novels. Mark how much of the TV show or novels you've seen to prevent seeing any spoilers. See the path of major characters over time." />
|
|
</head>
|
|
<body ng-app="quartermaester" ng-controller="mapCtrl">
|
|
|
|
<ui-gmap-google-map center='map.center' zoom='map.zoom' options='map.options' events='map.events' control='map.control'>
|
|
|
|
<!-- Base map tiles from Ser Mountain Goat -->
|
|
<ui-gmap-map-type options='map.smgMapType'></ui-gmap-map-type>
|
|
|
|
<!-- Location Markers -->
|
|
<ui-gmap-markers
|
|
models='mapModels.towns'
|
|
coords="'coords'"
|
|
click='map.locationClick'
|
|
options="'options'"
|
|
idkey="'key'">
|
|
</ui-gmap-markers>
|
|
|
|
<!-- Heraldry Markers -->
|
|
<ui-gmap-markers
|
|
models='mapModels.heraldry'
|
|
coords="'coords'"
|
|
options="'options'"
|
|
click="map.heraldryClick"
|
|
idkey="'key'">
|
|
</ui-gmap-markers>
|
|
|
|
<!-- Region Polygons -->
|
|
<ui-gmap-polygons
|
|
models="mapModels.regions"
|
|
path="'path'"
|
|
fill="'fill'"
|
|
stroke="'stroke'"
|
|
visible="options.geographicRegions"
|
|
idKey="'key'">
|
|
</ui-gmap-polygons>
|
|
|
|
<!-- Character Markers -->
|
|
<ui-gmap-markers
|
|
models='mapModels.characters'
|
|
coords="'coords'"
|
|
options="'options'"
|
|
click="map.characterClick"
|
|
type="'spider'"
|
|
idkey="'key'">
|
|
</ui-gmap-markers>
|
|
|
|
<!-- Character Paths -->
|
|
<!-- The values of the attributes seem to be ignored. All that matters is if they are defined or not -->
|
|
<ui-gmap-polylines
|
|
ng-if="state!='edit'"
|
|
models='mapModels.paths'
|
|
path="''"
|
|
stroke="''"
|
|
static="''"
|
|
editable="''"
|
|
icons="''"
|
|
idkey="'key'">
|
|
</ui-gmap-polylines>
|
|
<ui-gmap-polylines
|
|
ng-if="state=='edit'"
|
|
models='mapModels.editablePaths'
|
|
path="''"
|
|
stroke="''"
|
|
static="''"
|
|
editable="''"
|
|
icons="''"
|
|
idkey="'key'">
|
|
</ui-gmap-polylines>
|
|
|
|
</ui-gmap-google-map>
|
|
|
|
<div id="navigation">
|
|
<div class="list-group">
|
|
<button class="list-group-item btn-clear" ng-click="toState('slider-full')" ng-class="{highlight:(state=='slider-full'), hlborder:(state=='search')}">
|
|
<i class="glyphicon glyphicon-eye-close"></i>
|
|
</button>
|
|
<button class="list-group-item btn-clear" ng-click="toState('characters')" ng-class="{highlight:(state=='characters'),hlborder:(state=='search')}">
|
|
<i class="glyphicon glyphicon-user"></i>
|
|
</button>
|
|
<button class="list-group-item btn-clear" ng-click="toState('search')" ng-class="{highlight:(state=='search')}">
|
|
<i class="glyphicon glyphicon-search"></i>
|
|
</button>
|
|
<button class="list-group-item btn-clear" ng-click="toState('options')" ng-class="{highlight:(state=='options')}">
|
|
<i class="glyphicon glyphicon-cog"></i>
|
|
</button>
|
|
<button class="list-group-item btn-clear" ng-click="toState('about')" ng-class="{highlight:(state=='about')}">
|
|
<i class="glyphicon glyphicon-question-sign"></i>
|
|
</button>
|
|
<!-- <button class="list-group-item btn-clear" ng-click="toState('edit')" ng-class="{highlight:(state=='edit')}">
|
|
<i class="glyphicon glyphicon-pencil"></i>
|
|
</button> -->
|
|
</div>
|
|
</div>
|
|
|
|
<div id="side" ng-class="{wider:(state=='about'||state=='edit')}">
|
|
<!-- <p>{{state}}</p> -->
|
|
<div id="slider" ng-show="state.substring(0,6)=='slider'">
|
|
<h1 ng-show="state=='slider-full'">
|
|
Spoiler Control
|
|
<i class="glyphicon glyphicon-remove pull-right" ng-click="toState('slider')"></i>
|
|
</h1>
|
|
<div id="slider-readout" title="Click to adjust plot spoilers">
|
|
<!-- <span class="glyphicon glyphicon-menu-hamburger" ng-click="toState('menu')"></span> -->
|
|
<span ng-show="slider.show=='episodes'" ng-bind="episodes[slider.currentEpisode].name" title="{{episodes[slider.currentEpisode].name}}" ng-click="toState('slider-full')"></span>
|
|
<span ng-show="slider.show=='chapters'" ng-bind="chapters[slider.currentChapter].name" title="{{chapters[slider.currentChapter].name}}" ng-click="toState('slider-full')"></span>
|
|
</div>
|
|
<div id="slider-control" ng-show="state=='slider-full'">
|
|
<div class="btn-group btn-group-2" role="group">
|
|
<button type="button" class="btn" ng-click="slider.show='episodes';" ng-class="{'btn-primary':(slider.show=='episodes'), 'btn-default':(slider.show!='episodes')}">
|
|
<i class="glyphicon glyphicon-facetime-video"></i>
|
|
HBO Show
|
|
</button>
|
|
<button type="button" class="btn" ng-click="slider.show='chapters';" ng-class="{'btn-primary':(slider.show=='chapters'), 'btn-default':(slider.show!='chapters')}">
|
|
<i class="glyphicon glyphicon-book"></i>
|
|
Books
|
|
</button>
|
|
</div>
|
|
<rzslider
|
|
id="slide-episodes"
|
|
ng-show="slider.show=='episodes'"
|
|
rz-slider-model="slider.currentEpisode"
|
|
rz-slider-options="{floor:0, ceil:episodes.length-1}">
|
|
</rzslider>
|
|
<rzslider
|
|
id="slide-chapters"
|
|
ng-show="slider.show=='chapters'"
|
|
rz-slider-model="slider.currentChapter"
|
|
rz-slider-options="{floor:0, ceil:chapters.length-1}">
|
|
</rzslider>
|
|
<div class="btn-group btn-group-5" role="group">
|
|
<button type="button" class="btn btn-default" ng-click="slideTo(-10)">
|
|
<i class="glyphicon glyphicon-step-backward"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-default" ng-click="slideTo(-1)">
|
|
<i class="glyphicon glyphicon-chevron-left"></i>
|
|
</button>
|
|
<a role="button" class="btn btn-default" ng-show="slider.show=='episodes'" ng-href="{{episodes[slider.currentEpisode].url}}">
|
|
<i class="glyphicon glyphicon-link"></i>
|
|
</a>
|
|
<a role="button" class="btn btn-default" ng-show="slider.show=='chapters'" ng-href="{{chapters[slider.currentChapter].url}}">
|
|
<i class="glyphicon glyphicon-link"></i>
|
|
</a>
|
|
<button type="button" class="btn btn-default" ng-click="slideTo(1)">
|
|
<i class="glyphicon glyphicon-chevron-right"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-default" ng-click="slideTo(10)">
|
|
<i class="glyphicon glyphicon-step-forward"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="location" ng-show="state=='location'">
|
|
<h1>
|
|
Location Details
|
|
<i class="glyphicon glyphicon-remove pull-right" ng-click="toState('slider')"></i>
|
|
</h1>
|
|
<div class="list-group">
|
|
<a ng-href="{{locationDetail.url}}" role="button" class="list-group-item btn-clear">
|
|
<i class="glyphicon glyphicon glyphicon-map-marker"></i>
|
|
{{locationDetail.name}}
|
|
<i class="glyphicon glyphicon-menu-right pull-right"></i>
|
|
</a>
|
|
<a ng-href="{{locationDetail.houseUrl}}" role="button" class="list-group-item btn-clear" ng-if="locationDetail.houseUrl">
|
|
<img ng-src="{{locationDetail.houseImg}}">
|
|
{{locationDetail.house}}
|
|
<i class="glyphicon glyphicon-menu-right pull-right"></i>
|
|
</a>
|
|
<a ng-href="{{locationDetail.direct}}" role="button" class="list-group-item btn-clear">
|
|
<i class="glyphicon glyphicon-pushpin"></i>
|
|
Direct Link
|
|
<i class="glyphicon glyphicon-menu-right pull-right"></i>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="characters" ng-show="state=='characters'">
|
|
<h1>
|
|
Characters
|
|
<i class="glyphicon glyphicon-remove pull-right" ng-click="toState('slider')"></i>
|
|
</h1>
|
|
<ul class="list-group" qm-list="{{characters.length}}">
|
|
<li ng-repeat="character in characters" class="list-group-item">
|
|
<a ng-href="{{character.house.url}}" ng-if="character.house!=''" class="hasimg" target="_blank">
|
|
<img ng-src="{{character.house.img}}">
|
|
</a>
|
|
<a ng-href="{{character.url}}" ng-class="{noimg:(character.house=='')}">{{character.name}}</a>
|
|
<toggle-switch
|
|
ng-model="options.characters[character.key]"
|
|
on-label="Show"
|
|
off-label="Hide"
|
|
class="pull-right">
|
|
</toggle-switch>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div id="search" ng-show="state=='search'">
|
|
<h1>
|
|
Search
|
|
<i class="glyphicon glyphicon-remove pull-right" ng-click="toState('slider')"></i>
|
|
</h1>
|
|
<div class="input-group">
|
|
<input id="searchInput" ng-model="search" type="text" class="form-control" placeholder="towns, houses, characters, titles">
|
|
<span class="input-group-addon">
|
|
<i class="glyphicon glyphicon-search"></i>
|
|
</span>
|
|
</div>
|
|
<div class="list-group" ng-show="search!==''">
|
|
<button
|
|
ng-repeat="result in searchResults | filter:{ title: search }"
|
|
class="list-group-item"
|
|
ng-click="resultClick(result)">
|
|
<i class="glyphicon {{result.icon}}"></i>
|
|
<span>
|
|
{{result.title}}
|
|
<small>{{result.subtitle}}</small>
|
|
</span>
|
|
<i class="glyphicon glyphicon-menu-right pull-right"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="options" ng-show="state=='options'">
|
|
<h1>
|
|
Options
|
|
<i class="glyphicon glyphicon-remove pull-right" ng-click="toState('slider')"></i>
|
|
</h1>
|
|
<ul class="list-group">
|
|
<li class="list-group-item">
|
|
Character Paths
|
|
<toggle-switch
|
|
ng-model="options.characterPaths"
|
|
on-label="Show"
|
|
off-label="Hide"
|
|
class="pull-right">
|
|
</toggle-switch>
|
|
</li>
|
|
<li class="list-group-item">
|
|
House Heraldry
|
|
<toggle-switch
|
|
ng-model="options.houseHeraldry"
|
|
on-label="Show"
|
|
off-label="Hide"
|
|
class="pull-right">
|
|
</toggle-switch>
|
|
</li><li class="list-group-item">
|
|
Geographic Regions
|
|
<toggle-switch
|
|
ng-model="options.geographicRegions"
|
|
on-label="Show"
|
|
off-label="Hide"
|
|
class="pull-right">
|
|
</toggle-switch>
|
|
</li><li class="list-group-item">
|
|
Political Allegiances
|
|
<toggle-switch
|
|
ng-model="options.politicalAllegiances"
|
|
on-label="Show"
|
|
off-label="Hide"
|
|
class="pull-right">
|
|
</toggle-switch>
|
|
</li>
|
|
</ul>
|
|
|
|
|
|
</div>
|
|
|
|
<div id="about" ng-show="state=='about'" qmList>
|
|
<h1>
|
|
About Quatrermaester.info
|
|
<i class="glyphicon glyphicon-remove pull-right" ng-click="toState('slider')"></i>
|
|
</h1>
|
|
<p>This is a map of the world depicted in the novel series <a target="_blank" href="http://www.georgerrmartin.com/bibliography.html">A Song of Ice & Fire</a> and the TV adaptation, <a target="_blank" href="http://www.hbo.com/game-of-thrones">A Game of Thrones</a>. The website is designed to display useful information on top of the map layer and link to additional details on the <a target="_blank" href="http://awoiaf.westeros.org">Westeros.org wiki site</a>.</p>
|
|
<p>If you haven't finished reading the novels or watching the shows, you can hide any details that might spoil the plot. Simply drag the slider in the top-right corner to the last chapter or episode that you've completed. You can move the slider with arrow buttons in order to animate the characters' paths. Keep in mind that the slider only controls this map; any page you may open on <span style="font-style:italic;">the wiki site may contain spoilers</span>.</p>
|
|
<!-- <p>If you'd like to share this map with others and point them to a specific location, hold down the Ctrl button while you click on the map. You will be given a URL that will automatically center the map on that point. (e.g. <a id="lightboxLink" href="#@Winterfell">Winterfell</a>)</p> -->
|
|
<p>The map layer used in this website was drawn by <a target="_blank" href="http://www.sermountaingoat.co.uk/map">theMountainGoat</a>, based on previous work by <a target="_blank" href="http://www.cartographersguild.com/finished-maps/6683-westeros-fan-project.html">Tear of the Cartographer's Guild</a>. The map interface is built on the <a target="_blank" href="http://developers.google.com/maps/documentation/javascript/">Google Maps API</a>, through the <a target="_blank" href="http://angular-ui.github.io/angular-google-maps/">angular-google-maps directive</a>. It displays custom tiles generated by <a target="_blank" href="http://www.bartlett.ucl.ac.uk/casa/latest/software/gmap-image-cutter">GMap Image Cutter Version 1.42</a>. Intellectual property of <span style="font-style:italic;">A Song of Ice and Fire</span>, this map and all locations belong to <a target="_blank" href="http://www.georgerrmartin.com">George R.R. Martin</a>. If you find any errors in the map data, please <a target="_blank" href="mailto:ryan@rslc.us">let me know</a>.</p>
|
|
<p>You may notice that this map is contradicted, in places, by the maps shown in <a target="_blank" href="http://www.randomhouse.com/book/221316/the-lands-of-ice-and-fire-a-game-of-thrones-by-george-rr-martin/other">The Lands of Ice and Fire</a>. Since the maps in that collection are clearly copyrighted material, I have no intention of copying them directly and I'm going to remain cautious in pulling details from them to correct this website. You can find low-resolution versions of the official maps on <a target="_blank" href="http://www.fantasticmaps.com/the-lands-of-ice-and-fire/">the artist's website</a> or in Random House's <a target="_blank" href="https://itunes.apple.com/hk/app/george-r.-r.-martins-world/id570015223">iOS</a> & <a target="_blank" href="https://play.google.com/store/apps/details?id=com.randomhouse.woiaf">Android</a> apps.</p>
|
|
|
|
<h1>Other Resources</h1>
|
|
<ul>
|
|
<li>
|
|
<a target="_blank" href="http://joeltronics.github.io/got-book-show/bookshow.html">Game of Thrones episode chapter coverage</a>
|
|
</li>
|
|
<li>
|
|
<a target="_blank" href="https://www.reddit.com/r/gameofthrones/comments/1g1yvk/s03e10_narrative_chart_seasons_13_completed/">Game of Thrones (S1-3) Narrative Chart</a>
|
|
</li>
|
|
<li>
|
|
The Wars of Westeros Mapped Out - Parts
|
|
<a target="_blank" href="https://www.reddit.com/r/asoiaf/comments/4sg7cn/spoilers_everything_the_wars_of_westeros_mapped/">1</a>,
|
|
<a target="_blank" href="https://www.reddit.com/r/asoiaf/comments/4ss3hp/spoilers_everything_the_wars_of_westeros_mapped/">2</a>,
|
|
<a target="_blank" href="https://www.reddit.com/r/asoiaf/comments/4t11n8/spoilers_everything_the_wars_of_westeros_mapped/">3</a>,
|
|
<a target="_blank" href="https://www.reddit.com/r/asoiaf/comments/4tckjy/spoilers_everything_the_wars_of_westeros_mapped/#">4</a>,
|
|
<a target="_blank" href="https://www.reddit.com/r/asoiaf/comments/4tofm3/spoilers_everything_the_wars_of_westeros_mapped/">5</a>,
|
|
</li>
|
|
<!-- <li>
|
|
<a target="_blank" href="#">Something</a>
|
|
</li>
|
|
<li>
|
|
<a target="_blank" href="#">Something</a>
|
|
</li>
|
|
<li>
|
|
<a target="_blank" href="#">Something</a>
|
|
</li>
|
|
<li>
|
|
<a target="_blank" href="#">Something</a>
|
|
</li>
|
|
<li>
|
|
<a target="_blank" href="#">Something</a>
|
|
</li> -->
|
|
<li>
|
|
<a target="_blank" href="http://viewers-guide.hbo.com/game-of-thrones/season-1/episode-1/map/location/27/kings-landing">HBO Viewers' Guide</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div id="edit" ng-show="state=='edit'">
|
|
<h1>
|
|
Editor
|
|
<i class="glyphicon glyphicon-remove pull-right" ng-click="toState('slider')"></i>
|
|
</h1>
|
|
|
|
<table>
|
|
<tbody ng-repeat="path in mapModels.editablePaths">
|
|
<tr ng-repeat="point in path.path">
|
|
<td>{{path.key}}</td>
|
|
<td>{{point.location}}</td>
|
|
<td>{{point.latitude | number:4}}</td>
|
|
<td>{{point.longitude | number:4}}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</body>
|
|
</html>
|