I am running into some trouble using VueJS and the NPM version of PC. I have this ‘product’ page which will start a playcanvas instance on a specific canvas element. The first time it loads the app it works fine, however if I try to load it again, it restarts the app and doesn’t re-import the component scripts. This lead me into trying to keep the ‘app’ instance alive, but it doesn’t automatically attach to the canvas element again.
I’ve been trying to create a new graphics device on the app but it doesn’t work…
Any ideas ? Preferably one that doesn’t involve keeping the canvas element alive through the whole site
Hi @Ivolutio,
Not much experience with VueJS, but before unloading your first Vue page try calling:
this.app.destroy();
Maybe @Chris can help on this, he was working on a VueJS project recently
It seems to be mainly just an NodeJS thing.
When I do require("./components/cameracontroller")
it then executes pc.createScript()
. But technically I’m destroying the pc/app instance, so when I recreate the app, NodeJS still has cameracontroller
required, so it doesn’t re-run the code.
For now I’ve solved it by wrapping all my script components with
module.exports = () => {
pc.createScript(..)
...
}
and then change the require to execute it as a function:
require("./components/cameracontroller")();
It is not PERFECT, but I guess it works. @Chris if you have any other ideas please let me know
Sorry, I’ve been working on basically an app that uses PlayCanvas all the time, so I don’t have to worry about removing and re-adding the canvas element back in. Sounds like you’re developing engine-only, so I’m not sure if you’ve seen the start script exported PlayCanvas projects come with. I’ll post that below if it helps, but sounds like you have everything working.
(function () {
var CANVAS_ID = 'application-canvas';
var canvas, devices, app;
var createCanvas = function () {
canvas = document.createElement('canvas');
canvas.setAttribute('id', CANVAS_ID);
canvas.setAttribute('tabindex', 0);
// canvas.style.visibility = 'hidden';
// Disable I-bar cursor on click+drag
canvas.onselectstart = function () { return false; };
document.body.appendChild(canvas);
return canvas;
};
var createInputDevices = function (canvas) {
var devices = {
elementInput: new pc.ElementInput(canvas, {
useMouse: INPUT_SETTINGS.useMouse,
useTouch: INPUT_SETTINGS.useTouch
}),
keyboard: INPUT_SETTINGS.useKeyboard ? new pc.Keyboard(window) : null,
mouse: INPUT_SETTINGS.useMouse ? new pc.Mouse(canvas) : null,
gamepads: INPUT_SETTINGS.useGamepads ? new pc.GamePads() : null,
touch: INPUT_SETTINGS.useTouch && pc.platform.touch ? new pc.TouchDevice(canvas) : null
};
return devices;
};
var configureCss = function (fillMode, width, height) {
// Configure resolution and resize event
if (canvas.classList) {
canvas.classList.add('fill-mode-' + fillMode);
}
// css media query for aspect ratio changes
var css = "@media screen and (min-aspect-ratio: " + width + "/" + height + ") {";
css += " #application-canvas.fill-mode-KEEP_ASPECT {";
css += " width: auto;";
css += " height: 100%;";
css += " margin: 0 auto;";
css += " }";
css += "}";
// append css to style
if (document.head.querySelector) {
document.head.querySelector('style').innerHTML += css;
}
};
var reflow = function () {
app.resizeCanvas(canvas.width, canvas.height);
canvas.style.width = '';
canvas.style.height = '';
var fillMode = app._fillMode;
if (fillMode == pc.FILLMODE_NONE || fillMode == pc.FILLMODE_KEEP_ASPECT) {
if ((fillMode == pc.FILLMODE_NONE && canvas.clientHeight < window.innerHeight) || (canvas.clientWidth / canvas.clientHeight >= window.innerWidth / window.innerHeight)) {
canvas.style.marginTop = Math.floor((window.innerHeight - canvas.clientHeight) / 2) + 'px';
} else {
canvas.style.marginTop = '';
}
}
};
var displayError = function (html) {
var div = document.createElement('div');
div.innerHTML = [
'<table style="background-color: #8CE; width: 100%; height: 100%;">',
' <tr>',
' <td align="center">',
' <div style="display: table-cell; vertical-align: middle;">',
' <div style="">' + html + '</div>',
' </div>',
' </td>',
' </tr>',
'</table>'
].join('\n');
document.body.appendChild(div);
};
canvas = createCanvas();
devices = createInputDevices(canvas);
try {
app = new pc.Application(canvas, {
elementInput: devices.elementInput,
keyboard: devices.keyboard,
mouse: devices.mouse,
gamepads: devices.gamepads,
touch: devices.touch,
graphicsDeviceOptions: window.CONTEXT_OPTIONS,
assetPrefix: window.ASSET_PREFIX || "",
scriptPrefix: window.SCRIPT_PREFIX || "",
scriptsOrder: window.SCRIPTS || []
});
} catch (e) {
if (e instanceof pc.UnsupportedBrowserError) {
displayError('This page requires a browser that supports WebGL.<br/>' +
'<a href="http://get.webgl.org">Click here to find out more.</a>');
} else if (e instanceof pc.ContextCreationError) {
displayError("It doesn't appear your computer can support WebGL.<br/>" +
'<a href="http://get.webgl.org/troubleshooting/">Click here for more information.</a>');
} else {
displayError('Could not initialize application. Error: ' + e);
}
return;
}
var configure = function () {
app.configure(CONFIG_FILENAME, function (err) {
if (err) {
console.error(err);
}
configureCss(app._fillMode, app._width, app._height);
// do the first reflow after a timeout because of
// iOS showing a squished iframe sometimes
setTimeout(function () {
reflow();
window.addEventListener('resize', reflow, false);
window.addEventListener('orientationchange', reflow, false);
app.preload(function (err) {
if (err) {
console.error(err);
}
app.loadScene(SCENE_PATH, function (err, scene) {
if (err) {
console.error(err);
}
app.start();
});
});
});
});
};
if (PRELOAD_MODULES.length > 0) {
loadModules(PRELOAD_MODULES, ASSET_PREFIX, configure);
} else {
configure();
}
})();