diff --git a/README.md b/README.md index a5d7ff8..77bb095 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,8 @@ Note: Canvas specific configuartion like colors and cooldown is in `src/canvases.json` for all canvases. The CanvasSize is expected to be a power of 4 (4096, 16384, 65536,...) and not smaller than 256. bcd is base cooldown for unset pixels, pcd is cooldown for placing on top of others, cds is stacktime, req is the requirement to be allowed to set on canvas in total pixels placed. All the cooldown values are in ms. +If you want to add a new canvas, be sure that you additionally create `public/loading${canvasId}.png` and `public/assets3d/normal${canvasId}.jpg` and `public/assets3d/specular${canvasId}.jpg`, check out the existing ones to see what those files are for. + The default configuration values can be seen in `src/core/config.js` and for the canvases in `src/core/constats.js` ### Running diff --git a/public/loading.png b/public/loading0.png similarity index 100% rename from public/loading.png rename to public/loading0.png diff --git a/public/loading1.png b/public/loading1.png new file mode 100644 index 0000000..766589c Binary files /dev/null and b/public/loading1.png differ diff --git a/src/actions/index.js b/src/actions/index.js index 87d50d1..5ef5eb0 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -12,7 +12,7 @@ import type { Cell } from '../core/Cell'; import type { ColorIndex } from '../core/Palette'; import ProtocolClient from '../socket/ProtocolClient'; -import loadImage from '../ui/loadImage'; +import { loadImage } from '../ui/loadImage'; import { getColorIndexOfPixel, } from '../core/utils'; diff --git a/src/components/Globe.jsx b/src/components/Globe.jsx index 5f351e9..ebb48c1 100644 --- a/src/components/Globe.jsx +++ b/src/components/Globe.jsx @@ -19,6 +19,7 @@ const Globe = () => (
(0, 0)
Double click on globe to go back.
+
Loading...
); diff --git a/src/components/globe.tcss b/src/components/globe.tcss index b0ed9b2..950f55b 100644 --- a/src/components/globe.tcss +++ b/src/components/globe.tcss @@ -58,3 +58,21 @@ body { left: 16px; top: 16px } + +:global(#loading) { + font-size: 16px; + font-weight: bold; + position: absolute; + background-color: hsla(0,0%,89%,.8); + color: #4d4d4d; + text-align: center; + vertical-align: middle; + line-height: 36px; + width: auto; + height: 36px; + padding: 0 24px; + border: solid #000; + border-width: thin; + right: 16px; + top: 16px +} diff --git a/src/globe.js b/src/globe.js index f51b13e..7f1894a 100644 --- a/src/globe.js +++ b/src/globe.js @@ -114,6 +114,7 @@ document.addEventListener('DOMContentLoaded', () => { rotateToCoords(canvasSize, object, [x, y]); controls = createControls(); render(); + document.getElementById('loading').style.display = "none"; }, () => { // console.log(`${xhr.loaded} loaded`); }, () => { diff --git a/src/ui/ChunkRGB.js b/src/ui/ChunkRGB.js index 325e514..ebf6205 100644 --- a/src/ui/ChunkRGB.js +++ b/src/ui/ChunkRGB.js @@ -3,16 +3,7 @@ import type { Cell } from '../core/Cell'; import type { Palette } from '../core/Palette'; -import { TILE_SIZE, TILE_LOADING_IMAGE } from '../core/constants'; - -import loadImage from './loadImage'; - - -export const loadingTile = { - url: TILE_LOADING_IMAGE, - img: null, -}; -loadImage(TILE_LOADING_IMAGE).then((img) => { loadingTile.img = img; }); +import { TILE_SIZE } from '../core/constants'; class ChunkRGB { @@ -69,8 +60,8 @@ class ChunkRGB { return; } } - if (loadingTile.img) { - ctx.drawImage(loadingTile.img, 0, 0); + if (loadingTiles.hasTiles) { + ctx.drawImage(loadingTiles.getTile(0), 0, 0); return; } else { ctx.fillStyle = this.palette.colors[2]; diff --git a/src/ui/Renderer.js b/src/ui/Renderer.js index 1040d02..6092cda 100644 --- a/src/ui/Renderer.js +++ b/src/ui/Renderer.js @@ -19,7 +19,8 @@ import { renderPlaceholder, renderPotatoPlaceholder, } from './renderelements'; -import ChunkRGB, { loadingTile } from './ChunkRGB'; +import ChunkRGB from './ChunkRGB'; +import { loadingTiles } from './loadImage'; import pixelNotify from './PixelNotify'; @@ -205,8 +206,11 @@ class Renderer { if (chunk.ready) { context.drawImage(chunk.image, x, y); if (fetch) chunk.timestamp = curTime; - } else if (loadingTile.img) context.drawImage(loadingTile.img, x, y); - else context.fillRect(x, y, TILE_SIZE, TILE_SIZE); + } else if (loadingTiles.hasTiles) { + context.drawImage(loadingTiles.getTile(canvasId), x, y); + } else { + context.fillRect(x, y, TILE_SIZE, TILE_SIZE); + } } else { // we don't have that chunk if (fetch) { @@ -216,8 +220,11 @@ class Renderer { store.dispatch(fetchTile(canvasId, [tiledZoom, cx, cy])); } } - if (loadingTile.img) context.drawImage(loadingTile.img, x, y); - else context.fillRect(x, y, TILE_SIZE, TILE_SIZE); + if (loadingTiles.hasTiles) { + context.drawImage(loadingTiles.getTile(canvasId), x, y); + } else { + context.fillRect(x, y, TILE_SIZE, TILE_SIZE); + } } } } diff --git a/src/ui/loadImage.js b/src/ui/loadImage.js index 09ae5a2..00f82f2 100644 --- a/src/ui/loadImage.js +++ b/src/ui/loadImage.js @@ -1,6 +1,11 @@ /* @flow */ -function loadImage(url) { +/* + * general function for async loading images + * @param url url of image + * @return Promise + */ +export function loadImage(url) { return new Promise((resolve, reject) => { const img = new Image(); img.addEventListener('load', () => resolve(img)); @@ -11,4 +16,38 @@ function loadImage(url) { }); } -export default loadImage; +/* + * loading tiles that get temporarily shown till real tile is loaded + */ +class LoadingTiles { + tiles: Object; + hasTiles: boolean; + + constructor() { + this.hasTiles = false; + this.tiles = {}; + this.loadLoadingTile(0); + } + + getTile(canvasId: number) { + if (typeof this.tiles[canvasId] === 'undefined') { + this.loadLoadingTile(canvasId); + } + return this.tiles[canvasId] || this.tiles[0]; + } + + async loadLoadingTile(canvasId: number) { + if (this.tiles[canvasId] === null) { + return; + } + this.tiles[canvasId] = null; + const img = await loadImage(`./loading${canvasId}.png`); + this.tiles[canvasId] = img; + if (canvasId === 0) { + this.hasTiles = true; + } + } +} + + +export const loadingTiles = new LoadingTiles();