creating an HTML5 piano roll editor [closed] - javascript

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I am creating a piano roll like interface, one like you might find in a DAW such as ableton, that looks something like this http://www.abletonlife.com/wp-content/uploads/2010/04/midi-track-big.jpg . The grid represents a canvas to draw in notes to be played, the red squares being the notes to play. You double click on an empty space to create a new note, and you can drag the edges to change the length of the note.
I am new to web dev so I am having a bit of trouble seeing what the right architecture for this might be. With my limited knowledge, the following are the architectures I can think of.
1) Rows of horizontal flex-boxes.
display: box;
box-orient: horizontal;
box-flex: 1;
Something like this, http://jsfiddle.net/ZgzNw/.
Pros:
When resizing the browser window, the browser will automatically
handle resizing of the notes and therefore the grid. Resizing of divs/notes also handled easily for zooming in and out and changing quantization values.
All notes in all positions already exist, when double clicking to "create" a new note, all you have to do is change the css for that note (to be red) etc.
Cons:
Since there is a div for every space in the grid, even empty spaces where there is no note to be played, there will be a lot of divs. Can the browser handle thousands of divs? As an extreme example if there is a 32nd note quantization, a song of 200BPM would have 50 measures per minute, take a 10 minutes song, that would be 500 measures. Going back to the jsfiddle example above and setting measures=500 and quant=32, I get the following error in the Chrome Developer tools console after a few seconds "Uncaught RangeError: Maximum call stack size exceeded". This is when creating the divs in that bit of javascript, If I lower the number to around 300 it is able to create the divs, but things become laggy.
2) Create the grid using divs of width=1px for the vertical lines of the grid. Create new note divs on the fly, position them manually (with position: float?) based on the position of the mouse click.
Pros:
Only have a divs for actual note that are on, so don't have the con of method 1) being an issue
Cons:
Have to manually compute everything, Where to place newly created note, zooming in/out means repositioning vertical markers for grids, and calculating new sizes for note divs. This was mostly handled automatically in the method 1.
I'm sure there are a lot more architectures and pros/cons to the two methods I describe, but I've never created any web applications and the extent of my web-dev experience is the tutorials I've done over the last 2 weeks to teach myself.
My question I guess is what is the best architecture for creating this piano roll interface I am describing? Specifically the UI representation, not the backing model.

I would create a simple model (probably just a multi-dimensional array) to contain the representation of the score, where each array item represented a note at a point in time. From the model, you can then draw/redraw accordingly. You could also perform operations like time shifts, quantizing, thinning, etc. by modifying the arrays.
Can the browser handle thousands of divs?
A few thousand, yes, maybe more--maybe even a lot more--but results will greatly vary by browser, by computer, even by the way they are positioned (floats tend to be slower than absolute positioning, for example, because the browser has more to calculate).
Instead, I would research using a canvas and draw/redraw based on your underlying model. You can detect events on the whole canvas, and depending on coordinates, easily map the event to the note(s) to which it corresponds.
KineticJS has some cool examples using a canvas

I would use a background image to represent tracks and measures, and one div for each note. It is not necessary to keep all notes as div’s in the browser, it would work better only to have the div’s for the visible up to 10 measures.
Imho, this should be done fixed-width, and there should not be any resizing of the piano roll at all. So you can use calculation of pixels. I don’t think this will work without making use of Javascript heavily.

Related

Canvas re-drawing gets stucked (performance-problem) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm about to create a GUI for my Raspi-Project. There is Nodejs running on the Raspi3 which runs a NodeJs-Server and a then it gets requested with Chromium in kiosk-mode.
One page of this GUI needs to visualize the states of 48x potentiometers, 12x buttons, 8x faders. The NodeJs-Server sends data (which was modified by user) via websocket to the client, which redraws the whole canvas. Works fine so far for a few elements:
works fine but with a slight delay if you look closer
Now the problem is, that whith the growing number of elements that need to be drawn, the performance drops down to unacceptable dalay-times.
works, but with a way too big dalay, as more elements are drawn
and those are not even the half of stuff that needs to be drawn.
I am confused now, because I read about how fast canvas is, before I decided to go that way, and if I deactivate all canvas-drawings and simply console.log() the data that comes in via websocket, it is fast like in realtime.
so what am I doning wrong? maybe there it would be better not to draw the whole canvas on every value-change but animate the canvas? maybe someone has experience on this?
Here is the code.. when you look into assets/js/menu.class.js, this is the file which generates the canvas. the function createControllerGUI(options) is called every via websocket, every time a value changes.
Canvas is quick, but still cpu intensive. Also speed changes with the platform a bit.
Your function does all the drawing operation each change. Those operations have strokes, fills, center aligned text and something more ( i did not look all in details ).
There are some ways in which you can optimize the drawing operations.
partial redrawing
maybe the most effective.
Keep track of where a widget is, keep track of what data changed from message to message and draw only the differences.
Use clearRect on the area occupied by the widget and redraw it. Do not touch the other pixels.
Unless an octopus is using the hardware, you will have 2 or 3 widget changing per frame at maximum.
stroke all at once.
Instead of stroking on a per widget basis, you can trace all the paths you need at once, using a moveTo to the new position when changing widget, and using a single stroke operation at the end of the loop.
caching
If you have some rotatory controls for example, you can draw them once on a small separate canvas, and use that canvas as a source image to be drawn at a different angle if you need to represent a rotated control.
DrawImage is often optimized with hardware operations while the single fill and stroke may not.
There are probably other ways, and you can look at high level libraries that can do this for you, exposing a widget logic instead of the low level drawing operations.

Javascript - Large number of rendered objects

I'm building a web app based on javascript/jQuery and php, and I need to render and manage (e.g. have the user drag/drop, resize, etc) a large number (20,000+) of drawn objects on a web page and am looking for a recommendation in terms of approach/libraries to use, mainly to get an idea of how to do this whilst keeping page performance acceptable.
The objects are simple geometric shapes (rectangles, circles, squares, etc) that I will need to attach event handlers to and be able to move/re-size. Shape attributes will be based on properties of javascript objects and I'll need to change the shapes based on the javascript object properties and vice versa.
The canvas area is likely to be quite large (not sure if this will affect performance?) although not all objects will be 'visible' on the page, but must be able to scroll within a div (using overflow, etc) around the full canvas. I have built something for test purposes using jQuery SVGDOM which works well when I have a couple of hundred objects, but the page grinds to a halt when I go over 1000 objects.
What I like about svgdom is the way it fits nicely with jQuery for referencing the DOM objects (for event handlers, etc), but am willing to (try to) develop more complex code if I need to in order to be able to address the larger number of objects that svgdom doesn't seem happy with from a performance perspective.
Any suggestions for how to do this?
I think you need to look into webGL, which renders using the GPU. A good framework for that is three.js.
Still, to manage your expectations: making 20k objects interactive really a big challenge and might need some smart caching system to fake it. if you target mobile devices too, I would say your goal is way too ambigious. I am sometimes already happy if 100 objects run/move smooth.
I'm taking as the answer to my original question that it is not practical to display/manage the number of objects that I need on a single page whether SVG or directly to the canvas.
So my approach must be to reduce the number of objects displayed at any given time - now I just need to figure out what the best way to do this is...

Canvas vs CSS3 for Web Application

A very common question, but almost all comparison I've seen is mainly focused on games with a lot of interaction.
What I'll be working on is a web application that manipulate objects one at a time. For example, the object can be either an image or a text, then it can be replaced, resized, rotated, zoomed in, and deleted.
If the manipulations applied to many objects, I know that canvas will be a better choice but here the manipulation only can be done one at a time to one object only. Each container will at most have about 30 object in it, and I'll be working on multiple containers (maybe around 20 containers) that will be hidden or shown depends on the interaction.
The question is whether to use Canvas or CSS3? What I'm looking is the performance issue and complexity of the app.
I don't have a lot of experience with canvas but as far as I know if you use it together with requestAnimationFrame the performance is pretty similar to CSS animations. You should also consider that CSS animations are very limited when it comes to working with complex animations.

Canvas vs DOM for a chess board [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I'm creating an HTML 5 chess game. Server side is socket.io / node.js / backbone.js.
I'm now beginning to write the view for the game board. Would it be easier to represent a chess board in canvas or DOM elements (aka divs)? Disregard browser compatibility.
Really comes down to your motives.
If you know game developement well, and you're comfortable with dividing screens into segments for purposes of collision-detection or otherwise, and you can easily create your own custom click events, per square/unit, based on where on the canvas the player clicked, then go with the canvas, as you'll open more doors to advanced animations and graphical-interactions that way.
If you aren't comfortable with that, and would like a straightforward way of knowing which square was clicked, and would like a clean-cut way of knowing if there was a unit in the square you landed on, without having to figure it out based on the X and Y where you clicked inside the game window, then go with the DOM -- really, those are the benefits and most everything else is a side-effect of picking one or the other.
Canvas for animation and "polish", DOM for event-listeners and array-based (or attribute-based) notification of square clicked.
For what you're planning to do, I think DOM would be the best option. Not because Canvas has any drawbacks, but for just based on the amount of work you'd need to be done, and the ability to change how the board looks easily.
You can use divs and place them absolutely, add css styles to show/hide pieces on a certain square, and after all that, you can even make a large background-less canvas and draw special effects on top of the DOM based chess board.
So all in all, DOM should be the way to go for you.
It depends on your goals.
If your main interest is just to visualize the state of the game by rendering icons for the pieces as images then using the DOM (e.g. tables or divs) for board locations is probably easiest.
If your are more interested in advanced graphicals then canvas might be better.
I've developed one of those quite recently and used HTML5 Canvas for graphical interface. It was extremely powerful for drawing the board and moving the pieces.

I have a couple thousand javascript objects which I need to display and scroll through. What are my options?

I'm working off of designs which show a scrollable box containing a list of a user's "contacts".
Users may have up to 10,000 contacts.
For now assume that all contacts are already in memory, and I'm simply trying to draw them. If you want to comment on the question of how wise it is to load 10k items of data in a browser, please do it here.
There are two techniques I've seen for managing a huge list like this inside a scrollable box.
Just Load Them All
This seems to be how gmail approaches displaying contacts. I currently have 2k contacts in gmail. If I click "all contacts", I get a short delay, then the scrollable box at the right begins to fill with contacts. It looks like they're breaking the task into chunks, probably separating the DOM additions into smaller steps and putting those steps into timeouts in order to not freeze the entire interface while the process completes.
pros:
Simple to implement
Uses native UI elements the way they were designed to be used
Google does it, it must be ok
cons
Not totally snappy -- there is some delay involved, even on my development machine running Firefox. There will probably be quite a lot of delay for a user running a slower machine running IE6
I don't know what sort of limits there are in how large I can allow the DOM to grow, but it seems to me there must be some limit to how many nodes I can add to it. How will an older browser on an older machine react if I ask it to hold 10k nodes in the DOM?
Draw As Needed
This seems to be how Yahoo deals with displaying contact lists. The create a scrollable box, put a super-tall, empty placeholder inside it, and draw contacts only when the user scrolls to reveal them.
pros:
DOM nodes are drawn only as needed, so there's very little delay while loading, and much less risk of overloading the browser with too many DOM nodes
cons:
Trickier to implement, and more opportunity for bugs. For example, if I scroll quickly in the yahoo mail contact manager as soon as the page loads, I'm able to get contacts to load on top of one another. Of course, bugs can be worked out, but obviously this approach will introduce more bugs.
There's still the potential to add a huge number of DOM nodes. If the user scrolls slowly through the entire list, every item will get drawn, and we'll still end up with an enormous DOM
Are there other approaches in common use for displaying a huge list? Any more pros or cons with each approach to add? Any experience/problems/success using either of these approaches?
I would chunk up the DOM-writing into handle-able amounts (say, 25 or 50), then draw the chunks on demand. I wouldn't worry about removing the old DOM elements until the amount drawn gets quite large.
I would divide the contacts into chunks, and keep a sort of view buffer alive that changes which chunks are written to the DOM as the user scrolls through the list. That way the total number of dom elements never rises above a certain threshold. Could be fairly tricky to implement, however.
Using this method you can also dynamically modify the size of chunks and the size of the buffer, depending on the browser's performance (dynamic performance optimization), which could help out quite a bit.
It's definitely non-trivial to implement, however.
The bug you see in Yahoo may be due to absolutely positioned elements: if you keep your CSS simple and avoid absolutely/relatively positioning your contact entries, it shouldn't happen.

Categories

Resources