Now when I want to draw a crisp line, I found that there are two things to fight with. The first one is that canvas uses antialiasing. So when I draw a line of thikness 1 at integer coordinates, it will be blurred.
Let's say my display is hi-res and window.devicePixelRatio is 2.0. When I apply context scaling to adapt canvas to the hi-res display and want to draw the line with thickness of 1, can I just ignore the context scale and draw
The 0.5px offset for straight lines works only for line widths that are odd integers. As you hinted to, it's so that the stroke, that can only be aligned to the center of the path, and thus will spread inside and outside of the actual path by half the line width, falls on full pixel coordinates. For a comprehensive explanation, see this previous answer of mine.
Scaling the canvas buffer to the monitor's pixel ratio works because on high-res devices, multiple physical dots will be used to cover a single px area. This allows to have more details e.g in texts, or other vector graphics. However, for bitmaps this means the browser has to "pretend" it was bigger in the first place. For instance a 100x100 image, rendered on a 2x monitor will have to be rendered as if it was a 200x200 image to have the same size as on a 1x monitor. During that scaling, the browser may yet again use antialiasing, or another scaling algorithm to "create" the missing pixels.
By directly scaling up the canvas by the pixel ratio, and scaling it down through CSS, we end up with an original bitmap that's the size it will be rendered, and there is no need for CSS to scale anything anymore.
But now, your canvas context is scaled by this pixel ratio too, and if we go back to our straight lines, still assuming a 2x monitor, the 0.5px offset now actually becomes a 1px offset, which is useless. A lineWidth of 1 will actually generate a 2px stroke, which doesn't need any offset.
Preventing anti-aliasing requires that the pixels of the canvas, which is a raster image, are aligned with the pixels of the screen, which can be done by multiplying the canvas size by the devicePixelRatio, while using the CSS size to hold the canvas to its original size:
One thing to keep in mind is zooming. If you zoom in on the example, it will become anti-aliased as the browser scales up the raster image. If you then click run on the example again, it will become crisp again (on most browsers). This is because most browsers update the devicePixelRatio to include any zooming. If you are rendering in an animation loop while they are zooming, the rounding could cause some flickering.
Losing my mind here. I spent the last couple days writing the beginnings of a windows app in WinForms... yesterday did a 90 degree turn and had to switch over to WPF for aesthetic reasons. Been having some trouble converting certain things over... namely anything graphics related. In the wpf version, I had the following C# code to created a black circle and white rectangle at the point where the user clicked on the panel and display a message box displaying what the x coordinate is:
This compiles and runs correctly but when I click on canvas, nothing happens! The messagebox was there mainly as a test to see if the event was triggering at all, which it clearly isn't. Here's the corresponding XML for the window with the canvas in it:
Got it. Can't believe it took me 6 hours to draw a Rectangle. Not exactly sure what made it work but think it had to do somewhat with getting rid of using System.Drawing; When I tried sa_ddam213's code I got an error saying "Cannot convert from System.Drawing.Rectangle to System.Windows.UIElement" for unknown reasons. After google search number 5007 I came upon this article:
Drawing a scene like this requires paying careful attention to the perspective of the horizon line and the angles of the buildings. For that reason, I found it useful to to use a grid system to transfer this drawing to my painting surface.
At one end, some very skilled artists might not even need to draw on the canvas, diving straight into painting, measuring all angles and relationships by sight alone. This is a rare skill, so most of us will need to at least sketch in some guide lines to help us plan the painting.
For a very loose landscape, without any architecture or man-made structures, I might get away with not doing any measuring, just sketching in the main shapes, and even moving things about to make a pleasing composition.
The next step up from freehand drawing would be using the old measuring technique of holding a pencil or paintbrush at arms length and using your thumb to measure elements of your subject, and compare them with other elements, and to judge angles, and then to transfer those angles and measurements to your drawing.
The next step would be directly tracing your reference image, which you could do by printing it out at the size you want to paint it, covering the reverse side in graphite/soft pencil, and then placing it over your painting surface, and drawing over the outlines with a pen or something similar, so that the graphite gets transferred onto the painting surface.
Finally, at the other end of the spectrum, I suppose the most direct method would be to print the image directly onto your painting surface, and then paint on top of it. This would probably be more difficult to do, requiring a canvas printer, but it would also require the least amount of drawing skills.
Of course using a technique like tracing removes any opportunity for artistic license, so you might want to try a less rigid method, like the grid system, or a combination of techniques, like using the grid system for certain elements, while drawing other elements freehand.
I have a project which has many steps and I'd like to create a visual representation of the steps in a flowchart form, but the chart will be very long. I need something that I can "draw" on that will continue without "paging". I simply need an extremely long canvas.
As you can see it's just a simple, intuitive browser tool. It's got some handy features like copy and pasting cell styles, forcing objects to front/back and toggling pages on or off. If you need there are also plenty of tutorials and instructions to be found online though I have to admit it's extremely straight forward. :)
For flowcharts maybe give yed a try. It is a node based graph editor. You can connect the nodes and label the connections. You can also export as SVG and many image files. It has a never ending canvas like you want.
Now I'd like to draw animated custom vector shapes on my map like in this cool demo. The canvas class seems like a good place to start, but for the life of me, I could not find any (recent and simple) examples of how to use it. There are some old code pieces based on Leaflet 0.7, at a time when it probably did not provide the feature. I also looked at some plug-ins for inspiration, but they are usually too sophisticated to be helpful and/or do not extend the Canvas class and re-implement a lot of methods, which seems weird.
Keeping digging in SE, documents and testing code, I understood one important thing, thanks to this first answer in SE and this other question on SE: the Leaflet Canvas class is NOT intended to perform custom canvas-like drawing for users. This is why it is not documented in details. A couple of explanation lines in there would have avoided me to go on the wrong track for an entire day, I suppose this is part of the Leaflet learning curve :-)
I did find a (simple) solution though, thanks to this small L.CanvasLayer class that was referenced in the second SE question. Here is an extract of my test code. I draw a simple circle in 2D at (100,100) and I do not use the map projection (yet), but of course I plan to use more sophisticated shapes and tie them to the map - which was out of the scope of this question.
EDIT: as I am learning Leaflet, I am discovering alternate solutions. Drawing directly in a Canvas is not a silver bullet because you get artefacts when zooming or panning, so you have to write code to compensate for these - especially if you have some animation going on. The more it goes, the more I think that the SVGOverlay is an easier solution. It allows you to draw vector shapes of any kind. CSS can be used to style them, which is convenient. SVG shapes can be built programmatically, as demonstrated in the Leaflet doc. And they are well integrated in the Leaflet ecosystem. Since I am not going to have too many of them, this seems like an easier and faster path.
The following code example is designed for use with Windows Forms and requires a PaintEventArgs object. The PaintEventArgs object is named e and is a parameter of the Paint event handler. The code performs the following actions:
In .NET 6 and later versions, the System.Drawing.Common package, which includes this type, is only supported on Windows operating systems. Use of this type in cross-platform apps causes compile-time warnings and run-time exceptions. For more information, see System.Drawing.Common only supported on Windows.
You can obtain a Graphics object by calling the Control.CreateGraphics method on an object that inherits from System.Windows.Forms.Control, or by handling a control's Control.Paint event and accessing the Graphics property of the System.Windows.Forms.PaintEventArgs class. You can also create a Graphics object from an image by using the FromImage method. For more information about creating a Graphics object, see How to: Create Graphics Objects for Drawing.
You can draw many different shapes and lines by using a Graphics object. For more information about how to draw lines and shapes, see the specific DrawGraphicalElement method for the line or shape you want to draw. These methods include DrawLine, DrawArc, DrawClosedCurve, DrawPolygon, and DrawRectangle. For more information about how to draw lines and shapes, see Using a Pen to Draw Lines and Shapes and Using a Brush to Fill Shapes.
You can also draw images and icons by using the DrawImage and DrawIcon methods, respectively. To perform a bit-block transfer of color data from the screen to the drawing surface of the Graphics object, see CopyFromScreen. For more information about how to draw images with a Graphics object, see Working with Images, Bitmaps, Icons, and Metafiles.
795a8134c1