marcus_holmes 10 months ago

> These InteractionHandlers are just objects satisfying a specific TypeScript interface. They’re not coupled to React or hooks or anything like that, which feels quite freeing, honestly. There’s no worrying about stale closures or dependencies or hooks rules - it really is just TypeScript.

This is a great example of "fighting the framework". React + SVG got them from nothing to a working product. But then they had to rewrite completely to solve problems in the product because the framework no longer fit the product. I've seen this so many times.

But it's hard for people to believe when they start out and choose the "perfect" framework for their product:

"you will eventually have to rewrite your entire product because that's easier than fighting the framework to make it do what you need"

"no, we won't, this $framework is flexible enough to do whatever we need"

"OK, good luck"

2 years later:

"we're rewriting the product completely because $framework wouldn't let us do $thing"

Not that I'm advocating for not using frameworks, just for people to realise that eventually (almost) everyone fights the framework and rewrites. And the more the framework does, the earlier the fight begins.

  • dirkc 10 months ago

    I've also seen the other side where the argument is:

    "we should be doing things correctly from the start"

    2 years later:

    "the maintenance of custom doesn't deliver business value and makes recruitment and on-boarding increasingly difficult. We should rewrite in $framework since it's well known, maintained and flexible enough to do whatever they need"

    ...

    • sanitycheck 10 months ago

      There have been a few occasions where this has led to (literally) years of extra maintenance work for me, as I patiently wait for a team of devs to replace my custom app with v2 using $wellKnownFramework. Sometimes that v2 is eventually abandoned and I'm contracted to build v3.

      • marcus_holmes 10 months ago

        Also seen this where the $wellKnownFramework is dumped before v2 is completed, and the whole thing is rewritten in $newHotFramework for no other reason than the dev team wanted to work in $newHotFramework.

        There are lots of anti-patterns around this ;)

  • magpi3 10 months ago

    This in a nutshell is why Visual Basic 6 eventually failed. It worked for your use case until it didn't. And of course a programmer could dive into COM and ActiveX to extend it, but avoiding that mess was why people chose VB6 to begin with.

    • Malic 10 months ago

      I feel the same way about WordPress. If you stick to it's sweet-spot as a solution, it's ... good enough and cheap. But too many folks have this hammer called WordPress and see a world full of nails.

  • sdiupIGPWEfh 10 months ago

    It's almost like there's no silver bullet, and neither management nor engineering are capable of sticking to one set of trade-offs. Instead, the product thrashes back and forth while trying to accommodate whatever the current feature demands happen to be, with no one applying enough higher order thinking to see that there is no end-state that satisfies everything. Just endless busy work, a few more paychecks, and actual value down the drain.

    • hicksyfern 10 months ago

      I would agree with you if it was t for the fact that we’ve seen a big increase in the number of complex maps being made since the change.

      You give people a more powerful product and they’ll use the power.

      • sdiupIGPWEfh 10 months ago

        Glad to hear it's working out! Hope it continues to prove to be an exception to the rule, then.

  • aa-jv 10 months ago

    Anecdotal counter-argument from applying frameworks successfully over decades: the framework is there to help us get up and running .. we get up and running .. we build out the weaker parts of the ship while we're sailing, only when the work in framework no longer applies .. the app grows .. the user base grows .. the framework grows ..

    • marcus_holmes 10 months ago

      > the framework grows ..

      I've seen too many teams fight Rails (in particular) to implement new product features to agree with this. The framework never grows, it stays the same size and eventually becomes a straitjacket for the product.

      Like I said, though, this isn't a reason to not use a framework at the start. As long as everyone realises that at some point it'll need to be rewritten.

      • aa-jv 10 months ago

        Well, thats the case where too much responsibility is being off-loaded onto the framework providers and someone hasn't quite grok'ed TANSTAAFL. I never use a Framework I won't feel comfortable modifying ..

  • klysm 10 months ago

    It's unfortunate that coevolution like this usually lands in a very suboptimal start. If we tore it all down and started from what we knew we'd have much better things. Occasionally stuff like that happens, but it's really hard to fight against the momentum of decades of shit

  • djbusby 10 months ago

    Or, your stuck doing version upgrades of the framework before even getting to the fight.

  • bryanrasmussen 10 months ago

    >And the more the framework does, the earlier the fight begins.

    assuming that the more the framework does also means the less the framework allows you to do yourself. which is a pretty reasonable assumption of course.

simlevesque 10 months ago

ctrl+f "accessibility" in part 2: zero results

ctrl+f "accessibility" in part 1: zero results

Does anyone care about digital access to content for disabled people ? Or about the ADA ?

Svg to canvas without any answer for accessibility is backwardness, plain and simple.

You are letting down anyone who's deaf, blind or has trouble hearing or seeing, anyone who does not know how to read, has motor impairments, temporary or not and the older folks. Also screen translaters will not work on canvas.

Please follow the WCAG guidelines.

  • tadfisher 10 months ago

    Genuinely asking, how do you make something like their map view accessible with so many objects and layers? I'd imagine you end up with a solution that exposes various content rectangles and ignores everything else, kind of how Google Maps does it.

    • ygra 10 months ago

      Not all of accessibility is for those who cannot see (well). WCAG also has a bunch of guidelines for loss of dexterity and other ailments:

      • keyboard support (being able to navigate to all controls as needed, not being stuck in a navigation island from which there is no escape with the keyboard, etc.)

      • pointing device considerations (not requiring drag unless absolutely essential, no action on mouse-down, etc.)

      • not requiring the simultaneous use of mouse and keyboard (e.g. via modifier keys)

      • sufficient size for buttons and other pointer targets

      • the ability to suppress animations, flashing images, etc.

      • the ability to control colors and contrast of things on the screen

      ...

      Of course, something like Photoshop, Illustrator, or the visual part of Google Maps is hard to use when you cannot see, but there are so many different disabilities that some or even most accessibility guidelines can apply to pretty much any software.

      • dingledork69 10 months ago

        Oh is that why modern American software is almost unusable? Give me back my modifier keys and compact UIs

      • mydriasis 10 months ago

        No action on mouse down? So we need to develop applications that you can't click? Is that really part of accessibility requirements these days?

        • tylerag 10 months ago

          There's a difference between mouse down and mouse up. A click needs both.

    • mhoad 10 months ago

      This is a problem that turns up in Flutter when they compile for the web.

      The long term answer is the Accessibility Object Model spec currently under development.

      The current answer is to build a replica DOM structure for accessibility purposes.

  • pyrelight 10 months ago

    It's Flash Player all over again! Remember when SEO became important and everyone who had a Flash website had to make "low bandwidth HTML" sites for indexing? :)

  • Rapzid 10 months ago

    A somewhat common approach is to maintain a parallel DOM structure for accessibility and keep it in sync with the data structures driving the canvas view.

  • azangru 10 months ago

    Tangential question: how does accessibility work in Google Docs after they've switched to canvas?

    Or in Google Maps, which would be a much closer parallel?

    • a13o 10 months ago

      There's an accessibility mode you can enable which provides keyboard and menu navigation, as well as audio cues. It's basically an alternative interface for interacting with the data layer.

      I actually think this is a better approach to accessibility in web applications than trying to hang all of HTML+CSS+ARIA on the DOM. Check out Accessibility Object Model (AOM) for one spec proposal around this idea.

    • TonyStr 10 months ago

      While not directly related to your question, Google docs' switch to canvas broke my custom dark theme which I'd been maintaining for years, and several others were also using. This had been the main draw for me switching to Google docs in the first place and they took it away. I'd argue this is much less accessible as I can't use the product at night. Ironically, I feel like I've experienced more bugs after the switch than before

      • rablackburn 10 months ago

        > Ironically, I feel like I've experienced more bugs after the switch than before

        Not ironic, expected. When you do a refactor like this any good PM knows you’re creating a bunch of new bugs, and the ROI of the rewrite should consider this.

        Unfortunately the way it goes most of the time is “ok, what if we’re really careful not to write any bugs? Then it’s all upside!”

        …and now your dark theme is broken

  • rikroots 10 months ago

    I've never used the product, but I did see this snippet in the article, which gives me a flicker of hope that the product does address some accessibility concerns:

    > One particularly nice aspect of this system is that key presses follow the same flow as pointer events, which is not how things work in the DOM. In the DOM, you usually bind key handlers globally, and pointer events per element. But here, we get all the benefits of stopping propagation centrally, which is a real help for adding keyboard shortcuts and modifier keys.

    • layer8 10 months ago

      The quote doesn’t seem particularly related to accessibility. Having keyboard shortcuts doesn’t by itself imply accessibility.

  • vbezhenar 10 months ago

    Unless they have a legal requirement to provide product for disabled people, why would they care? It's a huge investment for very little output, unless this product is specifically targeted.

    • bryanrasmussen 10 months ago

      This attitude is why sooner or later everyone ends up with legal requirements for disabled people.

    • omniglottal 10 months ago

      Products are targetted toward people. Are the disabled not people? If you need an honest answer to "why would they care?", you need more help than can be provided here.

    • layer8 10 months ago

      Accessibility helps everyone, not just disabled people.

_virtu 10 months ago

I’ve been building a kinopio.club clone in Phoenix LiveView and the problems the author faces align with my experience from working with uis that require explicitly setting element position for the document. Having to manage all of the imperative handler logic was a huge pain on the JS side. I had also given myself the limitation to not use React for more complex Phoenix Hooks. It’s all native document rendering with the only dependency being x-state.

Moving the mouse event handler logic out into a state machine was where I found myself going in comparison to this author’s approach. I was pretty tickled by how much more maintainable it had been than the first time I had implemented it. x-state was by no means a requirement but it had a handful of features I didn’t feel like building for the current project.

I can absolutely believe that this is worth the effort, especially considering the fact that the team works with maps so much. The mental model presented in the article would be far easier to grok when working in the codebase than having to deal with the somewhat tricky to remember Event api provided by browsers for these types of use cases.

Others are mentioning fighting the framework but this is still a pain without React. But of course adding in React on top of all of this would make it harder.

  • hicksyfern 10 months ago

    Author here. Absolutely right what you said about being easier to grok.

    Shortly after this was merged to main (though under feature flag) another dev had to fix something and commented something like “I just fixed X in two minutes which would have taken me hours before”

    • hicksyfern 10 months ago

      And since you mention state machines: most of the handlers are done as state machines.

      Plus the overall app state is done as a kind of reverse state machine where we derive the status from various app states. I would like to change this to not be backwards one day but it was too big of a lift to change everything at once!

thomasfromcdnjs 10 months ago

I've built diagram like tools several times, constantly umming and ahing between Canvas and SVG.

SVG seems to get you pretty far, but I always end up with Canvas in the long run.

Fun fact: Google docs is actually a canvas.

  • chrismorgan 10 months ago

    > Fun fact: Google docs is actually a canvas.

    This is often said, and almost as often misunderstood as referring to what I call the “pure canvas” approach where you throw away almost everything the browser gives you and start from scratch. Some key points about Google Docs, just to clarify (I’m not disagreeing):

    ① Only its document area is rendered with canvas; its chrome is all still regular HTML.

    ② It still uses the browser for text shaping and painting, just not for macro-layout (breaking paragraph into lines, &c.). (I expect that’s what this article’s subject would be doing too, but it’s part of common misunderstandings.)

    ③ Even things like scrolling are completely left to the browser: it’s not a single <canvas>, but a regular DOM scrolling area contains a bunch of <canvas> tiles.

    ④ The shunning of using HTML-with-contenteditable for the entire thing makes editing perform very badly (throughput, latency and jitter), and things like keyboard caret navigation behave non-natively in ways that will be very frustrating for people that actually use and care about this stuff (you get to relying on things behaving the same, like with touch typing, so things that get it wrong like Google Docs and LibreOffice (which gets it all wildly wrong) constantly grate).

    ⑤ They could just as easily use HTML or SVG rendering as <canvas> (while keeping their input and layout the same, so I mean still with all manual line breaks and that kind of thing). You’d get quite similar performance (though probably overall a little worse), and the same problems (since it’s the input layer that makes it slow and jittery—it just fundamentally can’t be as good in those ways as boring old contenteditable, given the current primitives). In fact, it’d mildly surprise me if they didn’t have an SVG or HTML renderer handy, or did in the past and could revive it to complete indistinguishable functionality within a day or two (even if hacky).

    (I wrote a little more at https://news.ycombinator.com/item?id=33863185.)

    • rektide 10 months ago

      This is one of the best comments I've read on the much ballyhood Google Docs canvas! Favorited. I expect I'll be referencing this a good bit over the years.

  • rektide 10 months ago

    Google Docs document canvas is a tool. Most of the chrome & interface is html & works great.

    The switchover to canvas broke a ton of extensions. Chrome eventually went out & built a custom api to help users deal with some of the massive loss of functionality that switching off high-level html to go use lowest level html caused. But that took a ton of effort from Google, & the result is still a shadow of what was possible before.

    IMO, do the right thing for user agency & stick with higher level web stuff if you can, unless design truly compels it. Reinventing has many subtle pitfalls.

    • josephg 10 months ago

      > IMO, do the right thing for user agency & stick with higher level web stuff. Reinventing has many subtle pitfalls.

      This is great advice 99% of the time. But the browser has two big pitfalls which hurt google docs:

      1. Browser rich text editing events are famously awful and inconsistent on different browsers and platforms.

      2. Google docs wants the same document to render exactly the same on all OS / browser combinations. Thats not something that web browsers guarantee.

      In this case, I understand google's choice to build a custom renderer. I'm sure it was a massive effort for the team, but probably not quite as massive as working around all the browser quirks they were dealing with before. (From memory, before the canvas renderer, google docs ran their own rendering code then used CSS to absolutely position every single word in the document.)

      • chrismorgan 10 months ago

        > 2. Google docs wants the same document to render exactly the same on all OS / browser combinations. Thats not something that web browsers guarantee.

        Nor is it something Google Docs guarantees, since it still uses the browser for font shaping and rendering. The easiest way to demonstrate this is in Firefox, Settings → Fonts → Advanced → untick Allow pages to choose their own fonts, instead of your selections above, and Google Docs will layout and render the entire document using only your default font (most likely a serif). Not even doing a serif/sans-serif/monospace generic font fallback.

        (I’ve had that unticked for almost a year and a half now: it makes the web so much better on average, with minimal damage, almost all on Google properties due to their Material Icons font’s stupid ligation technique.)

        • josephg 10 months ago

          Ok, sure - you got me. If you mess with obscure browser options, you will successfully change how google docs renders content. But I suspect all of the people who select that option would fit in one meeting room, with a sign out front from google which says "WONTFIX".

          One thing people do do all the time in word processors is mash enter until the next bit of content ends up at the top of the following page. If a user does that, then they print their document from a different computer, it should print correctly. The next content should appear exactly at the top of the next page. If the word processor does anything else, users will be frustrated and blame the software. Word and Docs both put in a ton of engineering effort to get this right.

          (Educated users will insert a page break instead, but plenty of users don't know about page breaks. They still expect their documents to render correctly.)

          • chrismorgan 10 months ago

            I select that merely as the easiest way of demonstrating that it’s leaving important parts of its layout to the browser—parts that are not always consistent. There will be places where browsers in their default configurations differ, especially over time, to do with things like varying Unicode support or exotic OpenType shaping features, or even simple hinting. They won’t often be as big and flashy, but they’ll cause differences that may matter and added or removed lines from time to time.

            • josephg 10 months ago

              > There will be places where browsers in their default configurations differ, especially over time, to do with things like varying Unicode support or exotic OpenType shaping features, or even simple hinting.

              And my point is simply that google docs is explicitly designed to prevent any of these sort of issues from being noticable to the user. Sure, maybe individual characters or words will render slightly differently due to type hints. But as I understand it, google tries to make sure it never results in an added or removed line anywhere. The only way they can make sure of that is by shipping their own text layout engine. And hence the use of canvas to render text.

              • chrismorgan 10 months ago

                > And my point is simply that google docs is explicitly designed to prevent any of these sort of issues from being noticable to the user.

                I’ve demonstrated one place where it very obviously failed at this goal, and I know enough about variation in shaping to confidently state that others do exist, though the most obvious are almost entirely historical. But there are variations that can change glyph advance, which will affect layout.

                They use the browser’s shaping, so they’re subject to its quirks. In order to obtain absolutely consistent layout, they’d need to do the shaping themselves, but they have chosen not to do that (and I think they’re right not to).

                Google Docs has clearly been pushing for non-pagination in more recent times, and paragraph layout largely doesn’t matter once you’re not fussing about pagination.

                They reimplemented breaking paragraphs into lines, but gained literally nothing thereby in terms of actual functionality or behaviour, since the browser offers absolutely everything they wanted from it, and they still rely on the browser for the shaping.

      • dekhn 10 months ago

        I spoke to the original creator of Google Docs (from before it was Google Docs, https://www.theverge.com/2013/7/3/4484000/sam-schillace-inte...) and he confirmed what you recall; they had to write their own text rendering code because the browser does not implement the behavior required by a word processor (one example: flowing text around an image)

        • chrismorgan 10 months ago

          That was long before they switched to canvas rendering, too: they were still just using contenteditable, though potentially with mild layout augmentation with things like absolute positioning and sizing of things (I don’t know).

          Flowing text around an image: the web has been able to do this for donkey’s years, it’s the float property. More recently, there’s the CSS shape-outside property that even lets you use non-rectangular crop: https://developer.mozilla.org/docs/Web/CSS/shape-outside.

          • dekhn 10 months ago

            IIRC float is just left or right, you can't embed an image "in the middle" of text. I'm no web expert and the conversation was a decade ago, so I'm sure something got warped in translation.

      • mwcampbell 10 months ago

        > 2. Google docs wants the same document to render exactly the same on all OS / browser combinations.

        I think the industry needs to let go of this need for control. The browser is a user agent, not an author agent, and the same should be true of a document viewer. (Ideally, the browser itself should _be_ the document viewer.) For accessibility, if nothing else. And as for users brute-forcing a page break, let them be forced to finally let go of the print medium. We've been shackled by the print-first approach for long enough. Yes, I'm talking about accessibility again.

        • rektide 10 months ago

          "Pixel perfect design" is a phrase I keep seeing from Flutter camp, from Towards A Modern Web Stack. I'm so with you though: that's an anti feature!

          Developers/companies shouldn't have totalitarian control over the experience, I there should be malleability in software. Software is almost always best when it's not super hardened into form. This grasping for absolute control is poor form, in most cases.

      • rektide 10 months ago

        I have quite a lot of sympathy for Google, but I'd wager 90%+ of people heading down the Canvas path have really shoddy cases for why they're doing it.

        I'd also love to see more hybridization. With something like Figma, I both am sympathetic to their use of canvas. But I'd love it if they had a hybrid renderer that could also use HTML as well, with fixed position divs and HTML text. There used to be a slow but steady stream of blog posts on combining HTML and WebGL, some even with nice css3d transforms to make HTML act like a texture, but overall I don't think we've seen much hardcore uptake or attempts.

  • paulddraper 10 months ago

    You start with SVG

    Then you go to Canvas

    Then you go to WebGL

    Source: Early engineer at Lucidchart

    • ygra 10 months ago

      Similar journey here (yWorks, with a diagramming library, too). In our case the journey comes with drawbacks, though. Yes, WebGL allows for larger graphs, but it also does not support the flexibility (to customers) the other options offer.

    • hicksyfern 10 months ago

      Author here. For sure. That’s actually what we’re likely to do as the basemap rendering is done in webgl

    • mkl 10 months ago

      Then you go to WebGPU, I expect.

    • thekenwheeler 10 months ago

      it depends. canvas is typically much more cpu friendly. and does a way better job with text. (2d)

  • thrashh 10 months ago

    Same. Working around the issues with SVG sometimes takes as long as rewriting parts of SVG from scratch.

    It’s not an SVG problem so much as Canvas and SVG are not reconciled into one bigger rendering system, so when you hit an edge case that requires breaking outside out of SVG, you have no path.

  • alixanderwang 10 months ago

    i'm building a diagramming tool (https://terrastruct.com) and still umm and ah b/t it.

    I'm kind of waiting for webgpu to reach 95+% browser support before switching though.

    If I do all the work of switching, SVG better not get gpu/hardware-acceleration support the next day

    • Solvency 10 months ago

      I'm confused... Figma can seemingly do all of this already, from a rendering perspective. And it's outrageously performant. It's one of the most performant web apps I've ever seen.

      Why don't you do exactly what Figma is doing?

      • avmich 10 months ago

        A long time ago a small startup used unusual tooling in the industry. The startup was small, but the tooling had some great qualities, which allowed the startup to compete with bigger teams feature for feature, spending less efforts to produce the same functionality as their industry peers. Eventually the startup had a successful exit, the founders become rich, and one of them even started sharing his experience in a rather systematic manner. Happy end.

        Is it so that SVG requires to use all the features of it, or is it possible that you can mix and match, choosing what's important now and what's not, while benefiting from already existing SVG features? Is it possible that SVG followers don't do something which SVG does for them? Aren't there features, sufficiently aligned with SVG, which outperform directly working with other layers?

      • alixanderwang 10 months ago

        It's hard to get as performant as Figma does, not as straightforward as a rendering medium switch. What if webgpu lets me get Figma performance with my little 6 person startup team without the massive engineering man-hours Figma has spent on performance?

        Anyway, if it were high priority for us, we'd have done it already (switching to canvas/webgl). But right now it feels like buying a Quest when the Vision Pro is coming soon.

talkingtab 10 months ago

React three fiber and React three drei? Not sure what you are trying to do, but I have been super impressed by what you can do with react-three-etc. Video textures, images, click through works well. And when you need web thingies - input boxes for example - adding in a html is simple. Built on top of the outstanding threejs library. Examples of what you can do: https://docs.pmnd.rs/react-three-fiber/getting-started/examp... of what you can do. This one: https://codesandbox.io/s/drei-reflector-bfplr is pretty cool and not much code.

After a few weeks with r3f I am trying to figure out whether I can just use a very small amount of css and react. I integrated webrtc video chat as a texture pretty easily. Surely there must be some gotcha, but I have not found it yet.

dekhn 10 months ago

I gave up on interactive applications like this using web tech- Qt has the QGraphicsView framework which is far and away the best implementation I've seen so far in terms of programmability. There is a (significant) learning curve, but basically you're just learning how modern windowing systems work (and once you do, the browser model starts to seem awfully clumsy).

One of the crazy bits about QGraphicsView is that it provides not only simple primitives and the ability to make arbitrarily nested primitives, you can also render SVG, *and any Qt widget including a web browser) into the space.

CornCobs 10 months ago

> These InteractionHandlers are just objects satisfying a specific TypeScript interface. They’re not coupled to React or hooks or anything like that, which feels quite freeing, honestly. There’s no worrying about stale closures or dependencies or hooks rules - it really is just TypeScript.

> None of the interactions depend on a particular rendering system. We can actually use the DOM as a render target with all its pointer events disabled, and use this interaction system on top, which is quite neat!

In general, I think this is the most important takeaway here. Too often, we couple all our frontend logic to the rendering framework (especially state) when it has no business living in React and being tied to the component lifecycles.

I've had really good experience with MobX for React - separating out all our state into independent observable objects that React simply reacts to. This really cleans up a lot of logic and makes the presentation layer very clean.

In particular, a pattern that I believe in is simply exposing singleton, global stores for various parts of my application - effectively treating them as APIs that the rest of the app can subscribe to.

rektide 10 months ago

Super late to this but they mention element overlap in SVG making thinks like drag & drop hard. That's their "interactivity" gripe, and the one that for me carried the most weight.

I'd be very interested to get more discussion on this specific issue, of handling mouse events well in SVG.

The particular example felt contrived, in that I might just apply a class HasPointerEvents to every element and change the pointer events off for everyone except the drag & the dropped element. But I suspect there may be some other real mouse handling topics in SVG that really are interesting & challenging, & would love some discussion on that. Kind of iwld that the internet doesn't have a ton of obvious forums to go hash out tech topics like this... Post a random question/challenge to stackoverflow & cross your fingers.

  • hicksyfern 10 months ago

    Author here. The example given is slightly contrived. A more realistic example involves large polygons that you zoom “inside” or locked elements overlaying active ones. But I had to try to give an example without a ton of context.

    There are some more interesting but less easy to explain to a broad audience examples.

    One is having “nearest the pointer” hovering logic rather than rectangles or circles overlaying each other.

    Another is hovering line segments and the projecting the nearest hovered point onto the line. That was approximated with SVGs before and was just kind of a bug.

    Another example is allowing some “wiggle room” for touching elements without having to render SVGs multiple times with transparent elements and stuff like that.

    • rektide 10 months ago

      Circling back just to say this was really fun & interesting stuff. Appreciate you responding with these cases!

deterministic 10 months ago

Frameworks are great if your application fits perfectly into the subset of applications that the framework was designed for. However the moment your applications grows beyond the design boundaries of the framework, you might end up in a situation where you have to drastically rewrite the app or even do a complete rewrite.

Which is why I have always been more productive long term using my own frameworks. It takes longer to get started, but once you get the train going, nothing stops it.

nawgz 10 months ago

I'm interested in Canvas - I write a lot of data viz in SVG. I find it to have lots of warts, but provide lots of value. I'm interested by this article and wish to challenge it too, here's my thoughts.

Maybe I'm an idiot though - where is this library? I can't find it on their GitHub or linked from the articles

> In the SVG world, we use CSS z-index to place the DragBox at the back and the SelectionFrame at the front.

Not a great start IMO - SVGs don't support z-index. The front-to-back ordering z-index influences in HTML is decided in SVG directly by the order in the HTML within the <svg> element (in reverse - later elements are "on top"). What they could mean to say, if this isn't entirely inaccurate, is that "we render multiple SVGs and arrange them with z-index", which... I also find strange. I don't want to read their source code but I also don't find this to be giving them huge credibility.

> Performance

> Having every element produce a whole load of DOM elements for React to manage becomes a problem for performance when every element attaches event handlers, has to manage their lifecycles, observe state, etc., etc.

My concerns are mounting. This is fundamentally the problem React solves, not one it creates.

The amount of layers they picture in their example is not huge. I had the target to get 60fps on a Graph with 1000 nodes + smart edge routing, and you can do lots of interactions in the graph - each node can be moved independently or in a group, selected, you can drag a background box to select objects geometrically intersecting, and you can create new connections with drag, you know - basics. Not sure how performance is impacting them at an order of magnitude less, unless they are struggling with React itself.

> Interactivity Limitations

> with the text taking up so much space it’s very easy to accidentally drag the text instead

> This was a very longstanding bug

I interpret this as them saying "the text background was not displayed to users, so while it appeared the mouse was over the polygon, it was actually over the text background, therefore the text was dragged". Seems to me hover state would give the user the hints they need here, but I look forward to the Canvas solution

> Maintainability

Once again I really can't help but interpret this as a weak handle on React.

Onto the solution.

> The new system: per-state InteractionHandlers

Honestly, the fact they had to leave React to manage this once again speaks to bad React practices. Have they never heard of Context/Provider?

> The general idea is this: there are a lot of different things you can do in Felt, but at any given time, the number of things you can do is limited. If we can therefore define which interactions are active at any given time, and also manage the flow of events through the handlers we should be in a good place

Yes, this is good architecting. However, the only thing they describe here that piques my interest is this:

> Here is the full sequence of events that an InteractionHandler can process, with the ability to break the chain at any point, and prevent other handlers in the stack from being called.

> <graph showing how mouse events are managed manually, enabling mouse movement to correlate to available mouse events>

This is a big pain point in React - very difficult to manage onMouseDown separately from onClick. Usually I accomplished this by overloading onMouseDown and onMouseUp to call the actual dev-user-available action handlers, but their described result is more graceful.

> Goal 1: Interactions should be decoupled from each other

> Each interaction handler has no knowledge of any other. The knowledge about how to prevent “collisions” in interactions resides with the map of handlers and the manager.

Right, but why couldn't this be done in React?

> Goal 2: Interactions should be performant

> Because there is only one handler per feature as opposed to a bunch of handlers per element, there is a lot less allocation of resources.

Sounds and looks cool, is the implication that there is only O(feature count) event listeners for the Canvas?

I'll have to profile my library for this

> Goal 3: Interactions should be decoupled from access control

> Access control is now simply a case of writing a different list of interaction handlers for each access level. There’s no longer any isEditor code littered throughout

> Goal 4: Interactions should be decoupled from rendering

Yikes. I think they really conflated bad architecture with React problems a lot in this article.

Alright though, I see some clear wins at the end:

> Goal 5: Complex interactions should be achievable

> <video shows that text is interacted with not as a bounding rect but character polygons>

This is a win, and one they obviously wanted. It's probably true this isn't possible with the DOM, unless you render each character individually as a polygon or something that would undoubtedly be insanely painful

> Doing this with an element-centric approach is nigh-on impossible. There’s no way (as far as we know) to say to a DOM element: “receive clicks, but pass-through mousedowns and drags.”

I agree with this claim, but wish they would elaborate what these use cases look like.

> OK, there are some hidden details there such as ...

> we maintain a spatial index of our elements using rbush which we query for coarse intersections with the cursor before performing more accurate hit tests using Turf.js.

Right, this all sounds quite graceful, indeed it sounds a bit like implementing a graphics system. It sounds like it met some of their goals too, and enabled some long-desired features the DOM didn't make possible.

But their criticisms of React & SVG are really weak here, and it sounds to me like they never properly decided how the system should behave and what parts should interact in the DOM world, and their issues fell out of that.

I also think that you should really not talk so much about z-index with SVG unless you make it more clear how those things could even be related.

Overall, I think they had a great team that implemented a great solution that aligned with their end-goals, but the work they replaced doesn't sound like it was even well-aligned with the framework it was implemented in, let alone their end goals. I would not agree with their recommendation to move to Canvas if SVG doesn't "feel right" until you do more analysis of why your solution is failing and what options are available.

  • hicksyfern 10 months ago

    Author here. It might be worth reading part 1, also.

    Aside from that, yes z-index was because there are multiple SVGs rendered. We also had non-SVG stuff for each element like inputs and stuff, plus it was just like that when I got here, and it doesn’t seem unreasonable to me.

    Another thing was you said it’s a problem React solves rather than creates. This is very clearly not true.

    If you add event listeners to every component which is big-standard React, you end up with 1000s or tens of 1000s of event handlers often doing almost nothing. And sure, JavaScript can do 10_000 lots of almost nothing very quickly, but it’s noticeable when you’ve got a strict frame budget.

  • mch82 10 months ago

    Nothing wrong with a long comment, but it might facilitate discussion to break your long comment up into a few top level comments.

    • nawgz 10 months ago

      Possibly true; I think it would also be reasonable to pick some part of this if it interests you and reply to just that, nothing wrong with that.

wly_cdgr 10 months ago

Canvas is a really nice vector API, very underappreciated precisely because of its elegant simplicity. Its problem is that, because it's so straightforward and well-designed, people can't easily use having had to work with it to pretend they are Big Brain.

zagrebian 10 months ago

What’s with all the <p-inline> tags in the text?

  • lelandfe 10 months ago

    I just see span.p-inline elements, which appear to be their way of representing inline code (the <code> element would be a better choice, but meh, not a big deal)

jgalt212 10 months ago

Has anyone tried using canvas to stymie scrapers?

  • mkl 10 months ago

    Won't stop anyone determined - OCR is pretty easy. Better would be access control and rate limiting, but it's still a fundamentally unsolvable problem, as if it's visible it's scrapable.

hollow-moe 10 months ago

Ah yes, people blocking canvas fingerprinting will also love your blank pages, but as they're a minority of users it's not a concern

  • dingledork69 10 months ago

    If you choose to disable features in your browser then they won't work. Is this surprising to you?

robocat 10 months ago

It sounds like most of their problems were with using the browser SVG event handlers (or perhaps the framework).

They could have written their own event system for SVG (e.g. using event handlers on document), which would have fixed the gripes they blamed on SVG events. They wrote their own event system for canvas, so probably not much more difficulty in coding work?

Performance is the remaining issue that isn’t clear that SVG would meet. I assume SVG painting could be as fast as canvas painting. I am assuming if you attach no events to SVG elements, you remove the event performance issues (well, replace them with performance issues in your own custom event handlers, but no worse than canvas). Surely removing all the now unneeded SVG-grab-handle-elements (“DragBox”) that were only there to capture events would also improve performance (painting and event capture). Canvas is using imperative drawing primitives, and SVG can use composable primitives - both can be rendered by GPU. Canvas updates (eg. during dragging) require heavier imperative updates, while SVG primitives can theoretically be offloaded to the GPU. I can’t guess performance differences and performance delta probably strongly depends on browser, driver, and GPU.

Assuming you write your own event handling stack:

> the mouse only hits SVG elements inside their painted region

Fixed (as good as canvas)

> we could use things like pointer-events to disable certain interactions at certain times

Unnecessary (plus lowers stress on rendering?)

> Having every element produce a whole load of DOM elements for React to manage becomes a problem for performance when every element attaches event handlers, has to manage their lifecycles, observe state, etc., etc.

Fixed with document events

> Interactivity limitations. With our SVG renderer, each element managed its own interactions, which made it impossible to drag elements that were underneath other elements. This is a surprisingly common when making complex maps.

Fixed with document events

> Maintainability. However, with every element attaching its own interactions, there is a tendency for every interaction to know about every other, checking if it should be enabled or not.

Fixed with document events

> Another maintainability issue is the proliferation of event.stopPropagation() calls in the code. These are to stop events bubbling up through the complex DOM structure and allowing other components to handle events.

Fixed with document events (equivalent difficulty to canvas).

When writing complex code you learn that stopPropagation() is evil. Writing code to avoid it requires skills. IMHO stopPropagation should never be in any complex codebase (or perhaps with rules to prevent errors).

> We also have a few places where we have awkward setTimeout() calls

Oh my god, no! Terrible hack with terrible consequences, as they discovered. setTimeout() introduces very evil race-conditions, and testability issues. An alternative which isn’t much better is to use async to get microtasks, so at least you are not reordering events/tasks. IMHO in any modern codebase setTimeout should be banned or extremely restricted when it is absolutely needed.

SUMMARY

Basically, it sounds like the team needs some more experienced GUI developers.

I would bet good money they are trading one set of problems for another, and ending up with a codebase that is less maintainable.

I can only hope the article is not written by the lead developer - heaven help them if it were.

Opinions are my 10c as a custom framework developer (admittedly only one product that was not as complex as a GUI editor - that is why the inexpert mistakes sound so painful to me - although I could also avoid and detect problems because it was my own framework: depending on a third party framework makes it a heap harder to fix systematic faults).

  • hicksyfern 10 months ago

    Author here.

    I know this is the orange site and we have to expect this type of comment, but still…

    I’ve been building software for more than 20 years, and using React since it came out.

    You’re right that this event handling system isn’t exclusive to canvas. But then I’m not sure if you read the first part of the article where we talk about the other big reason: performance.

    Your assertions that setTimeouts should be banned show immaturity. There are some cases where certain browsers do things in a different order and you really are required to use a hack like that.

    You also neglect the fact (and this also points to your immaturity) that products are built by a number of people over a long period of time, with different constraints on them as things change.

    The SVG approach was done for good reasons and the code made sense for what it was for initially. Then things got more complex and people started making more complex maps.

    What we also found is that the complexity of maps people made increases with our performance gains: the faster the app is, the more people do with it.

    I haven’t got time to go into everything either in the articles or certainly this reply, but I’d ask you to have a look at yourself and decide if you really want to be That Guy on HN.

    • robocat 10 months ago

      Yeah, I should not have been so inflammatory and I should have limited my comments to where I have deep experience.

      The comments on preventDefault() and setTimeout() in particular repeat my own hard-won experiences: it is unfortunate you had to experience the same pain.

      In the previous article, maybe the first third is you fighting your framework, which is admittedly what happens to us all if we are on the bleeding edge with performance issues. Certainly you are not the first team to find that canvas is a better solution.

      In the first article you say “whenever the element’s coordinates or the viewport changed, we would re-render the element”, and you go on to talk about SVG versus canvas. HOWEVER it is impossible to tell whether your underlying performance problems actually stem from SVG (or SVG+events, or SVG+React). I can believe that canvas is more performant and more predictable, but your first article lacks enough detail to actually blame SVG. DOM changes, React, JavaScript could and probably did have severe impact on overall performance. That was the point I tried to make (admittedly, very poorly, since it isn’t clear you could avoid DOM changes in particular).

      My main gripe with your second article was that you were concentrating on problems to do with SVG events and React - a problem that you resolved with your own event stack on canvas. That solution could have worked for SVG, although as you wrote in your first article, would not resolve your performance problems when painting.

      > Your assertions that setTimeouts should be banned show immaturity. There are some cases where certain browsers do things in a different order and you really are required to use a hack like that.

      I guess I had that coming, but I stand by the statement. I learnt about setTimeout(0) caused-problems when working with DHTML controls (pre-frameworks) and frameworks that had nasty heisenbugs: intermittent hard-to-reproduce bugs that would surface because of events racing timeouts. One reason for writing a custom framework was that it was more reliable for users than depending on code that was out of our control: just the same as you are writing about. The framework KendoUI had been chosen by another at one point, and it was particularly troublesome for me. I believe using setTimeout() to avoid browser bugs is diabolical (or framework bugs even worse), because all too often you end up with further troubles that can be extremely hard to reproduce or diagnose. I worked hard to avoid setTimeout(), replumbing code at times, but it virtually always could be avoided with enough work (especially with complete control over event handlers). I stand by “setTimeout should be banned or extremely restricted when it is absolutely needed” because setTimeout(0) is a plaster that too many developers use to paste over cracks. Yes, browsers sometimes force us to accept the ugliest of hack solutions, to achieve some usability goal or avoid some browser bug.

      All the best. Without a doubt you are far more experienced than I in this area, and certainly you have had a ton of experience wrestling with canvas versus SVG, and I certainly appreciate your article about how you won using canvas. Fighting performance problems in browsers requires a certain intransigence and flexibility, and I feel your pain and your glory from my own past experiences doing the same.

      (Edited to add extra depth and details). I think that I was so skeptical because the articles lack many technical details that compare SVG performance versus canvas. It compares a React+SVG codebase, with a rewritten canvas codebase. I can believe that SVG is worse than canvas, but neither article has much that is convincing on that point except that the rewrite was successful (which is admittedly a good prior that canvas is better). it is possible you are too quick to dismiss the experience of others. Background: I was nearly 100% focused on front end work, mostly heavy DOM/JavaScript from 2006 for a bit over a decade; but I have worked in a variety of software dev roles for a few decades (embedded, DB, client-server, Windows apps, front-end, POS, plus other random bits). I can definitely say I am well above average at writing reliable, performant, usable code (maybe due to my embedded programming background?).

      • hicksyfern 10 months ago

        Appreciate the response.

        The thing is, for a lot of it I can’t go into huge amounts of detail otherwise I could write a book on it.

        You’re right that the interaction system could keep the SVG as a renderer, and I don’t remember whether that point ended up in the final version! But I have done that locally just for fun to see if it works and it does.

        I can give you one example of something that’s too much to go into in a high-level article: SVG and canvas are both very slow at drawing dashed lines. With mapping software, the overall zoom level gets to something like 50 million percent or something ludicrous, and what that means is often you have literal kilometres of dashed lines drawn off screen just if one pixel is on screen for that geometry.

        With SVG the only real way to get good perf is to use transforms to move things around when you’re not zooming, or scale them when you are. This doesn’t work if you then need to viewport-clip your lines – you need to render every frame and that gets really slow. With canvas it’s just not a problem, I guess partly because you’re not always making enormous path strings on every frame.

        Another example is viewport culling. To avoid thrashing the DOM as you zoom, you don’t really want to be adding and removing elements because it gets janky. We had a viewport culling solution in SVG land with a big dynamic CSS style switching each element on and off which alleviated the browser’s painting workload but it feels hacky as hell. With canvas, you just intersect the viewport with the world and that’s your display list so you render each element in that list. Much simpler model.

        Seriously there’s so much involved in making this stuff work well I could literally write a book, but I had to settle for a 2 part article where I had to pick the simplest examples and shortcut some of the detailed explanations.

        After all, it’s just a dev blog not an academic paper.

        • robocat 10 months ago

          Thanks heaps for the details.

          It is difficult to write a good blog post, and the extra detail is interesting.