HTML5 Canvas drawing and updating - javascript

Sorry for how vague the title is, but I'm not completely sure how to sum up what I'm trying ask.
First off, here is a jsFiddle of what I have so far.
I'm just starting off learning to use the HTML5 canvas element, as well as using js OOP.
As you can see from the fiddle, I create a rectangle class (so that I may create as many squares as possible, although I think that may be redundant), and reference it to draw. However, when I set the height = width, I always end up with a non-square. I'm relatively new to using the canvas, but I assume thats because the square's height and width are relative to the size of the canvas element, and so the canvas element's height and width must not be proportional (since their assigned percent values as opposed to definite pixels).
I can fix this by setting the size of the square to pixels, but then when my keypress event is called, the square doesn't move at all.
Also, I have the keypress event so that a user can move the square with the arrow keys. However, the up/down keys values seem to be inverted, even when I flip-flop them in the code? And the left/right keys don't do anything?
And, I also can only make the square move up/down once? Shouldn't my code allow me to increase my x/y values as long as the user keeps pushing the corresponding buttons?
If someone could check this out and give me some pointers as to what I'm doing wrong, that would be great! I'm trying a lot of new things with this, as its just a learning experience, so if you feel so inclined, help me learn!

You experienced a thing that often goes wrong with resizing a canvas - trying to use CSS for it. Using CSS for canvas drawing will scale it - not changing the resolution. For setting the resolution, use the width= and height= attributes in HTML.
As for the movements, it appears that keyup works better. However, for the up key, the y would decrement (top is 0, bottom is something positive).
A few other things I'd like to highlight.
Using canvas as a variable name for the context is a little ambiguous. There is a difference between the canvas and its context used for drawing.
Also, you state //browser doesn't support html5 if ctx does not exist. However, in case the browser does not support canvas/HTML5, the .getContext('2d') function call will fail already because it's not a function in that case. Your else statement will only get executed if the function does exist but does not return something. That will probably never be the case.
Empty else loops aren't very useful either, but that doesn't hurt :)
http://jsfiddle.net/DqrEm/4/

Your problem isn't with the size of your square, but with how you size your canvas. In your jsfiddle, when I changed the canvas starting line to <canvas id="practice" width="500" height="500"> the square was drawn properly. I tried changing the width and height in the CSS from 100% to 500px but the square was still drawn incorrectly.
Update: Setting the width and height to 100% in the actual canvas tag(i.e <canvas id="practice" width="100%" height="100%">) works too.

Related

SVG canvas size limitations

Problem
I was planning on using SVG as an infinite canvas on which I can move around using viewBox.
Turns out that when the viewbox reaches a specific sweetspot, the shapes start disappearing.
Example
Watch how the shapes always stay inside of the view box, until the viewbox passes the sweetspot:
Live reproduction
It's as if SVG has a limitation mismatch where the viewbox can keep running freely, but shapes can only render within specific bounds.
Research
Furthermore, the sweetspot is different between browsers:
On Chrome it's 33554399.
On Firefox it's 17895590.
The same happens on the other direction. Apply a minus sign to the above values and the shapes disappear on the other side of the canvas.
My best guess is that the browser implementation of SVG is internally constrained by something parallel to Number.MAX_VALUE (but is significantly lower).
However, I couldn't find any relevant documentation on the subject.
Question
Any way to fix or work around this? I'm hoping to keep my current implementation and not simulate the viewbox on my own.

(Three.js) Bloom effect performance

It has 50-60fps, if there is no bloom effect.
renderer.render( scene, camera );
Then, just have 10fps after added bloom effect.
camera.layers.set( BLOOM_SCENE );
bloomComposer.render();
camera.layers.set( ENTIRE_SCENE );
finalComposer.render();
How can i fix it? demo link is here
https://codepen.io/anson-chan/pen/QXeKqm?editors=1010
There are a few different problems here.
You have a LARGE number of cubes in your scene. Each cube is a unique material and drawCall. To keep a scene fast, you want to keep the number of drawcalls around 500 or so, and the number of polygons at or below around 1.5 million.
This is called being "draw call bound".
There are some strategies for dealing with this... such as using hardware instancing and/or a library like THREE.BAS to do instancing of your cubes. These techniques can render LARGE numbers of objects with a single draw call, and may help you.
(https://github.com/zadvorsky/three.bas)
(http://three-bas-examples.surge.sh/examples/instanced_prefabs/)
Next up:
your resize handler is always resizing to the bounds of the window.. not the size of the actual canvas. You are also NOT resizing the actual renderPasses in your code. Each pass that has a width/height parameter also needs to be resized, along with the effectsComposer itself, and presently always resizing to the size of the window.. not the size of the actual canvas area your are rendering.
Instead, try something like renderer.resize(renderer.domElement.width,renderer.domElement.height,false) Then control the canvas resizing via css rules, and then make sure your blurPass size is set, and the effectsComposer size is also set. The 'false' parameter on the resize method prevents THREE from setting the width/height of the canvas style, and allows you to control it explicitly. Otherwise, you can have problems of your size changing triggering additional resizes when THREE tries to change the CSS of the canvas to the new width/height you're passing.
This problem is causing you to render a full window sized canvas and effects pass no matter what the display size it.
The next issue is that blur/bloom is an inherently costly operation.. since it requires scaling down the entire framebuffer a few times to generate the blurred/bloomed version of the effect. This is compounded by the sizing problem mentioned above ^
Next up... I don't know what hardware you are running on, but if it's a retina display.. your devicePixelRatio will be greater than 1, in which case it further compounds the display sizing problems, since on a retina display, a devicePixelRatio of 2 will cause the renderer to render 4x as much as a devicePixelRatio of 1. You may want to consider using 1 instead of whatever you get from window.devicePixelRatio.
All of these issues compound each other. GPU's can only do so much, so you have to be clever how you manage them and what kind of loads you place on them.
Hope this helps.

Render scene at lower resolution (three.js)

How can i decrease my rendered canvas resolution(just like i can do on blender camera resolution)? I've seen another question saying that i need to use
renderer.setDevicePixelRatio(window.devicePixelRatio)
The problem is that the object either gets black or nothing shows on canvas, so i don't really know if this is it solves my problem.
I also tried to use
renderer.setSize()
and
renderer.setViewport()
together and separately, but it only changed the canvas size to a very small one(i need a high size preview of the canvas), and even though the viewport got on the size i wanted, it seems that the objects are rendered only on the smaller size, so i can't see all of it, so it doesn't do the trick.
Also, if possible, is there a way to do that by manually changing the image buffer to a lower resolution one, and displaying it?
The thing i needed was the setPixelRatio function on therenderer. no setDevicePixelRatio.

Positioning elements of different heights

Sorry for the vague title, but I'm not exactly sure what to call this. I'm making an assignment planner using HTML and JavaScript, and I've ran into a bit of a problem while trying to make a feature to snap your text to the nearest line.
The planner itself looks like this
The "Snap to Line" feature works by checking the Y coordinate of the note (which is an input element) and checking the nearest line. I know it's not good practice, but to make it easier everything is a fixed size, so I have an array of every line's Y coordinate it could snap to:
[58,80,102,124,146,168,190,212,234,257,279,301,323,345,367,389,411,434,458,480,502,524,546,568,590,612]
When the user creates a note or change's its position, this bit of code runs:
let height = parseInt(window.getComputedStyle(e.target).getPropertyValue('height'));
e.target.style.top = getClosest(yCoord+(height/2))-(height/2)
So it gets the element's height, then finds the Y coordinate of the closest line and subtracts half the height of the element to find the proper coordinates.
I arbitrarily used height/2 as opposed to height. I thought that since the coordinate is of the line, it would need to be exactly height higher up, which makes perfect sense, but in practice for whatever reason that didn't work, and height/2 was able to give me better, somewhat better results.
However, if I use the function, it doesn't exactly work. I've tried many different methods but I can't seem to figure it out. This is the result. As you can see, it works pretty well for smaller heights, but it's as if there's an offset relative to the height of the element that affects the position. Is the problem because my method is terribly wrong? (probably) Or is there just some factor that I've been forgetting?
There aren't any borders, no margins, the padding is only 1px, but that shouldn't matter anyway since I use getComputedStyle (which I believe takes everything into account) to find the height and not the font size.
The code surrounding this feature is only a small part in a decently sized project, but I'm posting the entire document so that it may be easier to fix this.
Thanks!
note: the window with the planner on it is a popup, so your browser might block it
The code (too many characters for this post so it's on pastebin)
EDIT: I think I found the problem, no surprise that I found it just as I posted this. First of all, I needed to use height and not height/2 (no surprise there, makes sense). I though I needed to use height/2 because I was testing with small heights and the snap points were a few pixels off (7, to be exact) which made it seem like height/2 was better. Two, the main problem, is that since I used height instead of font-size, the height was the height of the entire element which meant that the bottom of the P hit the line instead of going past it.

javascript matrix script, inefficient/slow for some reason

I've made a beginning of a script to achieve the "matrix effect" (to use in the background) in JavaScript. I used the Canvas element, but for some reason its kinda slow but i don't know why.
Matrix effect: Those (green) text lines which are scrolling from top to bottom.
script:
http://dominiquedebrabander.nl/matrix/matrix.js
i've linked the script, 'cause its to long for this textarea. I hope you guys know why, or have some tips.
greetings, Dominique
Why are you calling clearRect if you are just gonna fill it with black? Remove that call
Don't set the font over and over if it never changes, just set it once at the start.
drawing text is slow, see my post here. Consider painting every letter to a second invisible canvas and using drawImage to draw parts of that canvas to your real canvas
If you really want it to be done the way you are doing it now it will be much faster if you draw everything to a large offscreen canvas and you just draw that single canvas over and over, but then you wouldn't be able to have the letters fall at different speeds from each other. And it would look more matrix-like if you did that, say put the y at += Math.random()*4.5 (or so) instead of 0.5

Categories