using Blazor.Extensions.Canvas.Canvas2D; using Blazor.Extensions; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components; using Microsoft.JSInterop; using Newtonsoft.Json.Linq; using Newtonsoft.Json; using StackExchange.Redis; namespace BlazorCanvas.Server.Components.Data; // https://www.codeproject.com/Articles/5269947/Drawing-with-the-HTML-Canvas-Element-in-Blazor-Ser public class CanvasService { private Canvas2DContext? _currentCanvasContext; private IJSRuntime _jsRuntime; private IConnectionMultiplexer _cache; private ChannelMessageQueue _channel; private CanvasCommand _lastCommand = new(); private bool _is_started = false; public CanvasService(IJSRuntime jsRuntime, IConnectionMultiplexer cache) { _jsRuntime = jsRuntime; _cache = cache; _channel = _cache.GetSubscriber().Subscribe(RedisChannel.Literal("lol")); } public string currentColor { get; set; } = "Black"; public int pointSize { get; set; } = 1; public bool snap { get; set; } public ElementReference divCanvas { get; set; } public BECanvasComponent myCanvas { get; set; } = new(); public async void Consume() { CancellationToken cToken = new(); while (!cToken.IsCancellationRequested) { var mess = await _channel.ReadAsync(cToken); var comm = JsonConvert.DeserializeObject(mess.Message); if (comm is not null) Draw(comm); } } public async void Draw(IEnumerable lsCommand) { if (_currentCanvasContext is null) { _currentCanvasContext = await myCanvas.CreateCanvas2DAsync(); await _currentCanvasContext.ClearRectAsync(0, 0, 1920, 1080); } await _currentCanvasContext.BeginBatchAsync(); foreach (CanvasCommand command in lsCommand) { await _currentCanvasContext.SetFillStyleAsync(command.Color); await _currentCanvasContext.FillRectAsync(command.X, command.Y, command.PointSize, command.PointSize); } await _currentCanvasContext.EndBatchAsync(); } public async void Draw(CanvasCommand command) { if (_currentCanvasContext is null) { _currentCanvasContext = await myCanvas.CreateCanvas2DAsync(); await _currentCanvasContext.ClearRectAsync(0, 0, 1920, 1080); } await _currentCanvasContext.SetFillStyleAsync(command.Color); await _currentCanvasContext.FillRectAsync(command.X, command.Y, command.PointSize, command.PointSize); } public async void HandleMouse(MouseEventArgs eventArgs) { double mouseX = 0, mouseY = 0; if (!_is_started) { Consume(); _is_started = true; } if (eventArgs.Buttons == 0 || eventArgs.Buttons > 2) return; // Rien faire si aucun bouton est appuyé ou si les deux boutons/ d'autres boutons sont appuyés. if (divCanvas.Id?.Length > 0) { string data = await _jsRuntime.InvokeAsync("getDivCanvasOffsets", new object[] { divCanvas }); string color = "White"; CanvasCommand command = new(); JObject? offsets = (JObject?)JsonConvert.DeserializeObject(data); if (offsets is not null && offsets.HasValues) { // Translation entre le canvas et la souris. mouseX = eventArgs.PageX - offsets.Value("offsetLeft"); mouseY = eventArgs.PageY - offsets.Value("offsetTop"); } if (eventArgs.Buttons == 1) // Couleur si bouton gauche, blanc si bouton droit color = currentColor; if (snap) { // Magnétisme boboche. mouseX -= mouseX % pointSize; mouseY -= mouseY % pointSize; } command.X = mouseX; command.Y = mouseY; command.Color = color; command.PointSize = pointSize; if (command.Equals(_lastCommand)) return; // Pour pas spammer des commandes si c'est pas pertinent. // TODO: Shipper les commandes à Franz. _cache.GetSubscriber().Publish(RedisChannel.Literal("lol"), JsonConvert.SerializeObject(command)); //Draw(command); _lastCommand = command; } } }