All Projects → fzipp → canvas

fzipp / canvas

Licence: BSD-3-Clause License
Draw on an HTML 2D canvas in a web browser from a server program using WebSockets.

Programming Languages

go
31211 projects - #10 most used programming language
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to canvas

Construct
JavaScript Digital Organisms simulator
Stars: ✭ 17 (-76.06%)
Mutual labels:  websockets, canvas2d
Picasso
Picasso is a high quality 2D vector graphic rendering library. It support path , matrix , gradient , pattern , image and truetype font.
Stars: ✭ 205 (+188.73%)
Mutual labels:  canvas2d, 2d-graphics
WebSocketPipe
System.IO.Pipelines API adapter for System.Net.WebSockets
Stars: ✭ 17 (-76.06%)
Mutual labels:  websockets
crank4go
API Gateway implemented in Golang
Stars: ✭ 124 (+74.65%)
Mutual labels:  websockets
nclua
Event handling and 2D graphics for Lua scripts
Stars: ✭ 15 (-78.87%)
Mutual labels:  canvas-api
real-time-todo
A real time todo list using websockets
Stars: ✭ 22 (-69.01%)
Mutual labels:  websockets
typesocket
🌐 TypeScript WebSockets library.
Stars: ✭ 24 (-66.2%)
Mutual labels:  websockets
simple-websocket-server
A simple WebSocket server
Stars: ✭ 26 (-63.38%)
Mutual labels:  websockets
shmup.re
Learning Reason/OCaml by making an old-school canvas game.
Stars: ✭ 24 (-66.2%)
Mutual labels:  canvas2d
apollo-chat-graphql-server
Apollo Chat is a Chat Service build on GraphQL Apollo with Subscriptions
Stars: ✭ 13 (-81.69%)
Mutual labels:  websockets
realtime-chat-go-react
An example of a Real-Time Chat Application built using React.js and Go!
Stars: ✭ 61 (-14.08%)
Mutual labels:  websockets
amazon-ivs-simple-chat-web-demo
⚠️ IMPORTANT ⚠️ This repository is no longer actively maintained and will be archived at the end of 2022. A basic live chat implementation built with WebSockets, that can be used in conjunction with Amazon IVS to build compelling customer experiences for live video streams with chat use cases.
Stars: ✭ 53 (-25.35%)
Mutual labels:  websockets
node-red-contrib-blynk-websockets
No description or website provided.
Stars: ✭ 35 (-50.7%)
Mutual labels:  websockets
viper
Real-time tracking and analytics using Node.js and Socket.IO
Stars: ✭ 12 (-83.1%)
Mutual labels:  websockets
gochess
Online real time chess web server using websockets
Stars: ✭ 32 (-54.93%)
Mutual labels:  websockets
megaphone
Hear ye, hear ye 📣
Stars: ✭ 15 (-78.87%)
Mutual labels:  websockets
interactive-plants
Generative plants and flowers.
Stars: ✭ 21 (-70.42%)
Mutual labels:  canvas2d
WebsocketBundle
Provides websocket services for Symfony2, including an in-built server, multiplexing, and semantic configuration. Uses Wrench.
Stars: ✭ 50 (-29.58%)
Mutual labels:  websockets
dataviewer-example
📊 Usage examples of dataviewer - https://github.com/jasrodis/dataviewer
Stars: ✭ 15 (-78.87%)
Mutual labels:  websockets
pushest
Bidirectional Pusher client in Elixir
Stars: ✭ 33 (-53.52%)
Mutual labels:  websockets

canvas

PkgGoDev Build Status Go Report Card

This Go module uses WebSockets to communicate with a 2D canvas graphics context in a web browser. It offers a portable way to create interactive 2D graphics from within a Go program.

The Go program (server) sends draw commands to the web browser (client) via WebSockets using a binary format. The client in return sends keyboard, mouse and touch events to the server.

The module does not require operating system specific backends or Cgo bindings. It does not use WebAssembly, which means the Go code runs on the server side, not in the browser. The client-server design means the canvas can be displayed on a different machine over the network.

Examples

The example subdirectory contains several demo programs.

Screenshots of examples

Usage

Drawing

The ListenAndServe function initializes the canvas server and takes the following arguments: the network address with the port number to bind to, a run function, and zero or more options, such as the canvas size in pixels, or a title for the browser tab.

The run function is executed when a client connects to the server. This is the entry point for drawing.

package main

import (
	"image/color"
	"log"

	"github.com/fzipp/canvas"
)

func main() {
	err := canvas.ListenAndServe(":8080", run,
		canvas.Size(100, 80),
		canvas.Title("Example 1: Drawing"),
	)
	if err != nil {
		log.Fatal(err)
	}
}

func run(ctx *canvas.Context) {
	ctx.SetFillStyle(color.RGBA{R: 200, A: 255})
	ctx.FillRect(10, 10, 50, 50)
	// ...
	ctx.Flush()
}

After the program has been started, the canvas can be accessed by opening http://localhost:8080 in a web browser.

The server does not immediately send each drawing operation to the client, but buffers them until the Flush method gets called. The flush should happen once the image, or an animation frame is complete. Without a flush nothing gets displayed.

Each client connection starts its own run function as a goroutine. Access to shared state between client connections must be synchronized. If you do not want to share state between connections you should keep it local to the run function and pass the state to other functions called by the run function.

An animation loop

You can create an animation by putting a for loop in the run function. Within this loop the ctx.Events() channel should be observed for a canvas.CloseEvent to exit the loop when the connection is closed.

A useful pattern is to create a struct that holds the animation state and has an update and a draw method:

package main

import (
	"log"
	"time"

	"github.com/fzipp/canvas"
)

func main() {
	err := canvas.ListenAndServe(":8080", run,
		canvas.Size(800, 600),
		canvas.Title("Example 2: Animation"),
	)
	if err != nil {
		log.Fatal(err)
	}
}

func run(ctx *canvas.Context) {
	d := &demo{}
	for {
		select {
		case event := <-ctx.Events():
			if _, ok := event.(canvas.CloseEvent); ok {
				return
			}
		default:
			d.update()
			d.draw(ctx)
			ctx.Flush()
			time.Sleep(time.Second / 6)
		}
	}
}

type demo struct {
	// Animation state, for example:
	x, y int
	// ...
}

func (d *demo) update() {
	// Update animation state for the next frame
	// ...
}

func (d *demo) draw(ctx *canvas.Context) {
	// Draw the frame here, based on the animation state
	// ...
}

Keyboard, mouse and touch events

In order to handle keyboard, mouse and touch events you have to specify which events the client should observe and send to the server. This is done by passing an EnableEvents option to the ListenAndServe function. Mouse move events typically create more WebSocket communication than the others. So you may want to enable them only if you actually use them.

The ctx.Events() channel receives the observed events, and a type switch determines the specific event type. A useful pattern is a handle method dedicated to event handling:

package main

import (
	"log"

	"github.com/fzipp/canvas"
)

func main() {
	err := canvas.ListenAndServe(":8080", run,
		canvas.Size(800, 600),
		canvas.Title("Example 3: Events"),
		canvas.EnableEvents(
			canvas.MouseDownEvent{},
			canvas.MouseMoveEvent{},
			canvas.TouchStartEvent{},
			canvas.TouchMoveEvent{},
			canvas.KeyDownEvent{},
		),
	)
	if err != nil {
		log.Fatal(err)
	}
}

func run(ctx *canvas.Context) {
	d := &demo{}
	for !d.quit {
		select {
		case event := <-ctx.Events():
			d.handle(event)
		default:
			d.update()
			d.draw(ctx)
			ctx.Flush()
		}
	}
}

type demo struct {
	quit bool
	// ...
}

func (d *demo) handle(event canvas.Event) {
	switch e := event.(type) {
	case canvas.CloseEvent:
		d.quit = true
	case canvas.MouseDownEvent:
		// ...
	case canvas.MouseMoveEvent:
		// ...
	case canvas.TouchStartEvent:
		// ...
   	case canvas.TouchMoveEvent:
		// ...
   	case canvas.KeyDownEvent:
		// ...
	}
}

func (d *demo) update() {
	// ...
}

func (d *demo) draw(ctx *canvas.Context) {
	// ...
}

Note that the canvas.CloseEvent does not have to be explicitly enabled. It is always enabled.

Alternatives

2D game engines:

License

This project is free and open source software licensed under the BSD 3-Clause License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].