Giter Site home page Giter Site logo

kristofferstrube / distributeddrawing Goto Github PK

View Code? Open in Web Editor NEW
25.0 1.0 3.0 10.22 MB

A distributed drawing tool written in Blazor Wasm that uses an external SignalR Hub to sync drawings between clients.

HTML 61.15% C# 7.33% CSS 14.38% JavaScript 17.14%
blazor webassembly wasm svg draw collaboration creative signalr blazor-webassembly github-actions

distributeddrawing's Introduction

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

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 <Line /> 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 package by the people behind 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 <Line /> 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's project DrawTogether.NET.

Backend

The backend is not part of this repo, but it's not the most complex if you are familiar with SignalR.

public class StaticStorage
{
    public static IList<Line> draws = new List<Line>();
    public static IDictionary<string, string> users = new Dictionary<string, string>();
}
    
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<IList<Line>>(fs);
            }
        }
        await base.OnConnectedAsync();
    }

    public async Task<int> CountLines()
    {
        return StaticStorage.draws.Count();
    }

    public async IAsyncEnumerable<Line> StartLines([EnumeratorCancellation]
    CancellationToken cancellationToken)
    {
        foreach (Line line in StaticStorage.draws)
        {
            cancellationToken.ThrowIfCancellationRequested();

            yield return line;
        }
    }

    public async Task<List<string>> 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();
    }
}

distributeddrawing's People

Contributors

kristofferstrube avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

distributeddrawing's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.