https://github.com/kristofferstrube/distributeddrawing
A distributed drawing tool written in Blazor Wasm that uses an external SignalR Hub to sync drawings between clients.
https://github.com/kristofferstrube/distributeddrawing
blazor blazor-webassembly collaboration creative draw github-actions github-pages signalr svg wasm webassembly
Last synced: 5 months ago
JSON representation
A distributed drawing tool written in Blazor Wasm that uses an external SignalR Hub to sync drawings between clients.
- Host: GitHub
- URL: https://github.com/kristofferstrube/distributeddrawing
- Owner: KristofferStrube
- Created: 2020-06-18T13:44:12.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-12-27T03:23:45.000Z (almost 2 years ago)
- Last Synced: 2025-05-07T03:04:09.248Z (5 months ago)
- Topics: blazor, blazor-webassembly, collaboration, creative, draw, github-actions, github-pages, signalr, svg, wasm, webassembly
- Language: HTML
- Homepage:
- Size: 9.98 MB
- Stars: 27
- Watchers: 1
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# DistributedDrawing
A distributed drawing tool that uses an external SignalR Hub to sync drawings between clients. It also saves the drawings automatically.## Demo
It can be demoed at [kristofferstrube.github.io/DistributedDrawing](https://kristofferstrube.github.io/DistributedDrawing/)## Frontend
I have experimented with a couple of different ways to draw the lines.The first approach was to add a `@foreach` loop that renders `` tags in the SVG using razor syntax, but that caused a big delay as all previous lines had to be drawn each time a single line was added
Next I looked at using the [Canvas](https://github.com/BlazorExtensions/Canvas) package by the people behind [BlazorExtensions](https://github.com/BlazorExtensions). This used a canvas instead to render lines which is very effective compared to SVG elements. I had a working version of this, but I did not continue with this as I wanted to be able to potentially manipulate the drawn elements in the future without having to learn how to use graphics libraries.
Next I looked at using JSInterop to add/clear `` tags from JavaScript, so that I knew that Blazor would not handle when these are rendered.
I have later found that you can do this smarter by creating a component for a SVG `line` like I helped doing in [PetaBridge](https://github.com/petabridge)'s project [DrawTogether.NET](https://github.com/petabridge/DrawTogether.NET/blob/dev/src/DrawTogether.UI/Server/Components/Curve.razor#L16).
## Backend
The backend is not part of this repo, but it's not the most complex if you are familiar with SignalR.```csharp
public class StaticStorage
{
public static IList draws = new List();
public static IDictionary users = new Dictionary();
}
public class DrawHub : Hub
{
private readonly string drawingPath = "drawing.draw";public override async Task OnConnectedAsync()
{
if (StaticStorage.draws.Count() == 0)
{
using (FileStream fs = File.OpenRead(drawingPath))
{
StaticStorage.draws = await JsonSerializer.DeserializeAsync>(fs);
}
}
await base.OnConnectedAsync();
}public async Task CountLines()
{
return StaticStorage.draws.Count();
}public async IAsyncEnumerable StartLines([EnumeratorCancellation]
CancellationToken cancellationToken)
{
foreach (Line line in StaticStorage.draws)
{
cancellationToken.ThrowIfCancellationRequested();yield return line;
}
}public async Task> StartUsers(string user)
{
StaticStorage.users.Add(Context.ConnectionId, user);
await Clients.Others.SendAsync("ReceiveUsers", StaticStorage.users.Values.ToList());
return StaticStorage.users.Values.ToList();
}public override async Task OnDisconnectedAsync(Exception exception)
{
StaticStorage.users.Remove(Context.ConnectionId);
await Clients.Others.SendAsync("ReceiveUsers", StaticStorage.users.Values.ToList());
using (FileStream fs = File.Create(drawingPath))
{
await JsonSerializer.SerializeAsync(fs, StaticStorage.draws);
}
await base.OnDisconnectedAsync(exception);
}public async Task Draw(double prevX, double prevY, double currX, double currY, string color, float lineWidth)
{
await Clients.Others.SendAsync("ReceiveDraw", prevX, prevY, currX, currY, color, lineWidth);
StaticStorage.draws.Add(new Line(prevX, prevY, currX, currY, color, lineWidth));
}public async Task Clear()
{
await Clients.All.SendAsync("ReceiveClear");
StaticStorage.draws.Clear();
}
}
```