I can see where you say a developer familiar with the DOM is more likely to work with on the canvas api directly. And yes, the more technical options the better. Sure. But I do not see how you can say that an OO vs procedural or functional approach is not that relevant? OO vs procedural/functional is quite the different design approach. I would even say that those are worlds apart. In what way do you think that this difference not relevant?
On Sat, Feb 8, 2025 at 8:53 PM Colin Alworth <[email protected]> wrote: > > @Craig - If you draw everything on the same canvas, the zoom/scale works > on everything on that canvas. it limits what you can do with that canvas. > If you want to scale or zoom everything, yes then it doesn't matter. So yes > you are right, it depends on the project. > > This isn't true, it only applied on the operations that take place while > it is set. You can call scale(1, 1) to go back to 1:1, or you can use the > save()/restore() that Craig mentioned. You can also clip to keep the zoomed > content within certain bounds. > > @Colin - With multiple layers I would also need multiple canvas's and > overlay them right? > > Correct - each would have its own frame buffer, and could be cleared/drawn > independently. > > > We wrote a single adapter widget that uses a single canvas. This adapter > widget knows what the zoom level is. Objects that are drawn on that widget > of a certain type get zoomed, whilst others of a different type do not. It > is super simple and easily explained to new devs. Everyone on the team can > add views or objects and the type determines how these are displayed. Even > devs without exact knowledge of how the canvas works can develop and > maintain objects to be displayed. > > I guess it's also a development style/preference thing. If you code the > view of the canvas in a single class or single method, the solution is > likely to have to rely more on the technological capabilities of the > canvas. Working with an adapter then does not really make a lot of sense. > If you have more of an OO style of development, you express more in > functional blocks. Then you have to rely less on the technical capabilities > as you can translate what needs to be done on the basis of what your > objects are before you hit the canvas. Then the zooming/scaling happens > in the object, not on the canvas so to speak. > So the required functionality of the canvas remains fairly basic. > > I don't make these suggestions lightly - if you are happy with how canvas > performs and the quality of the output, then you may well never need them, > but it can be fun to know they exist. > > I don't much care about OO vs FP styles for this - building an API around > these features should be straightforward within whatever paradigm you > prefer. For most projects we ended up with roughly two layers of > abstractions - the "shapes that get drawn on the screen via canvas > commands" abstraction (iterate through "shapes", respect their "z-index" or > other relative positioning, capture clicks and figure out which "shape" was > clicked on, redraw only changed "shapes" and those that intersect them, > etc), and the "business logic drives what shapes to draw" abstraction ("I > want a pie chart in the corner, compute slices based on data", "these > buttons over here control those axes", "Labeled items in the legend will > drive which stars/circles in the chart are highlighted when hovered"). It > feels natural to someone who is used to working with a DOM (esp SVG), and > can handle thousands of items without much trouble. > > Zoom can appear at either level here - multiple coord systems, or make the > "zoom" part of the "shape" API. You're totally correct that scaling need > not happen at the "canvas level" - while the MDN link I gave seems to imply > that, it really is just trying to make it easier for the developer to not > need to think about one more "layer" of ways that their data needs to be > transformed. From a certain perspective, you might want to just have a > transform matrix that you apply to each shape, and compose your > zoom-because-zoom-widget, translate-because-panning, rotate, etc operations > all at that level, and just apply the transform once when drawing (or even > apply to the coords before you call in to canvas). None of it matters as > long as the math is correct. > > If you need more power, odds are you can find pretty quickly where the > "unnecessary" O(n^2) or O(n lg n) operations are taking place (sorted > insertion by z-index, solving for intersections, etc), and can do a better > job partitioning "shapes" or go all out and drop down to just "business > logic drives canvas commands" where it is required. > > > > performance wise, I've done fully animated person relation networks and > animated dashboards in large canvases for nearly a decade now. > We've never ran into any performance issues. > That being said, I think the views and on-screen actions we used were > somewhat limited when compared to developing a game with full world > rendering or something similar. > > Did I already say I love this gwt group? It makes me think a lot more > about what I am doing and why I am doing it. > Plus the input from the GWT devs usually give me insights I haven't > thought about before or didn't know existed. > > If you can stand the stream of discussion, you may also enjoy > https://matrix.to/#/#gwtproject_gwt:gitter.im. It tends to be more > conversational, and can get into the weeds in unrelated topics like this. > > > On Sat, Feb 8, 2025 at 2:56 AM Colin Alworth <[email protected]> > wrote: > > I'm sorry if my message confused the two kinds of 'zoom' being discussed > here - there's the one where the pixels on the physical monitor don't match > the pixels of your display (this covers both HDPI and ctrl +/-), and > there's the one where the user clicks the + icon (drawn on the canvas) to > make everything inside a specific rectangle bigger. > > The context2d.scale() method can do both, but I was mostly referring to > the first, adapting to the user's current monitor+settings at any given > time. Note that in this context, scale() does _not_ make things blurry when > you zoom, but effectively multiplies all your coordinates by the scale. The > canvas "height" and "width" (the "actual size" in the link's code sample) > are what makes things blurry or super precise. > > In the second case, scale() can still be totally appropriate, especially > if coupled with a "panning" feature, or if data is updating. Odds are very > high that in those cases, the parts of the canvas outside the "rectangle" > aren't moving - all the various controls, the rectangle itself. Avoiding > redrawing whatever you can each frame is important for performance. Or, you > can just adjust your coordinate system when projecting on to the canvas, > multiplying by your current zoom factor for each position - as above, it is > doing the same thing. > > While we're discussing it, clipping (with save/restore or without) still > also be helpful to conserve rewrites too - if you had a single canvas > element, you would clip to inside the rectangle, clear, and redraw only > what is in there - save() and restore() are a valid way of handling that, > or just reapply state at each pass. If you're careful, you could even just > redraw a subset of the rectangle's contents - solve for which items > actually changed (doing some intersection math), and clip+clearRect just > that section, then redraw just what is in there. If you "draw" a little > outside the clip in any of these cases, no big deal - it will get clipped > out (but you'll still pay for the code to run, it just won't have any > overdraw). > > If you think about this like "partitioning" the drawing area with clip, > there are two other ways to partition too - you can "tile" canvases, > selectively redrawing their entire contents if they are affected, and you > can "layer" them, using transparency to enable lower layers or higher > layers to remain intact when other layers need to be cleared and repainted. > Tiling can also work with non-homogenous blocks - the "rectangle" above > could be one canvas, and the "controls" could be in their own. > > On Friday, February 7, 2025 at 5:11:41 PM UTC-6 [email protected] > wrote: > > > *I would not use the scale functionality as it applies to the whole > canvas. * > > Whatever works for your project is best, however, the scale only applies > when you set it. And you can always reset it. Eg: > > // Save the current state > context2d.save(); > > // Apply zoom > context2d.scale(xxx, xxx); > > // Draw zoomed stuff > ... > > // Reset the zoom > context2d.restore(); > > This also lets browsers use the GPU to render (although, I'm not actually > sure if the scaling is done on the CPU or the GPU). > > On Friday, 7 February 2025 at 5:02:17 pm UTC+11 Leon Pennings wrote: > > I would not use the scale functionality as it applies to the whole canvas. > I'd prefer to apply an adapter pattern for determining actual coordinates > on the canvas. > Then you can still have a toolbar, location display or slider for the zoom > factor in it's normal proportions and just have the actual content you want > to show in a different scale. > > Op donderdag 6 februari 2025 om 13:33:12 UTC+1 schreef Colin Alworth: > > No problem - I wanted to be sure I didn't make a mistake, since I haven't > myself used canvas "in anger" in many years, and only loosely keep track of > resources and advice on it. > > SmartGWT's "Draw" examples make the API look very similar to the GXT > "draw" packages - it isn't really a raster API at all, but a vector API > that just happens to be built on top of a canvas implementation. > > My recollection is that for fewer than around 1k-10k drawn items, SVG is > faster and simpler to understand than canvas, and canvas's benefits only > start kicking in when the DOM gets too heavy to manipulate quickly each > frame. Looking briefly at the example page you shared a few weeks ago, if > you were interested in getting into the low level details of how to do the > drawing, your case perhaps could stand being remade in plain SVG - always > high resolution. The benefits may be mostly for your own understanding > rather than any real observed performance improvements from running the > page (that said: dropping SmartGWT would appear to drop almost 8mb of JS > out of your 9+mb page). > > On Wednesday, February 5, 2025 at 9:46:51 PM UTC-6 [email protected] > wrote: > > > Neil, I'm not sure where I appeared to have said that. > > > > I am sorry, I did not intend to put words in your mouth. > > That was my understanding from your previous email stating > that canvas is a raster format. I misinterpreted your statements. > > > > I apologize for that. > > > > Thank you, > > Neil > > > > -- > > Neil Aggarwal, (972) 834-1565, http://www.propfinancing.com > > We offer 30 year loans on single family houses! > > -- > You received this message because you are subscribed to a topic in the > Google Groups "GWT Users" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/google-web-toolkit/E3P4xZ8SFCg/unsubscribe > . > To unsubscribe from this group and all its topics, send an email to > [email protected]. > To view this discussion visit > https://groups.google.com/d/msgid/google-web-toolkit/0e1b79f7-fa2e-482f-899b-65c5e9ca3e72n%40googlegroups.com > <https://groups.google.com/d/msgid/google-web-toolkit/0e1b79f7-fa2e-482f-899b-65c5e9ca3e72n%40googlegroups.com?utm_medium=email&utm_source=footer> > . > > -- > You received this message because you are subscribed to a topic in the > Google Groups "GWT Users" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/google-web-toolkit/E3P4xZ8SFCg/unsubscribe > . > To unsubscribe from this group and all its topics, send an email to > [email protected]. > To view this discussion visit > https://groups.google.com/d/msgid/google-web-toolkit/c66862dd-bcfc-4516-b2bf-c5dc17a73deen%40googlegroups.com > <https://groups.google.com/d/msgid/google-web-toolkit/c66862dd-bcfc-4516-b2bf-c5dc17a73deen%40googlegroups.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "GWT Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/google-web-toolkit/CABjQu7RvSkCYSpSJ67HSZRvxvkJombWT-T%3D6n1hizuBhKy992g%40mail.gmail.com.
