THREE is not defined; how do I fix this? - javascript

I am currently experimenting with Three.js but I can't seem to fix this error, I've tried and searched for a lot of answers but I cant fix it.
I've included the threejs library
and in my script everything is written just fine
This is my html index file
<body>
<script src="script.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/242637/TrackballProjectorDetector.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/242637/AsciiEffect.js"></script>
</body>
This is some part of the script file
function init() {
var width = window.innerWidth || 2;
var height = window.innerHeight || 2;
container = document.createElement('div');
document.body.appendChild(container);
var info = document.createElement('div');
info.style.position = 'absolute';
info.style.top = '20px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'Drag to change the view';
container.appendChild(info);
camera = new THREE.PerspectiveCamera(70, width / height, 1, 1000);
camera.position.y = 150;
camera.position.z = 500;
controls = new THREE.TrackballControls(camera);
scene = new THREE.Scene();
var light = new THREE.PointLight(0xffffff);
light.position.set(500, 500, 500);
scene.add(light);
var light = new THREE.PointLight(0xffffff, 0.25);
light.position.set(-500, -500, -500);
scene.add(light);
sphere = new THREE.Mesh(new THREE.SphereGeometry(200, 20, 10), new THREE.MeshLambertMaterial());
scene.add(sphere);
I get an error on the line:
camera = new THREE.PerspectiveCamera(70, width / height, 1, 1000);
But when I remove it, the error goes down to the next THREE element.

<script src="script.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r79/three.min.js"></script>
I'd say the order may be important here. If the init function is run when loading script.js(a), THREE will not yet have been defined, since that would happen on the following line.
The solution, in that case, would be to load three.js before your script file.
(a) This is often done at the end of a js file but we can't be sure in this case, since we don't have the entire file. Hence I'd be looking at that file to see if it's something like:
function init() {
blahBlahBlah();
}
init();

Related

How do I fix my html/javascript code to animate a sprite sheet?

I attempted to animate a sprite sheet using html and javascript to no avail. Here is my sprite sheet
Below is lines 36-59 of my code. I'm not getting any errors so I don't really know what's wrong. How do I fix/improve my code?
This is for a project I'm doing. I've tried using different methods I've found online but none really worked either. I've tried shifting the image as well.
<html>
<head>
<title>Tree Animation</title>
</head>
<body>
<canvas id='canvas'></canvas>
<script>
var canWidth = 400;
var canHeight = 100;
//position where the frame will be drawn
var x = 0;
var y = 0;
var srcX;
var srcY;
var sheetWidth = 230;
var sheetHeight = 79;
var frameCount = 5;
var width = sheetWidth/frameCount;
var height;
var currentFrame = 0;
var tree = new Image();
tree.src = "tree sprite.jpg"
var canvas = document.getElementById('canvas');
canvas.width = canWidth;
canvas.height = canHeight;
var ctx = canvas.getContext('2d');
function updateFrame(){
currentFrame = ++currentFrame%frameCount
srcX = currentFrame*width;
srcY = 0;
ctx.clearRect(x, y, width, height);
}
function draw(){
updateFrame();
}
setInterval(function(){
draw();
}, 100);
</script>
</body>
</html>
I expect the output to be an animation of a tree growing, but instead I'm getting a blank page.
you should provide more code or a snippet, there are several variables didn't show up in your code
and it's hard to debug your code if u use setInterval, you should make sure your code can work first.
maybe you can try step by step:
draw the whole img on the canvas first. if it works, go next
invoke your draw() function manually, check if the img drawed
invoke more, such assetTimout(draw, 1000), check the result
ok, and i think you can console.log these variables in draw

Is there a way to avoid letterboxing with canvas scaling?

I'm working on a small project in Javascript, using Pixi.js as the rendering engine. However, I've only found a few methods of scaling the canvas to full window that seem to work best for the current version. It does have a caveat, however, in that it produces letterboxes on the sides based on the orientation.
Is it possible to avoid the letterboxing at all with Pixi?
This is the code that I have so far, as it relates to the scaling:
var application = null;
var GAME_WIDTH = 1060;
var GAME_HEIGHT = 840;
var ratio = 0;
var stage = null;
application = new PIXI.Application(
{
width: GAME_WIDTH,
height: GAME_HEIGHT,
backgroundColor: 0x00b4f7,
view: document.getElementById("gwin")
});
stage = new PIXI.Container(true);
window.addEventListener("resize", rescaleClient);
function rescaleClient()
{
ratio = Math.min(window.innerWidth / GAME_WIDTH, window.innerHeight /
GAME_HEIGHT);
stage.scale.x = stage.scale.y = ratio;
application.renderer.resize(Math.ceil(GAME_WIDTH * ratio), Math.ceil(GAME_HEIGHT * ratio));
}
My goal with this is to achieve a similar full screen/window effect to Agar.io/Slither.io, however I have not discovered a satisfactory method that allows it easily. There do seem to be examples that use Pixi to achieve this, but the code is more then often closed source, and they seem to use external tools such as Ionic and Phonegap.
I finally found the answer. I was close to the right track, but a few more things needed to be applied.
application.renderer.view.style.position = "absolute";
application.renderer.view.style.display = "block";
application.renderer.autoResize = true;
application.renderer.resize(window.innerWidth, window.innerHeight);
This sets some additional things internally, while a minor modification to the resize script...
ratio = Math.min(window.innerWidth / GAME_WIDTH, window.innerHeight / GAME_HEIGHT);
stage.scale.x = stage.scale.y = ratio;
renderer.resize(window.innerWidth, window.innerHeight);
configures things correctly, so that the related Renderer window now fills the screen without squashing the content.
This was not easy to discover. So many tutorials just leave it at the first half, and assume that is what people wish to do.
var application;
//var GAME_WIDTH = window.screen.width-20;
var GAME_WIDTH = window.innerWidth;
//var GAME_WIDTH = document.body.clientWidth;
var GAME_HEIGHT = window.innerHeight;
var ratiox = 0;
var ratioy = 0;
var container;
application = new PIXI.Application(
{
width: GAME_WIDTH,
height: GAME_HEIGHT,
backgroundColor: 0x00b4f7,
view: document.getElementById("gwin")
});
//document.body.appendChild(application.view);
container = new PIXI.Container(true);
application.stage.addChild(container);
window.addEventListener("resize", rescaleClient);
function rescaleClient()
{
//ratiox = Math.min(window.innerWidth / GAME_WIDTH, window.innerHeight / GAME_HEIGHT);
application.stage.scale.x = ratiox = window.innerWidth / GAME_WIDTH
application.stage.scale.y = ratioy = window.innerHeight / GAME_HEIGHT;
application.renderer.resize(Math.ceil(GAME_WIDTH * ratiox), Math.ceil(GAME_HEIGHT * ratioy));
}
#viewport{
width:device-width
}
body {
padding :0px;
margin:0px
}
<script src="https://pixijs.download/v4.6.2/pixi.min.js"></script>
<canvas id="gwin"></canvas>

Weird behavior with canvas Context variable definition location causing canvas render freeze when tab is inactive

I have come across a very odd behavior that is causing issues in Chrome (only tested browser). I have a canvas that is being used to render an audio frequency spectrum visual. Whenever I define the CanvasRenderingContext2D variable
var canvasCtx;
canvasCtx = canvas.getContext("2d");
or define the ScriptProcessorNode variable
var scriptNode;
scriptNode = audioCtx.createScriptProcessor(2048, 1, 1);
and the variable definition is inside any closure or function, the visualization rendering will freeze if you switch tabs, change windows, or even change the window width size.
However, I found out that if the variable definition for those two types are defined at the global scope outside all functions, the canvas will continue to render even if the page is inactive.
Here is a JSFiddle demonstrating the bug:
http://jsfiddle.net/K8J26/541/
(Audio may not play in JSFiddle due to cross-origin safety, so a local file may be needed)
I am wondering, why is this happening?
Does the browser hold onto the state of variables and objects that are tied to the global scope even if the page is inactive? Or is it something completely unrelated to the location of variable definition, and instead something I just completely overlooked?
Thanks!
Your problem seems to be that you are calculating the new size and creating the gradient while the browser has not updated the size of your elements yet.
Pass the updateScale in a requestAnimationFrame call so the browser has the time to render the elements :
(function initVisualizer() {
var AudioContext = window.AudioContext || window.webkitAudioContext;
if (!AudioContext) {
return;
}
var PERCENT_HIGH_FREQ_TRIM = 0.3;
var PERCENT_HEIGHT_OF_WITDH = 0.25;
var SMOTHING_CONSTANT = 0.6;
var audioCtx = new AudioContext();
var canvas = document.getElementById("visualizer");
canvas.style.width = "100%";
// Defining canvasCtx here causes frozen canvas rendering when tab is inactive
var canvasCtx = canvas.getContext("2d");
// Defining scriptNode here causes frozen canvas rendering when tab is inactive
var scriptNode = audioCtx.createScriptProcessor(2048, 1, 1);
scriptNode.connect(audioCtx.destination);
var analyser = audioCtx.createAnalyser();
analyser.smoothingTimeConstant = SMOTHING_CONSTANT;
analyser.connect(scriptNode);
var widthMax;
var heightMax;
var dataCount;
var barWidth;
var barOffset;
var gradient;
scriptNode.onaudioprocess = function() {
var frequencyData = new Uint8Array(dataCount);
analyser.getByteFrequencyData(frequencyData);
canvasCtx.clearRect(0, 0, widthMax, heightMax);
canvasCtx.fillStyle = gradient;
var modifier = heightMax / 255;
for (var i = 0; i < dataCount; i++) {
var value = ~~(frequencyData[i] * modifier);
canvasCtx.fillRect(i * (barWidth + barOffset), heightMax - value, barWidth, heightMax);
}
};
window.addEventListener("resize", function() {
if (canvas.parentElement.offsetWidth !== widthMax) {
requestAnimationFrame(updateScale);
}
});
function updateScale() {
widthMax = canvas.offsetWidth;
heightMax = ~~(widthMax * PERCENT_HEIGHT_OF_WITDH);
var size = nearestPow2(~~(widthMax / 4));
dataCount = ~~((size / 2) * (1 - PERCENT_HIGH_FREQ_TRIM));
var rectWidth = widthMax / dataCount;
barOffset = rectWidth * 0.25;
barWidth = rectWidth - barOffset;
analyser.fftSize = size;
canvas.setAttribute("width", widthMax);
canvas.setAttribute("height", heightMax);
gradient = canvasCtx.createLinearGradient(0, 0, 0, heightMax);
gradient.addColorStop(1, "#ff6600");
gradient.addColorStop(0, "#ffff00");
}
function playAudio(audio) {
var sourceNode = audioCtx.createMediaElementSource(audio);
sourceNode.connect(analyser);
sourceNode.connect(audioCtx.destination);
console.log(audio.play());
setTimeout(function() {
audio.pause();
}, 30000);
}
function nearestPow2(size) {
return Math.pow(2, Math.round(Math.log(size) / Math.log(2)));
}
updateScale();
playAudio(document.getElementById('audio'));
})();
body {
background: #222;
}
<audio id="audio" controls crossorigin="anonymous">
<source src="https://upload.wikimedia.org/wikipedia/en/d/dc/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg" />
<source src="https://upload.wikimedia.org/wikipedia/en/d/dc/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg" />
</audio>
<canvas id="visualizer"></canvas>
However I don't know why it was working when you set the variable in global context...
Ps : your fiddle wasn't working on FF and only worked on chrome because of a bug, you need to set the crossorigin attribute before the resource are loaded, otherwise it has no effect.

object has no method onFrame

sorry for what is probably a really dumb question but I am trying to learn how to use KineticJS and am trying to modify a tutorial (http://www.html5canvastutorials.com/labs/html5-canvas-star-spinner/) to use a static image instead of a shape. For what it's worth, I'm trying to animate a PNG of Glenn Beck's head to make it spin (neither here nor there really).
I've muddled through a bunch of errors so far but I keep getting stuck with "Uncaught TypeError: Object# has no method 'onFrame'"
I've read multiple questions about objects/methods here on SO and other sites and while I think I understand what the problem is, I'm not sure how to fix it:
object Object has no method
JavaScript object has no method
contains is object has no method?
From what I understand, the "no method" errors mean there is no function available to be called..? Surely "onFrame" exists inside Kinetic, though..? I tried looking through the Kinetic docs to see if they changed the name between 3.8.X (the tutorial) and 4.X (the library I am using) but it doesn't appear as though they did.
Here is my code:
<head>
<script src="http://test.XXXXX.com/js/kinetic-v4.3.2.js"></script>
<script>
function animate(animatedLayer, beck, frame){
var canvas = animatedLayer.getCanvas();
var context = animatedLayer.getContext();
// update
var angularFriction = 0.2;
var angularVelocityChange = beck.angularVelocity * frame.timeDiff * (1 - angularFriction) / 1000;
beck.angularVelocity -= angularVelocityChange;
if (beck.controlled) {
beck.angularVelocity = (beck.rotation - beck.lastRotation) * 1000 / frame.timeDiff;
beck.lastRotation = beck.rotation;
}
else {
beck.rotate(frame.timeDiff * beck.angularVelocity / 1000);
beck.lastRotation = beck.rotation;
}
// draw
animatedLayer.draw();
}
window.onload = function(){
console.log('stage =', stage); // DEBUG
var stage = new Kinetic.Stage({ container: "container", width: 240, height: 320 });
console.log('stage =', stage); // DEBUG
var backgroundLayer = new Kinetic.Layer();
var animatedLayer = new Kinetic.Layer();
var beck = new Image();
beck.onload = function() {
var beck = new Kinetic.Image({
x: 240,
y: stage.getHeight() / 2 - 59,
image: beckHead,
width: 150,
height: 230
});
beckHead.src = "http://test.XXXXX.com/i/beckhead.png";
animatedLayer.add(beck);
};
stage.on("mousedown", function(evt){
this.angularVelocity = 0;
this.controlled = true;
});
// add listeners to container
stage.on("mouseup", function(){
beck.controlled = false;
}, false);
stage.on("mouseout", function(){
beck.controlled = false;
}, false);
stage.on("mousemove", function(){
if (beck.controlled) {
var mousePos = stage.getMousePosition();
var x = (stage.width / 2) - mousePos.x;
var y = (stage.height / 2) - mousePos.y;
beck.rotation = 0.5 * Math.PI + Math.atan(y / x);
if (mousePos.x <= stage.width / 2) {
beck.rotation += Math.PI;
}
}
}, false);
stage.add(backgroundLayer);
stage.add(animatedLayer);
// draw background
var context = backgroundLayer.getContext();
context.save();
context.beginPath();
context.moveTo(stage.width / 2, stage.height / 2);
context.lineTo(stage.width / 2, stage.height);
context.strokeStyle = "#555";
context.lineWidth = 4;
context.stroke();
context.restore();
stage.onFrame(function(frame){
console.log("onFrame fired")
animate(animatedLayer, beck, frame);
});
stage.start();
};
</script>
</head>
<body onmousedown="return false;">
<div id="container"><canvas id="container"></canvas>
</div>
</body>
This is outdated example which uses version 3.8.4
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v3.8.4.js">
, and the current version is > 4.3
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.0-beta2.js"></script>
The current version does not have methods like Stage#onFrame and Stage#start.
You can use this example, http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-rotation-animation-tutorial/ as your base, then add stage.on("mouseup/down/move/out") to catch mouse movement and affect animation.
The perfect answer would be conversion of that old example to the new version one, which I may try in the future.

html5 canvas context .fillStyle not working

Just giving canvas a go for the first time with the intention of creating a game. I have an image displaying but oddly the fillStyle method doesn't seem to be working. ( At least the canvas background is still white in google chrome.)
Note that in my code the canvas var is actually the canvas elements 2d context, maybe that's where i'm getting myself confused? i can't see the problem, would appreciate if anyone else could.
LD24.js:
const FPS = 30;
var canvasWidth = 0;
var canvasHeight = 0;
var xPos = 0;
var yPos = 0;
var smiley = new Image();
smiley.src = "http://javascript-tutorials.googlecode.com/files/jsplatformer1-smiley.jpg";
var canvas = null;
window.onload = init; //set init function to be called onload
function init(){
canvasWidth = document.getElementById('canvas').width;
canvasHeight = document.getElementById('canvas').height;
canvas = document.getElementById('canvas').getContext('2d');
setInterval(function(){
update();
draw();
}, 1000/FPS);
}
function update(){
}
function draw()
{
canvas.clearRect(0,0,canvasWidth,canvasHeight);
canvas.fillStyle = "#FFAA33"; //orange fill
canvas.drawImage(smiley, xPos, yPos);
}
LD24.html:
<html>
<head>
<script language="javascript" type="text/javascript" src="LD24.js"></script>
</head>
<body>
<canvas id="canvas" width="800" height="600">
<p> Your browser does not support the canvas element needed to play this game :(</p>
</canvas>
</body>
</html>
3 notes:
fillStyle does not cause your canvas to be filled. It means that when you fill a shape it will be filled with that color. Therefore you need to write canvas.fillRect( xPos, yPos, width, height).
Wait until your image actually loads, otherwise the rendering may be inconsistent or buggy.
Careful of cross-domain images used in your canvas - most browsers will throw a security exception and stop executing your code.
Wait till image loads as well:
var img = new Image();
img.onload = function() {
handleLoadedTexture(img);
};
img.src = "image.png";
function handleLoadedTexture(img) {
//call loop etc that uses image
};
Or maybe you were just missing
canvas.fill();
after
canvas.drawImage(smiley, xPos, yPos);

Categories

Resources