OSDN Git Service

663a50ff867b62b6d7e184a5a896075af1a6cbab
[automap/automap.git] / Automap / MapSRC / src / ViewFrame.js
1 function ViewFrame() {
2         // dom stuff
3         const map = document.createElement('canvas'); // the map we see
4         map.className = 'map';
5         map.height = window.innerHeight;
6         map.width = window.innerWidth;
7         document.getElementsByTagName('body')[0].append(map);
8         // this is the map that we actually draw on
9         this.map = map.getContext('2d', {
10                 alpha: false
11         });
12         this.map.imageSmoothingEnabled = false;
13
14         // the info box in the corner
15         this.infobox = document.getElementsByClassName('infoboxTable')[0];
16         this.infoboxSlots = new Array();
17
18         // load the metadata!
19         this.chunkScript = document.createElement('script');
20         this.chunkScript.type = 'text/javascript';
21         this.chunkScript.src = 'Metadata.js';
22         document.getElementsByTagName('body')[0].append(this.chunkScript);
23         this.chunkScript.addEventListener('load', () => {
24                 ViewFrame.initInfobox(this.infobox, this.infoboxSlots);
25                 this.x = ViewFrame.chunks.startCoords[0];
26                 this.y = ViewFrame.chunks.startCoords[1];
27                 this.availableChunks = ViewFrame.chunks.chunkMetadata;
28                 this.render();
29         }, {
30                 once: true
31         });
32
33         // Tracks images that have been loaded and are on the map
34         this.loadedChunksByName = new Map();
35         // this is needed because [1, 2] != [1, 2] and thats how we store coords.
36         this.loadedChunksByCoords = new Map();
37         this.availableChunks = null; // the chunks in ./Metadata.js
38         // so that we dont render twice at the same time
39         this.rendering = false;
40
41         this.x = -1;
42         this.y = -1; // can be fractional
43         this.zoom = 32; // pixels wide the images are to be
44         this.updateEdges();
45 }
46 // prototypes, some less... notable? methods are
47 // in ViewFrameUtils.js 
48 ViewFrame.prototype.reloadChunkList = function () {
49         if (this.chunkScript) {
50                 this.chunkScript.remove();
51                 delete this.chunkScript;
52         }
53
54         this.chunkScript = document.createElement('script');
55         this.chunkScript.type = 'text/javascript';
56         this.chunkScript.src = 'Metadata.js';
57         document.getElementsByTagName('body')[0].append(this.chunkScript);
58
59         this.chunkScript.addEventListener('load', () => {
60                 this.availableChunks = ViewFrame.chunks.chunkMetadata;
61                 this.render();
62         });
63 };
64
65 ViewFrame.prototype.render = function () {
66         if (!this.availableChunks) return;
67         if (this.rendering) clearInterval(ViewFrame.intervalRef);
68         this.rendering = true;
69         this.updateEdges();
70         this.map.clearRect(0, 0, window.innerWidth, window.innerHeight);
71         // culling
72         this.loadedChunksByCoords
73                 .forEach((chunk, coord) => { // check the bounds
74                         if (coord[0] < this.eastChunk &&
75                                 coord[0] >= this.westChunk &&
76                                 coord[1] <= this.northChunk &&
77                                 coord[1] >= this.southChunk) {
78
79                                 this.place(chunk, coord[0], coord[1]);
80                                 return;
81                         }
82                         // its out of range!!!
83                         // get 'em boys!!!!!
84                         this.loadedChunksByCoords.delete(coord);
85                         this.loadedChunksByName.delete(coord.join('_'));
86                         chunk.remove();
87                 });
88
89         // gathering what we need to load
90         const neededChunks = new Set();
91         for (var x = this.westChunk; x < this.eastChunk; x++) {
92                 for (var y = this.southChunk; y < this.northChunk; y++) {
93                         const chunKey = [x, y]; // chunk + key = chunKey :)
94                         const name = chunKey.join('_');
95                         // continue if its not available, or it is loaded
96                         if (!this.availableChunks.has(name) ||
97                                 this.loadedChunksByName.has(name)) continue;
98                         neededChunks.add(chunKey);
99                 }
100         }
101         // iterating over everything we need to load
102         const it = neededChunks.values();
103         ViewFrame.intervalRef = setInterval(() => {
104                 let round = it.next();
105                 if (!round.done) {
106                         // load
107                         const img = new Image(32, 32);
108                         const name = round.value.join('_');
109
110                         img.src = name + '.png';
111
112                         decode(img, loadedImage => {
113                                 this.place(img, round.value[0], round.value[1]);
114                         });
115                         this.loadedChunksByName.set(name, img);
116                         this.loadedChunksByCoords.set(round.value, img);
117                 } else {
118                         clearInterval(ViewFrame.intervalRef);
119                         this.rendering = false;
120                 }
121         }, 4);
122 };
123
124 ViewFrame.prototype.place = function (img, x, y) {
125         x -= this.x;
126         y -= this.y;
127         x *= this.zoom;
128         y *= this.zoom;
129         x += this.width / 2;
130         y += this.height / 2;
131
132         this.map.drawImage(img, Math.floor(x), Math.floor(y), this.zoom, this.zoom);
133 };
134
135 ViewFrame.prototype.updateInfobox = function (chunkName) {
136         const chunkMeta = this.availableChunks.get(chunkName);
137         this.infoboxSlots.forEach((l, k) => {
138                 l.innerText = chunkMeta ? chunkMeta[k] : '0';
139         });
140 };