Drawing to the Screen
Drawing a picture to the screen is usually the end goal of using Doodle.
The usual way to draw a
Picture is by calling the
draw method. Using the Java2D backend will produce output in a window, while the SVG backend can produce output inside a web page.
The examples below use the Java2D backend, but the general principles work with other backends.
You need the normal imports to do anything with Doodle. Here are the imports for
Picture and the JVM backend.
import doodle.core.* import doodle.syntax.all.* import doodle.java2d.* import cats.effect.unsafe.implicits.global
The normal way to draw output is by calling the
val picture = Picture.circle(100).strokeColor(Color.crimson)
When using the Java2D, the output will appear in separate window.
As explained in the concepts chapter, Doodle has the concept of a frame and a canvas. A canvas is an area where a picture can be drawn, and a frame describes how to create a canvas. If you don't explicitly tell Doodle what frame you want, it uses a default. The default has a white background, is a little bit larger than the picture being drawn, and centers the picture in the middle of it.
The Java2D Frame allows you specify the size of the window, a background color, and more. Here's an example where we change the size and background color.
val frame = Frame.default.withSize(300, 300).withBackground(Color.midnightBlue)
Once we have a frame, we can pass it to
Sometimes you'll want to draw several pictures on the same canvas. This is how animations work, repeatedly drawing to the same canvas. To do this you need to get a reference to a
canvas syntax method on
Frame will produce an
val canvas = frame.canvas()
You can then call
canvas.map(c => picture.drawWithCanvas(c))
However, this is not very idiomatic code. The above methods are all conveniences that hide the underlying use of
IO. As soon as we introduce
IO we should use the methods described below.
Drawing with IO
It can be useful to convert a
Picture[A] to an
IO[A]. This could be because the picture is part of a larger program using
IO, you are working with an
IO[Canvas], or you want to access the
A value that is discarded by the
draw variants discussed above. The
drawToIO method does this conversion.
There are also variants
drawWithCanvasToIO is the idiomatic way to work with an
canvas.flatMap(c => picture.drawWithCanvasToIO(c))
Once you have an
IO, you can run it in the usual way as part of an
unsafeRunSync, or one of the other methods.