From 36c1182710bcb132e6e094eed1554933a733da89 Mon Sep 17 00:00:00 2001 From: ZhengLinLei Date: Sat, 14 Oct 2023 15:18:04 +0200 Subject: [PATCH] New Feature Share With Friends #39 --- css/style.css | 2 +- css/style.css.map | 2 +- index.html | 14 ++++- js/lib/png2share.js | 118 ++++++++++++++++++++++++++++++++++++++++ js/{ => pwa}/pwa.js | 5 +- js/{ => pwa}/pwa.min.js | 0 js/script.js | 116 ++++++++++++++++++++++++++++++++++----- scss/style.scss | 86 ++++++++++++++++++++++++++++- sw.js | 3 +- 9 files changed, 325 insertions(+), 21 deletions(-) create mode 100644 js/lib/png2share.js rename js/{ => pwa}/pwa.js (91%) rename js/{ => pwa}/pwa.min.js (100%) diff --git a/css/style.css b/css/style.css index 29cf825..7445955 100644 --- a/css/style.css +++ b/css/style.css @@ -1 +1 @@ -*{margin:0;padding:0;color:#fff;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-tap-highlight-color:rgba(0,0,0,0)}html{min-height:calc(100% + env(safe-area-inset-top)) !important;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left) !important}body{font-family:"Source Code Pro",monospace;text-align:center;cursor:pointer}body .point-result{position:fixed;top:calc(20vh + 50px);z-index:99;left:50%;transform:translateX(-50%);transition:.8s}body .point-result.active{top:40px}body .combo-extra-point{position:fixed;top:200px;left:50%;transform:translateX(-50%);transition:.3s;opacity:0}body .combo-extra-point.active{animation:extraPointFlash 1s ease-out}body .combo-strike{font-weight:800;font-size:54px;position:fixed;top:50vh;left:50vw;transform:translate(-50%, 15vh);transition:.3s;opacity:0}body .combo-strike.open{transform:translate(-50%, 10vh) scale(1.7) rotate(-10deg);opacity:1}body .result-area{transition:.4s;position:fixed;width:100vw;height:100vh;background-color:rgba(0,0,0,.8);display:flex;justify-content:center}body .result-area.disable{opacity:0}body .result-area header{margin-top:20vh;position:relative;transition:1s}body .result-area header .best{display:none}body .result-area header.new .best,body .result-area header.new .color-shape{display:block}body .result-area header.new .score{display:none}body .result-area header .color-shape{height:5px;display:none;width:100%;margin-top:5px;background:linear-gradient(90deg, #42c2f1 0%, #fbda4f 25%, #ab63df 50%, #5fc581 75%, #42c2f1 100%);background-size:200%;animation:moveGradient 3s linear infinite}@keyframes moveGradient{0%{background-position:0% 0%}100%{background-position:-200% 0%}}body .result-area footer.flash-text{position:absolute;bottom:20vh;animation:flash 1s infinite ease}body .result-area footer.flash-text .mobile-version{display:none}@media screen and (max-width: 700px){body .result-area footer.flash-text .mobile-version{display:block}body .result-area footer.flash-text .desktop-version{display:none}}body #pwa-install{position:fixed;top:30px;left:50%;transform:translateX(-50%) translateY(-100%);background-color:#fff;z-index:999;padding:10px;border-radius:5px;display:none;justify-content:space-between;grid-gap:20px;width:250px;height:60px;flex-wrap:nowrap;overflow:hidden}body #pwa-install.display{display:flex;animation:scrollDown .3s ease forwards}body #pwa-install .pwa-install-action{flex:1;justify-content:space-between;display:flex;flex-direction:column}body #pwa-install .pwa-install-text>*{font-size:12px;color:#000;text-align:start}body #pwa-install .pwa-install-text>*.pwa-install-description{font-size:10px;color:#999}body #pwa-install .pwa-install-icon>img{width:60px;border-radius:5px;height:60px}body #pwa-install .pwa-install-button{display:flex;justify-content:end}body #pwa-install .pwa-install-button button{border:none;background-color:#42c2f1;color:#fff;padding:7px 15px;border-radius:5px;cursor:pointer;font-size:10px;transition:.3s;font-weight:bold}body #pwa-install .pwa-install-button button:hover{background-color:#5fc581}@keyframes flash{50%{opacity:0}100%{opacity:1}}@keyframes extraPointFlash{60%{top:100px;opacity:1}100%{top:90px;opacity:0}}@keyframes scrollDown{100%{transform:translateX(-50%) translateY(0%)}}/*# sourceMappingURL=style.css.map */ \ No newline at end of file +*{margin:0;padding:0;color:#fff;-webkit-touch-callout:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-tap-highlight-color:rgba(0,0,0,0)}html{min-height:calc(100% + env(safe-area-inset-top)) !important;padding:env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left) !important}body{font-family:"Source Code Pro",monospace;text-align:center;cursor:pointer}body .point-result{position:fixed;top:calc(20vh + 50px);z-index:99;left:50%;transform:translateX(-50%);transition:.8s}body .point-result.active{top:40px}body .combo-extra-point{position:fixed;top:200px;left:50%;transform:translateX(-50%);transition:.3s;opacity:0}body .combo-extra-point.active{animation:extraPointFlash 1s ease-out}body .combo-strike{font-weight:800;font-size:54px;position:fixed;top:50vh;left:50vw;transform:translate(-50%, 15vh);transition:.3s;opacity:0}body .combo-strike.open{transform:translate(-50%, 10vh) scale(1.7) rotate(-10deg);opacity:1}body .result-area{transition:.4s;position:fixed;width:100vw;height:100vh;background-color:rgba(0,0,0,.8);display:flex;justify-content:center}body .result-area.disable{opacity:0}body .result-area header{margin-top:20vh;position:relative;transition:1s}body .result-area header .best{display:none}body .result-area header.new .best,body .result-area header.new .color-shape{display:block}body .result-area header.new .score{display:none}body .result-area header .color-shape{height:5px;display:none;width:100%;margin-top:5px;background:linear-gradient(90deg, #42c2f1 0%, #fbda4f 25%, #ab63df 50%, #5fc581 75%, #42c2f1 100%);background-size:200%;animation:moveGradient 3s linear infinite}@keyframes moveGradient{0%{background-position:0% 0%}100%{background-position:-200% 0%}}body .result-area footer.flash-text{position:absolute;bottom:20vh;animation:flash 1s infinite ease}body .result-area footer.flash-text .mobile-version{display:none}@media screen and (max-width: 700px){body .result-area footer.flash-text .mobile-version{display:block}body .result-area footer.flash-text .desktop-version{display:none}}body #click-event{width:100vw;height:100vh;z-index:2;position:fixed;top:0;left:0}body #pwa-install{position:fixed;top:30px;left:50%;transform:translateX(-50%) translateY(-100%);background-color:#fff;z-index:2;padding:10px;border-radius:5px;display:none;justify-content:space-between;grid-gap:20px;width:250px;height:60px;flex-wrap:nowrap;overflow:hidden}body #pwa-install.display{display:flex;animation:scrollDown .3s ease forwards}body #pwa-install .pwa-install-action{flex:1;justify-content:space-between;display:flex;flex-direction:column}body #pwa-install .pwa-install-text>*{font-size:12px;color:#000;text-align:start}body #pwa-install .pwa-install-text>*.pwa-install-description{font-size:10px;color:#999}body #pwa-install .pwa-install-icon>img{width:60px;border-radius:5px;height:60px}body #pwa-install .pwa-install-button{display:flex;justify-content:end}body #pwa-install .pwa-install-button button{border:none;background-color:#42c2f1;color:#fff;padding:7px 15px;border-radius:5px;cursor:pointer;font-size:10px;transition:.3s;font-weight:bold}body #pwa-install .pwa-install-button button:hover{background-color:#5fc581}body #record-share{position:fixed;top:50%;left:50%;transform:translate(-50%, -50%);z-index:99;border-radius:5px;overflow:hidden;background-color:#fff;transition:.5s;display:none}body #record-share.display{display:block;animation:jumpShaking .5s}body #record-share:hover{transform:translate(-50%, -50%) rotate(-5deg) scale(1.1)}body #record-share *{color:#000}body #record-share img{width:35vw;height:35vw;min-width:140px;min-height:140px;max-width:200px;max-height:200px;-o-object-fit:cover;object-fit:cover}@media screen and (max-height: 700px){body #record-share img{width:28vw;height:28vw;max-height:180px;min-width:180px}}@media(hover: none){body #record-share.display{animation:jumpShakingTouch .5s forwards}}body #record-share small{display:block;padding:10px;font-size:10px}@keyframes flash{50%{opacity:0}100%{opacity:1}}@keyframes extraPointFlash{60%{top:100px;opacity:1}100%{top:90px;opacity:0}}@keyframes scrollDown{100%{transform:translateX(-50%) translateY(0%)}}@keyframes jumpShaking{0%{transform:translate(-50%, -50%)}25%{transform:translate(-50%, calc(-50% - 9px))}35%{transform:translate(-50%, calc(-50% - 9px)) rotate(-5deg)}55%{transform:translate(-50%, calc(-50% - 9px)) rotate(5deg)}65%{transform:translate(-50%, calc(-50% - 9px)) rotate(-5deg)}75%{transform:translate(-50%, calc(-50% - 9px)) rotate(5deg)}100%{transform:translate(-50%, -50%)}}@keyframes jumpShakingTouch{0%{transform:translate(-50%, -50%)}25%{transform:translate(-50%, calc(-50% - 9px))}35%{transform:translate(-50%, calc(-50% - 9px)) rotate(-5deg)}55%{transform:translate(-50%, calc(-50% - 9px)) rotate(5deg)}65%{transform:translate(-50%, calc(-50% - 9px)) rotate(-5deg)}75%{transform:translate(-50%, calc(-50% - 9px)) rotate(5deg)}100%{transform:translate(-50%, -50%) rotate(-5deg) scale(1.1)}}/*# sourceMappingURL=style.css.map */ \ No newline at end of file diff --git a/css/style.css.map b/css/style.css.map index 3b30b90..0750430 100644 --- a/css/style.css.map +++ b/css/style.css.map @@ -1 +1 @@ -{"version":3,"sources":["../scss/style.scss"],"names":[],"mappings":"AAAA,EACI,QAAA,CACA,SAAA,CACA,UAAA,CACA,0BAAA,CACA,wBAAA,CAEG,qBAAA,CAEK,gBAAA,CAER,yCAAA,CACA,yCAAA,CAGJ,KAEI,2DAAA,CACA,4HAAA,CAGJ,KACI,uCAAA,CACA,iBAAA,CACA,cAAA,CAEA,mBACI,cAAA,CACA,qBAAA,CACA,UAAA,CACA,QAAA,CACA,0BAAA,CACA,cAAA,CAEA,0BACI,QAAA,CAGR,wBACI,cAAA,CACA,SAAA,CACA,QAAA,CACA,0BAAA,CACA,cAAA,CACA,SAAA,CAGA,+BACI,qCAAA,CAGR,mBACI,eAAA,CACA,cAAA,CACA,cAAA,CACA,QAAA,CACA,SAAA,CACA,+BAAA,CACA,cAAA,CACA,SAAA,CAEA,wBACI,yDAAA,CACA,SAAA,CAGR,kBAII,cAAA,CACA,cAAA,CACA,WAAA,CACA,YAAA,CACA,+BAAA,CACA,YAAA,CACA,sBAAA,CATA,0BACI,SAAA,CAUJ,yBACI,eAAA,CACA,iBAAA,CACA,aAAA,CACA,+BACI,YAAA,CAIA,6EACI,aAAA,CAEJ,oCACI,YAAA,CAGR,sCACI,UAAA,CACA,YAAA,CACA,UAAA,CACA,cAAA,CAEA,kGAAA,CACA,oBAAA,CACA,yCAAA,CAGJ,wBACI,GACI,yBAAA,CAEJ,KACI,4BAAA,CAAA,CAIZ,oCACI,iBAAA,CACA,WAAA,CACA,gCAAA,CACA,oDACI,YAAA,CAEJ,qCACI,oDACI,aAAA,CAEJ,qDACI,YAAA,CAAA,CAMhB,kBAGI,cAAA,CACA,QAAA,CACA,QAAA,CACA,4CAAA,CACA,qBAAA,CACA,WAAA,CACA,YAAA,CACA,iBAAA,CACA,YAAA,CACA,6BAAA,CACA,aAAA,CACA,WAAA,CACA,WAda,CAeb,gBAAA,CACA,eAAA,CACA,0BACI,YAAA,CAEA,sCAAA,CAEJ,sCACI,MAAA,CACA,6BAAA,CACA,YAAA,CACA,qBAAA,CAEJ,sCACI,cAAA,CACA,UAAA,CACA,gBAAA,CAEA,8DACI,cAAA,CACA,UAAA,CAGR,wCACI,UAvCS,CAwCT,iBAAA,CACA,WAzCS,CA2Cb,sCACI,YAAA,CACA,mBAAA,CACA,6CAEI,WAAA,CACA,wBAAA,CACA,UAAA,CACA,gBAAA,CACA,iBAAA,CACA,cAAA,CACA,cAAA,CACA,cAAA,CACA,gBAAA,CAEA,mDACI,wBAAA,CAOpB,iBACI,IACI,SAAA,CAEJ,KACI,SAAA,CAAA,CAIR,2BACI,IACI,SAAA,CACA,SAAA,CAEJ,KACI,QAAA,CACA,SAAA,CAAA,CAIR,sBACI,KACI,yCAAA,CAAA","file":"style.css"} \ No newline at end of file +{"version":3,"sources":["../scss/style.scss"],"names":[],"mappings":"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","file":"style.css"} \ No newline at end of file diff --git a/index.html b/index.html index 98d12b7..8f1be08 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - + @@ -45,6 +45,9 @@

BEST SCORE

+ +
+
@@ -61,9 +64,16 @@

BEST SCORE

+ +
+ + Tap to share picture +
+ + - + \ No newline at end of file diff --git a/js/lib/png2share.js b/js/lib/png2share.js new file mode 100644 index 0000000..41c50a6 --- /dev/null +++ b/js/lib/png2share.js @@ -0,0 +1,118 @@ +// ================================================================================ + +// Github: https://github.com/hughsk/canvas-pixels +// +// Get Pixel amount in a 3D canvas +function getPixels3d(gl) { + var canvas = gl.canvas + var height = canvas.height + var width = canvas.width + var buffer = new Uint8Array(width * height * 4) + + gl.readPixels(0, 0 + , canvas.width + , canvas.height + , gl.RGBA + , gl.UNSIGNED_BYTE + , buffer + ); + + return buffer +} + +// Get Pixel amount in a 2D canvas +function getPixels2d(ctx) { + var canvas = ctx.canvas + var height = canvas.height + var width = canvas.width + + return ctx.getImageData(0, 0, width, height).data +} + + + +// ================================================================================ + + +// WebGL to 2D CANVAS +// Github: https://github.com/Experience-Monks/webgl-to-canvas2d +const Webgl2canvas = (webgl, canvas2D) => { + + var outCanvas = canvas2D ? canvas2D.canvas || canvas2D : document.createElement('canvas'); + var outContext = outCanvas.getContext('2d'); + var outImageData; + + webgl = (webgl instanceof WebGLRenderingContext) ? webgl : (webgl.getContext('webgl2') || webgl.getContext('webgl') || webgl.getContext('experimental-webgl')); + + outCanvas.width = webgl.canvas.width; + outCanvas.height = webgl.canvas.height; + + outImageData = outContext.getImageData(0, 0, outCanvas.width, outCanvas.height); + + outImageData.data.set(new Uint8ClampedArray(getPixels3d(webgl).buffer)); + outContext.putImageData(outImageData, 0, 0); + outContext.translate(0, outCanvas.height); + outContext.scale(1, -1); + outContext.drawImage(outCanvas, 0, 0); + outContext.setTransform(1, 0, 0, 1, 0, 0); + + return outCanvas; +}; + + +// ================================================================================ + +// Stackoverflow: https://stackoverflow.com/a/17906462 +// Stackoverflow: https://stackoverflow.com/questions/17906169/how-to-copy-from-one-canvas-to-other-canvas +// +// Convert WebGL Canvas to Image +// Canvas(WebGL) -> Canvas(2D){Do changes} -> Image(JPG, PNG) +const DrawCanvasCopy = (canvas, callback, callbackBlob) => { + let c = Webgl2canvas(canvas); + // Prepare new canvas + callback(c.getContext('2d')); + // Export + c.toBlob(callbackBlob); + // Delete + c.remove(); +} + +// ================================================================================ + +// Stackblock: https://stackoverflow.com/questions/68362603/share-image-via-social-media-from-pwa +// +// Convert blob to image share +const Blob2Share = async(blob) => { + if (!('share' in navigator) || !('canShare' in navigator)) { + return false; + } + const files = [new File([blob], 'newRecord.png', { type: blob.type })]; + const shareData = { + text: 'Play with me. In Stackblock.io', + title: 'Stackblock.io', + files, + }; + if (navigator.canShare(shareData)) { + try { + await navigator.share(shareData); + } catch (err) { + if (err.name !== 'AbortError') { + console.error(err.name, err.message); + return false; + } + } + } else { + console.warn('Sharing not supported', shareData); + return false; + } +}; + +const Blob2Download = (blob) => { + let a = document.createElement('a'); + let url = window.URL.createObjectURL(blob); + a.href = url; + a.download = "StackBlock_newRecord.png"; + a.click(); + window.URL.revokeObjectURL(url); + a.remove(); +} \ No newline at end of file diff --git a/js/pwa.js b/js/pwa/pwa.js similarity index 91% rename from js/pwa.js rename to js/pwa/pwa.js index 6911237..ee9c222 100644 --- a/js/pwa.js +++ b/js/pwa/pwa.js @@ -18,10 +18,13 @@ window.addEventListener("load", () => { if (window.matchMedia('(display-mode: standalone)').matches || window.matchMedia('(display-mode: fullscreen)').matches || window.navigator.standalone === true || localStorage.getItem('PWA_installed') === "true") { localStorage.setItem("PWA_installed", 'true'); activeDownload = localStorage.getItem("PWA_installed"); + } else { + localStorage.removeItem("PWA_installed"); + activeDownload = false; } } - if(activeDownload || activeDownload == 'true') { + if(!activeDownload || activeDownload == 'false') { enableDownload = true; installBtn.addEventListener("click", () => { diff --git a/js/pwa.min.js b/js/pwa/pwa.min.js similarity index 100% rename from js/pwa.min.js rename to js/pwa/pwa.min.js diff --git a/js/script.js b/js/script.js index a2afab3..f84b14f 100644 --- a/js/script.js +++ b/js/script.js @@ -8,7 +8,18 @@ let GAME_ = { combo: 0, bestResult: (window.localStorage.getItem('bestResult')) ? window.localStorage.getItem('bestResult') : 0, newRecord: false, // TO RESET SCREEN - designPalette: 6 + designPalette: 0, + // + // Stackoverflow: https://stackoverflow.com/questions/30628064/how-to-toggle-preservedrawingbuffer-in-three-js + // Stackoverflow: https://stackoverflow.com/a/30647502 + screenshot: { + enable: false, + frames: 0, + // Take screenshot after x frames + callback: null, + blob: null + // Image content buffer + }, // TO TAKE SCREENSHOT IN RENDER [enable:boolean, callback:object] } // ================================== @@ -53,6 +64,10 @@ window.addEventListener('load', ()=>{ let scoreTab = document.querySelector('.score-tab'); let comboStrike = document.querySelector('.combo-strike'); let comboExtraPoint = document.querySelector('.combo-extra-point'); + // EVENT LAYER DOM + let eventLayer = document.querySelector('#click-event'); + // RECORD SHARE + let recordShare = document.querySelector('#record-share'); /* ========================================== = FUNCTIONS ============================================*/ @@ -141,7 +156,7 @@ window.addEventListener('load', ()=>{ return `#${f(0)}${f(8)}${f(4)}`; } - // RESET COLISION WORLD AND SCENE + // RESET COLISION WORLD AND SCENE AND OTHER STUFFS (LIKE MY MADNESS BECAUSE THERE ARE MANY BUGS) function reset(){ GAME_.designPalette = Math.floor(Math.random() * colorDesign.length); @@ -182,7 +197,12 @@ window.addEventListener('load', ()=>{ // FIRST LAYER addLayer(0, 0, boxSize.x, boxSize.z, 'x'); // TOP LEVEL - + + // DISABLE PWA IF EXIST + document.querySelector('#pwa-install').classList.remove('display'); + + // REMOVE NEW RECORD SHARE + recordShare.classList.remove('display'); } // ============================================= @@ -223,10 +243,15 @@ window.addEventListener('load', ()=>{ camera.lookAt(0, 0, 0); // RENDER SCENE - renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer = new THREE.WebGLRenderer( + { + antialias: true, + // preserveDrawingBuffer: true + }); renderer.setSize(window.innerWidth, window.innerHeight); renderer.render(scene, camera); + renderer.domElement.id = "Stackblock"; // DISPLAY document.body.appendChild(renderer.domElement); @@ -257,8 +282,6 @@ window.addEventListener('load', ()=>{ // DISABLE RSULT AND DISPLAY POINTS resultTabDom.classList.toggle('disable'); pointDom.classList.toggle('active'); - // DISABLE PWA IF EXIST - document.querySelector('#pwa-install').classList.remove('display'); // DISABLE NEW RECORD if(GAME_.newRecord){ @@ -409,12 +432,18 @@ window.addEventListener('load', ()=>{ // ACTIVE RECORD MODE GAME_.newRecord = true; + + GAME_.screenshot.callback = img => { + recordShare.replaceChild(img, recordShare.querySelector('img')); + // SHOW ANIMATION: SHAKY SHAKY SHAKIRA + recordShare.classList.add('display'); + } + GAME_.screenshot.enable = true; } // CHECK PWA INSTALLATION (1.0.4 version) - if (enableDownload) { + if (enableDownload) document.querySelector('#pwa-install').classList.add('display'); - } } } } @@ -449,17 +478,70 @@ window.addEventListener('load', ()=>{ updatePhisics(); renderer.render(scene, camera); + + // CHECK IF CLIENT REQUESTED TO TAKE A SCREENSHOT + // This section of code must be executed after renderer.render(scene, camera) to avoid buffer cleaning + // Once the canvas(webgl2) buffer has been cleaned, it can not take screenshot anymore. + if (GAME_.screenshot.enable) { + // TAKE THE SCREENSHOT AFTER 5 FRAMES FOR MORE PRECISE IMAGE STATUS + if(GAME_.screenshot.frames == 5) { + // CREATE A EXTRA CANVAS + DrawCanvasCopy(renderer.domElement, + ctx => { + // BG + ctx.fillStyle = "rgba(0, 0, 0, 0.2)"; + ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); + // TEXT + ctx.fillStyle = "#ffffff"; + ctx.font = '32px monospace'; + + var textString = "NEW RECORD", + textWidth = ctx.measureText(textString).width; + + + ctx.fillText(textString , (ctx.canvas.width/2) - (textWidth / 2), ctx.canvas.height / 2 - 100); + + // RECORD + ctx.font = 'bold 64px monospace'; + + textString = GAME_.score; + textWidth = ctx.measureText(textString).width; + + ctx.fillText(textString , (ctx.canvas.width/2) - (textWidth / 2), ctx.canvas.height/ 2 + 50); + + }, + blob => { + const img = document.createElement("img"); + const url = URL.createObjectURL(blob); + + img.onload = () => { + // no longer need to read the blob so it is revoked + URL.revokeObjectURL(url); + }; + + img.src = url; + + // SAVE BLOB + GAME_.screenshot.blob = blob; + + GAME_.screenshot.callback(img); + }); + + // DISABLE OPTION, IF THE PROCESS HAS SUCCESS OF FAILED SHOULD DISABLE. + // OTHERWISE WITH THE DELAY OF THE CALLBACK THE FUNCTION WILL BE CALLED MULTIPLE TIMES + GAME_.screenshot.enable = false; + GAME_.screenshot.frames = 0; + } else { + GAME_.screenshot.frames++; + } + } } let supportsTouch = 'ontouchstart' in window || navigator.msMaxTouchPoints; let eventType = supportsTouch ? 'touchstart' : 'mousedown'; - window.addEventListener(eventType, e => { - if (!e.target.className.split(' ').some((c) => { return /pwa-.*/.test(c); })) { - fncStart(); - } - }); // ADD FNC + eventLayer.addEventListener(eventType, fncStart); // ADD FNC let keyFree = true; // PC Version @@ -482,6 +564,14 @@ window.addEventListener('load', ()=>{ keyFree = true; } }); + + // SHARE RECORD + recordShare.addEventListener(eventType, async () => { + if( ! await Blob2Share(GAME_.screenshot.blob)){ + Blob2Download(GAME_.screenshot.blob); + } + + }) }); diff --git a/scss/style.scss b/scss/style.scss index ce6f999..7ad0ab0 100644 --- a/scss/style.scss +++ b/scss/style.scss @@ -130,6 +130,14 @@ body{ } } + #click-event { + width: 100vw; + height: 100vh; + z-index: 2; + position: fixed; + top: 0; + left: 0; + } #pwa-install { $image-size: 60px; // @@ -138,7 +146,7 @@ body{ left: 50%; transform: translateX(-50%) translateY(-100%); background-color: white; - z-index: 999; + z-index: 2; padding: 10px; border-radius: 5px; display: none; @@ -195,6 +203,61 @@ body{ } } } + + #record-share { + $gadget-size: 35vw; + // + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + z-index: 99; + border-radius: 5px; + overflow: hidden; + background-color: white; + transition: .5s; + display: none; + &.display { + display: block; + animation: jumpShaking 0.5s; + } + &:hover { + transform: translate(-50%, -50%) rotate(-5deg) scale(1.1); + } + * { + color: black; + } + + img { + width: $gadget-size; + height: $gadget-size; + min-width: 140px; + min-height: 140px; + max-width: 200px; + max-height: 200px; + object-fit: cover; + } + // Dektop make it smaller + @media screen and (max-height: 700px) { + img { + width: calc($gadget-size * 0.8); + height: calc($gadget-size * 0.8); + max-height: 180px; + min-width: 180px; + } + } + // Mobile + @media (hover: none) { + &.display { + animation: jumpShakingTouch 0.5s forwards; + } + } + small { + display: block; + padding: 10px; + font-size: 10px; + } + } } @keyframes flash { @@ -221,4 +284,23 @@ body{ 100% { transform: translateX(-50%) translateY(0%); } -} \ No newline at end of file +} + +@keyframes jumpShaking { + 0% { transform: translate(-50%, -50%) } + 25% { transform: translate(-50%, calc(-50% - 9px)) } + 35% { transform: translate(-50%, calc(-50% - 9px)) rotate(-5deg) } + 55% { transform: translate(-50%, calc(-50% - 9px)) rotate(5deg) } + 65% { transform: translate(-50%, calc(-50% - 9px)) rotate(-5deg) } + 75% { transform: translate(-50%, calc(-50% - 9px)) rotate(5deg) } + 100% { transform: translate(-50%, -50%)} +} +@keyframes jumpShakingTouch { + 0% { transform: translate(-50%, -50%) } + 25% { transform: translate(-50%, calc(-50% - 9px)) } + 35% { transform: translate(-50%, calc(-50% - 9px)) rotate(-5deg) } + 55% { transform: translate(-50%, calc(-50% - 9px)) rotate(5deg) } + 65% { transform: translate(-50%, calc(-50% - 9px)) rotate(-5deg) } + 75% { transform: translate(-50%, calc(-50% - 9px)) rotate(5deg) } + 100% { transform: translate(-50%, -50%) rotate(-5deg) scale(1.1)} +} diff --git a/sw.js b/sw.js index 4ebc6bf..eee7536 100644 --- a/sw.js +++ b/sw.js @@ -13,7 +13,8 @@ let filesToCache = [ "https://cdn.jsdelivr.net/npm/party-js@latest/bundle/party.min.js", "./js/script.min.js", `./sw.js?v=${CACHE_VERSION}`, - "./js/pwa.min.js", + "./js/pwa/pwa.min.js", + // "./js/lib/png2share.min.js", "./index.html", "./", ];