increase image size without loosing quality - JS - javascript

i'm using electron to make an app that get application icons.
so i used app.getFileIcon() to get the icon and with icon.toDataURL() and pass the image url with an event to index.html
and it works fine but when i increase the size of the image it gets blurry because the max size of icon by app.getFileIcon() can only be 32px(or 48 in MacOs or linux)
this is how it looks like (before height increase)
after height increase
Main.js
const { app, BrowserWindow, ipcMain, shell } = require('electron')
const path = require('path');
const { writeFileSync } = require('fs');
let win
function createWindow () {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
}
})
win.loadFile('public/index.html')
}
app.whenReady().then(createWindow)
// Get File Icons ------------------------------------------------
const filePath = path.normalize("C:\\Users\\hamid\\Desktop\\DualTouch\\NordVPN.lnk");
const realPath = shell.readShortcutLink(filePath).target
app.getFileIcon(realPath).then(icon => {
const ImgUrl = icon.toDataURL()
ipcMain.on('ImgUrl-request', (event)=>{
event.sender.send('ImgUrl-reply', ImgUrl)
})
writeFileSync('icon.png', icon.toPNG())
}).catch(err => console.log(err))
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DualTouch</title>
</head>
<body>
<div id="app"></div>
<script src="assets/js/app.js"></script>
<script>
const { ipcRenderer } = require('electron')
ipcRenderer.send('ImgUrl-request');
ipcRenderer.on('ImgUrl-reply', function (event, args) {
document.write(`<img src='${args}' />`)
});
</script>
</body>
</html>
Icon Url

Sadly the image size is inversely proportional to the quality, i.e the exposure of the picture elements of the image. So in order to get greater quality, I would suggest you get an image with more pixels and greater resolution.

You can't add information to an image that does not exist, but there are some really good upscaler's theses days, especially those based on AI.
For example going to this website -> https://bigjpg.com/ I was able to upscale your image to look like this ->
A quick search for tools for AI upscaling bring this up https://github.com/topics/upscaling , so maybe one of these options might be of use.

Related

("Document not defined" in renderer.js) - Sending data and rendering it in electron

I am trying to create a Debug app for Body Positioning Data. This data is received as JSON via MQTT in my receiveAndConversion.js. I was able to receive the data properly and print to console. So far so good. But now I want in my main window the values that I receive to show up (make the screen green for example when hand closed).
I have tried a lot of things including ipc and adding
nodeIntegration: true, contextIsolation: false, enableRemoteModule: true, as preferences in main.js
Researching this is kind of a pain, as I always get to questions where the person tries to change the DOM from main.js instead of the renderer.
I am new to electron and have been spending hours on the documentation but all their examples are either triggerd on launch of the app or by a button (user interaction). I need to change the DOM when a new message is received, independent on user interaction or other things.
My structure at the moment is like this:
main.js
receiveAndConversion.js
index.html
renderer.js
Except for receiveAndConversion.js, renderer.js and the mentioned Preferences in main.js, the code is more or less the same as The quick start guide.
The main issue that seems to block me is, that I cant seem to be able to call my renderer.js from my receiveAndConversion.js mqttClient.on() which runs when I have received a new message. My thinking was I could just call from there a render function in render.js but as it is called from receiveAndConversion.js I get a "document is not defined" error (at least I believe that's the reason).
I would really appreciate if you had an idea for me on how to implement this without having to put everything in main.js.
You can find the complete code below.
// main.js
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain } = require('electron')
//const Renderer = require('electron/renderer')
const path = require('path')
const mqttClient = require('./receiveAndConversion.js')
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
//nativeWindowOpen: true,
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true,
preload: path.join(__dirname, 'preload.js')
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
//
//ipcMain.handle('left-hand-closed', (event, arg) => {
// console.log('left hand is closed');
//}
//)
createWindow()
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
<!-- Create different field which will be used to visualise if hands are open or not. So one field for left hand one field for right hand. -->
<div id="left-hand"></div>
<div id="right-hand"></div>
<!-- You can also require other files to run in this process -->
<script src="./renderer.js"></script>
</body>
</html>
//renderer.js
// get info of open or closed hands from receiveAndConversion.js
// then make the left-hand div or right-hand div green or red depending on open or closed
//const {ipcRenderer} = require('electron')
// //write something in the divs
// leftHandDiv.innerHTML = 'Left Hand: ' + leftHandClosed
// rightHandDiv.innerHTML = 'Right Hand: ' + rightHandClosed
// ipcRenderer.handle('left-hand-closed', (event, arg) => {
// leftHandDiv.innerHTML = 'Left Hand: ' + arg
// }
// )
// ipcRenderer.handle('right-hand-closed', (event, arg) => {
// rightHandDiv.innerHTML = 'Right Hand: ' + arg
// }
// )
function handChange(leftHandClosed, rightHandClosed) {
//get the divs from the html file
const leftHandDiv = document.getElementById('left-hand')
const rightHandDiv = document.getElementById('right-hand')
//check if the hand is open or closed
if (leftHandClosed) {
leftHandDiv.style.backgroundColor = 'green'
console.log('left hand is closed');
} else {
leftHandDiv.style.backgroundColor = 'red'
console.log('left hand is open');
}
if (rightHandClosed) {
rightHandDiv.style.backgroundColor = 'green'
console.log('right hand is closed');
} else {
rightHandDiv.style.backgroundColor = 'red'
console.log('right hand is open');
}
}
//make handChange() usable outside of the renderer.js
module.exports = {
handChange
}
// preload.js
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})
To keep your receiveAndConversion.js file separate from your main.js file and send signals via IPC to index.html, you need access to Electrons window instance of index.html. This can be achieved by using a "getter" method. Separating the creation (and getting) of mainWindow into its own file will therefore be needed.
Good use of a preload.js script dictates setting nodeIntegration: false and contextIsolation: true. Additionally, there should be no need to use any form of remote modules. I have re-worked your preload.js script to be used only as a form of communication between the main process and render process. Various forms of preload.js scripts can be used, but in this instance I have used the most simplified (but not very flexible) approach.
Lastly, not having access to your receiveAndConversion.js file, I have mocked a random hand / position data stream.
As you can see, separating domains into their own files can keep the overall application logical, easy to maintain and bug free when adding additional features.
main.js (main process)
// Require the necessary Electron modules
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
// Require the necessary Node modules
const nodePath = require('path');
// Require the necessary Application modules
const appMainWindow = require(nodePath.join(__dirname, './main-window'));
const appReceiveAndConversion = require(nodePath.join(__dirname, './receiveAndConversion'));
// Prevent garbage collection
let mainWindow;
electronApp.on('ready', () => {
mainWindow = appMainWindow.create();
appReceiveAndConversion.run();
});
electronApp.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
electronApp.quit();
}
});
electronApp.on('activate', () => {
if (electronBrowserWindow.getAllWindows().length === 0) {
appMainWindow.create();
}
});
Having the create() and get methods of the mainWindow in its own file allows for inclusion within any other file that need reference to the mainWindow.
main-window.js (main process)
// Require the necessary Electron modules
const electronBrowserWindow = require('electron').BrowserWindow;
// Require the necessary Node modules
const nodePath = require('path');
let mainWindow;
function create() {
mainWindow = new electronBrowserWindow({
x: 0,
y: 0,
width: 800,
height: 600,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: nodePath.join(__dirname, './preload.js')
}
});
mainWindow.loadFile('index.html')
.then(() => { mainWindow.show(); })
return mainWindow;
}
function get() {
return mainWindow;
}
module.exports = {create, get}
receiveAndConversion.js (main process)
Mocked...
// Require the necessary Node modules
const nodePath = require('path');
// Require the necessary Application modules
const appMainWindow = require(nodePath.join(__dirname, './main-window'));
let mainWindow;
// Generate a random number
function randomNumber(lower, upper) {
return Math.floor(Math.random() * (upper - lower + 1) + lower)
}
// An infinitely polled function
function listener() {
let hand = (randomNumber(0, 1)) ? 'leftHand' : 'rightHand';
let position = (randomNumber(0, 1)) ? 'opened' : 'closed';
console.log(hand + ' ' + position); // Testing
mainWindow.webContents.send(hand, position);
}
// Called from main.js
function run() {
mainWindow = appMainWindow.get();
setInterval(() => { listener(); }, 350);
}
module.exports = {run}
preload.js (main process)
A simple (but rigid) example.
// Import the necessary Electron components
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;
// Exposed protected methods in the render process
contextBridge.exposeInMainWorld(
// Allowed 'ipcRenderer' methods
'electronAPI', {
// From main to render
leftHand: (position) => {
ipcRenderer.on('leftHand', position);
},
rightHand: (position) => {
ipcRenderer.on('rightHand', position);
}
});
Instead of changing background colors via JavaScript, it is better to change class names or even better again, data attribute values in this instance.
For simplicity, I have incorporated a revised renderer.js between the <script> tags.
index.html.js (render process)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Electron Test</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';"/>
<style>
body {
margin: 0;
padding: 0;
height: 100vh;
display: flex;
flex-flow: row nowrap;
}
#left-hand,
#right-hand {
flex: 1 0 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 3em;
}
#left-hand[data-position="closed"],
#right-hand[data-position="closed"] {
background-color: darkred;
}
#left-hand[data-position="opened"],
#right-hand[data-position="opened"] {
background-color: darkgreen;
}
</style>
</head>
<body>
<div id="left-hand" data-position="closed">Left Hand</div>
<div id="right-hand" data-position="closed">Right Hand</div>
</body>
<script>
let leftHand = document.getElementById('left-hand');
let rightHand = document.getElementById('right-hand');
window.electronAPI.leftHand((event, position) => {
console.log('leftHand ' + position); // Testing
leftHand.dataset.position = position;
});
window.electronAPI.rightHand((event, position) => {
console.log('rightHand ' + position); // Testing
rightHand.dataset.position = position;
});
</script>
</html>

Electron on click of a button can it execute node?

So I have a start button, and once the button is clicked I want it to execute a function.
I know I can execute the function on start of the electron app but is there anyway to say have a start button, and it execute the code on click of the button?
Also I know you can't use node in the browser, and I know Electron uses chromium, but there is still access to node right ?
This is the error I get :
Uncaught Exception:
ReferenceError: document is not defined
index.js
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const Bot = require('./bot')
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
}
const createWindow = () => {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
preload: "./bot.js"
}
});
// and load the index.html of the app.
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Open the DevTools.
mainWindow.webContents.openDevTools();
};
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.
Here is the bot.js file:
const robot = require('robotjs')
const electron = require('electron')
const ipc = electron.ipcRenderer
const Bot = () => {
const button = document.getElementById('start');
button.addEventListener('click', () => console.log('Click'))
// button.addEventListener('click', function (e) {
// // Get mouse position.
// var mouse = robot.getMousePos();
// // Get pixel color in hex format.
// var hex = robot.getPixelColor(mouse.x, mouse.y);
// console.log("#" + hex + " at x:" + mouse.x + " y:" + mouse.y);
// });
}
module.exports = Bot;
The index.html file :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World!</title>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<div class="App">
<div class="Header">
<h1>Checkout-Bot</h1>
</div>
<div class="Wrapper">
<p>Click Start</p>
<button id="start">Start</button>
</div>
</div>
</body>
</html>
Move this line and Bot(); from index.js to index.html:
const Bot = require('./bot')
Change this:
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
});
To this:
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
}
});
Electron has a 'renderer' thread for frontend javascript like button clicks. You can run your Bot code from there if you just include the bot.js file in the bottom of your index.html file:
<script src="./bot.js"></script>
And to allow the use of node you have to set webPreferences.nodeIntegration to true in your browser window:
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
}
})
My assumption is you are preloading that JS file before HTML is rendered therefore there no such button exists to attach an event.
Also, I don't see the Bot method is being called. If you don't call Bot() it's not going to attach anything to your button.
Where do you call it? If you forgot, you should add after the button
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World!</title>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<div class="App">
<div class="Header">
<h1>Checkout-Bot</h1>
</div>
<div class="Wrapper">
<p>Click Start</p>
<button id="start">Start</button>
</div>
</div>
<script>Bot();</script>
</body>
</html>

Unable to load tilesets and maps into my Phaser3 game

I am new to phaser and game development.
I followed the below tutorial.
https://medium.com/#michaelwesthadley/modular-game-worlds-in-phaser-3-tilemaps-1-958fc7e6bbd6
I downloaded and Tiled software and made a simple map with a tileset I got from OpenGameArt.org. Unfortunately, nothing gets loaded on the browser screen, I just see a black rectangle instead of the map. I find no errors in the console. I am running this using XAMPP in Windows 10.
I will paste all my code here, let me know if you find anything wrong.
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/phaser#3.15.1/dist/phaser-arcade-physics.min.js">
</script>
</head>
<body>
<script src="index.js" type="text/javascript"></script>
</body>
</html>
The is the index.js file
const config = {
type: Phaser.AUTO, // Which renderer to use
width: 100, // Canvas width in pixels
height: 100, // Canvas height in pixels
parent: "game-container", // ID of the DOM element to add the canvas to
scene: {
preload: preload,
create: create,
update: update
}
};
const game = new Phaser.Game(config);
function preload() {
// Runs once, loads up assets like images and audio
this.load.image("tiles", "assets/tilesets/GoldBricks.png");
this.load.tilemapTiledJSON("map", "assets/tilemaps/mario.json");
}
function create() {
// Runs once, after all assets in preload are loaded
const map = this.make.tilemap({ key: "map" });
const tileset = map.addTilesetImage("GoldBricks", "tiles");
// Parameters: layer name (or index) from Tiled, tileset, x, y
const belowLayer = map.createStaticLayer("Tile Layer 1", tileset, 0, 0);
}
function update(time, delta) {
// Runs once per frame for the duration of the scene
}
EDIT: Below is the json file
{ "compressionlevel":-1,
"height":100,
"infinite":false,
"layers":[
{
"compression":"",
"data":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUAAAAWAAAAFwAAABgAAAAZAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAVAAAAFgAAABcAAAAYAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAkQAAAJIAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAANgAAADYAAAA2AAAAA==",
"encoding":"base64",
"height":100,
"id":1,
"name":"Tile Layer 1",
"opacity":1,
"type":"tilelayer",
"visible":true,
"width":100,
"x":0,
"y":0
}],
"nextlayerid":2,
"nextobjectid":1,
"orientation":"orthogonal",
"renderorder":"right-down",
"tiledversion":"1.3.2",
"tileheight":32,
"tilesets":[
{
"columns":16,
"firstgid":1,
"image":"..\/..\/..\/..\/..\/Users\/Shashank A C\/Downloads\/Goldbricksandgrass\/GoldBricks.png",
"imageheight":512,
"imagewidth":512,
"margin":0,
"name":"GoldBricks",
"spacing":0,
"tilecount":256,
"tileheight":32,
"tilewidth":32
}],
"tilewidth":32,
"type":"map",
"version":1.2,
"width":100
}
I am also seeing and error in the console now.
Uncaught TypeError: Cannot read property '0' of undefined
at StaticTilemapLayer.upload (phaser.js:74806)
at StaticTilemapLayerWebGLRenderer [as renderWebGL] (phaser.js:122959)
at WebGLRenderer.render (phaser.js:65133)
at CameraManager.render (phaser.js:114533)
at Systems.render (phaser.js:27184)
at SceneManager.render (phaser.js:46818)
at Game.step (phaser.js:109346)
at TimeStep.step (phaser.js:106091)
at step (phaser.js:66488)
UPDATE: Check this file structure --
https://next.plnkr.co/edit/OqywHzLC80aZMGeF
======
Need to see the JSON file to completely understand the issue, but I will just try to speculate. Make sure your JSON file has below settings correctly:
"tilesets":[
{
"image":"path/to/GoldBricks.png",
"name":"GoldBricks"
...
}
]
In some cases Tiled includes wrong/different path to the image file, so make sure to check that part. If there is no image path, embed it in Tiled.
In addition, the name value should match the first parameter of map.addTilesetImage(). Hope it helps!
I had a similar problem myself, the solution was going back to Tiled software and check: 'Embed tileset' on each tileset of the map.
Alright, I asked in the phaser community forum itself and got some help.
The tilemap layer is taller than the game canvas so the visible tiles are out of sight. The solution is to add the below code in the create function.
this.cameras.main.centerOn(800, 1300);

Why Electron spawns a process per each window?

I'm working on electron app with multiple windows. Let say I have the main one and a few child windows.
If I create 20 child windows with google.com open from the main process it spawns around 23 Electron processes(one per each window + GPU process + something else) and consumes around 800 MB in total of memory on my Windows 10 machine. Which is obviously a lot.
const {app, BrowserWindow} = require('electron')
let mainWindow
const webPreferences = {
sandbox: true
};
function createWindow () {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences
})
mainWindow.loadFile('index.html')
for (var t = 0; t < 20; t++) {
const childWindow = new BrowserWindow({
webPreferences
})
childWindow.loadURL('https://google.com')
}
}
app.on('ready', createWindow)
Task Manager with 23 Electron processes
I know this is the way Chromium works - each tab is a separate process so if one is broken the whole browser and other tabs are alive. I have no doubt about that but I've noticed one interesting thing. If I use native window.open as described here it mysteriously spawns only 4 processes. Somehow it combines all "window" processes into a single one + GPU + something else which consumes 400 MB in total which is much better result.
const {app, BrowserWindow} = require('electron')
let mainWindow
const webPreferences = {
sandbox: true // without sandboxing it spawns 23 processes again :(
};
function createWindow () {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences
})
mainWindow.loadFile('index.html')
mainWindow.webContents.on('new-window', (event, url, frameName, disposition, options) => {
event.preventDefault()
const win = new BrowserWindow({
...options,
show: false,
webPreferences
})
win.once('ready-to-show', () => win.show())
if (!options.webContents) {
win.loadURL(url) // existing webContents will be navigated automatically
}
event.newGuest = win
})
}
app.on('ready', createWindow)
And index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
<script>
for (var t = 0; t < 20; t++) {
window.open('https://google.com');
}
</script>
</body>
</html>
Task Manager with 4 Electron processes
Is there any way to have only single process for all child windows if I create them from the main process(first snippet)? It would be great if someone could explain why it works that way.
P.S. I'm using electron fiddler with Electron 6.0.2 runtime to run these snippets
Update: affinity is being removed, see https://github.com/electron/electron/pull/26874.
The affinity option does the trick. Windows with the same affinity will be gathered together in a single process.
More details on this feature could be found here
https://github.com/electron/electron/pull/11501
and here
https://electronjs.org/docs/api/browser-window#new-browserwindowoptions

Prevent white flash between page loads electron

Each time the window starts to loads new html or makes a makes request to the server the Window will go white until the page has finished loading or server has responded to the request. This does not look good at all and can be quite jarring.
How can I stop this?
The code if you wish to see it app.js
const {app, BrowserWindow} = require('electron');
const path = require('path');
const url = require('url');
let win;
function createWindow () {
// Create the browser window.
win = new BrowserWindow({width: 800, height: 600});
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}));
win.on('closed', () => {
win = null;
})
}
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (win === null) {
createWindow()
}
});
inedx.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body style="background-color: #222222">
Click on me to see a flash
</body>
</html>
As far as I have seen (like here: 4 must-know tips for building cross platform Electron apps) setting the background color of the window is the typical way to at least mitigate the "flash". Perhaps you could get fancy with a CSS transition to fade out the window content before loading and then fade it in once the new content has loaded?
From that site:
2.1 Specify a BrowserWindow background color If your application has a non-white background color, make sure to specify it in your
BrowserWindow options. This won't prevent the square-of-solid-color
while your application loads, but at least it doesn't also change
color halfway through:
mainWindow = new BrowserWindow({
title: 'ElectronApp',
backgroundColor: '#002b36',
};
2.2 Hide your application until your page has loaded: Because we're actually in the browser, we can choose to hide the windows until we
know all our resources have been loaded in. Upon starting, make sure
to hide your browser window:
var mainWindow = new BrowserWindow({
title: 'ElectronApp',
show: false,
};
Then, when everything is loaded, show the window and focus it so it
pops up for the user. You can do this with the "ready-to-show" event
on your BrowserWindow, which is recommended, or the
'did-finish-load' event on your webContents.
mainWindow.on('ready-to-show', function() {
mainWindow.show();
mainWindow.focus();
});

Categories