From 5ee01f3cc23df29fffb19c23fd2d78034ab8ea03 Mon Sep 17 00:00:00 2001 From: HF Date: Fri, 3 Jan 2020 16:19:37 +0100 Subject: [PATCH] Improve Loading make loading tiles canvas specific make loading text on 3d globe --- README.md | 2 ++ public/{loading.png => loading0.png} | Bin public/loading1.png | Bin 0 -> 2383 bytes src/actions/index.js | 2 +- src/components/Globe.jsx | 1 + src/components/globe.tcss | 18 +++++++++++ src/globe.js | 1 + src/ui/ChunkRGB.js | 15 ++-------- src/ui/Renderer.js | 17 +++++++---- src/ui/loadImage.js | 43 +++++++++++++++++++++++++-- 10 files changed, 79 insertions(+), 20 deletions(-) rename public/{loading.png => loading0.png} (100%) create mode 100644 public/loading1.png diff --git a/README.md b/README.md index a5d7ff8b..77bb095e 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 0000000000000000000000000000000000000000..766589c3f2d6d4736f0033d78edf31a2eff2e564 GIT binary patch literal 2383 zcmchZ`#aN(8^=HU*yfPKbU>{bI-oQ?HHVTdhos~X@#MHl2;oT&V{B7WJxE7{+C0RH zEaoh%gq1W;v79I8avZgp&GzVfegB2;_qyKKecku_*VpyF-uEpRCwmp8ElL0Ys5l(6 zJp}-ewG{#=tW6+xv#<^T6g3=dkGK>1W(Pte`pq@q!@|2s*k`ZMIo@#aYgqESk8e3HsxKL{aV;#GmK(+00-(2+cCSCAP?u$ZyJ zEgu985(x?jFvQApL60U{as&AY8ZJ+Pgqe`hx_G9C4BfTQ*S3)UWsN$KdPkQSH5r&@dBG^u5Fh!j;6QznR_A*%n#}y)D`Xz7lQTWz(^x^Wg~$)JWtF zeh^s{HUHewS-Ja}1C`A~41eU*p-wd*zqej@9}m~UXsZ~3Goskcw@wYX>e8qg*mGXo zfrCm5lRuy^BGopj0hd(5EHn0o>>Te;Gxckgq6EB z5A9zwV8?M6DTtR2=knHgNhK(#`#!TPiai1HtQ3mi4$qjT8r57yIT_ueUmy>e)yLww zhIe_okss!5aKv|NS>3nUy!G@kA&Ry-79jvnQ;{C9uzT*B>uX>YMUp=u-MPpo(D!^! z4n^>=>7XiIFtC8?3?`Exv&OQETU|P7!1^AzZrF zE?bfZ3H&-@G92*-bEOhh5+sv8^#XXZ< zATAlAi*MTZl$3o9rHg1&;u_S!*(?Fi)|^8&(Z%8) zKZ5MZCo!g0i{j;$cMnt_?aatP3aBvL#_ZG9Cv${>&Wc)}iQQy4;Hq#r!ld8(cWai` z8pH_>Z)lUnxV$c2dDtFDWUJN09r4&1qnLGhwe1>3aF^G;uKfI56~&^I%wPAP#NIi5 z$_(asVKvVm)x1+FI1>w=xUB9 zj@VAFLk8adLx#d{otBk=eg0A#G&?s&YRxhiV$ER{Z4x^)`(_ZfzWNu~jBk<0q!%|b zkIQ}k#tTfA9B6O|Jm?PLEtkCWwRVzmQ|uQ9&KC*bQNIObKaxL}9btwPFC24B^T-KL zgFL`xLjr4~s%3DK_9V+MFX}1Ys1ATt7s3j!YO%0a`MpsvNmPwgEEr#D%7@>+6qfPA zPOte9b>88n@f~d;)(hiOMgC(i-&0l+l~{=L>XltgO^Rkdds6%p91;XQR^h@v^+`Qn zXm%}{9kreiO!}(Pl?u{Un~tM{#~5iz1GAi0dRNvT^Y+g<$fe|`rDIq_(t*&c@`+vi z%Cd5}(Wrkhd=F8~WGHEZ&z3@?0&DgAdn~teZC01$P|kD-#dj`u)?WZJ1$U_Ar~}Ri zM3oL=#9ZT~PZ4lul9y#V*EsKUqmFeS``)asJsHvK7`8>&R>Sn ztK-D|rNZwc-J|Q-9ytvvA3u_NwCH9bs}?GS%$4b)lndIvtxHH;gKM!}U(UyROL*!v z$*8JmQ1b&2U+0|G(HMVP4!<=($883S?c%*$F0Zb4)`FN%UobOVY_ZAQjZY%V0WnMT zOu3+-G7rESpEQ!beUREc^b$(x3c0Y4^>}*IAgJJ?92BSnwHVTt(jI_s7SlJIH6Hcd z^LQ+=T%nzZJbvgfylbVoXTWMgV<~F!r=a$*e1Jh~P#%bP9ETjhkbS84z_K(GklI7H@f?Dt|ITK z!rm$MIbAiL?bPE;M$IeIpp@_4Mu{2ckms>}Dl!PrzGJ~;9RnC^_XK7-x(Uj|Pr~rT zrSRV%k=V+?7r^$Wp&)J;b_g`l$*ApUlzJ&or_0W4&KZy%ZHf_}y%2V}9`|t_jnukg z$T (
(0, 0)
Double click on globe to go back.
+
Loading...
); diff --git a/src/components/globe.tcss b/src/components/globe.tcss index b0ed9b21..950f55ba 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 f51b13e6..7f1894a7 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 325e5144..ebf62054 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 1040d022..6092cda9 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 09ae5a24..00f82f28 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();