excubo-ag / Blazor.Canvas

https://excubo-ag.github.io/Blazor.Canvas/
MIT License
220 stars 23 forks source link

Save Paths and isPointInStroke() #157

Closed bearsystems closed 2 years ago

bearsystems commented 2 years ago

Thank you again for providing this awesome addition to the Blazor world! I have been using the Canvas for a little while now with great results but I am faced with a new challenge.

I now need to add in click events for a number of lines being drawn between objects. From what I have found online, to accomplish this task, I need to store each line as a Path2D() object and then check to see if a given mouse click occurs on any of those paths (https://stackoverflow.com/questions/45993483/how-to-use-multiple-click-event-on-a-canvas).

I have tried everything I can in the editor, and looked through all of the source files in your Components examples, but I am unable to figure out how to enable this capability.

I do see the Paths.BeginPathsAsync() and the .isPointInPathAsync() calls but I do not see a way to register those paths between calls and then to maintain the paths lists. In my case, people can draw any number of lines and I need to track all of those paths between calls and know which path has been clicked in order to provide the correct Modal Window.

Can you please let me know if your support these features and, if so, how they are implemented?

Thank you!

stefanloerwald commented 2 years ago

Hi @bearsystems,

When we implemented this library, we had to make clear decisions about what's included and what's not. We decided to exclude creation of Path2D objects.

It is nonetheless possible. You will have to write your own code to create paths and store them. When you draw them, use Fill/StrokeAsync(string path) (see https://github.com/excubo-ag/Blazor.Canvas/blob/main/Canvas/Contexts/Context2D_DrawingPaths.cs#L27-L40). You can see from the implementation that you can put quite arbitrary things as "path", because it's just pasted into the eval statement (yes, that can be abused! don't let users control that input directly). So if you created a window.path = new Path2D(...) somewhere in javascript, you can pass it to Fill/Stroke as "window.path". IsPointInPath follows the same pattern, so as long as you created that path in JS, you can use it there as well.

Here's how that would roughly look like:

function createPath(dataFromCSharp) {
   window.path = new Path2D(dataFromCSharp);
}
await JS.InvokeVoidAsync("createPath", myDataInCsharp);
await canvas.StrokeAsync("window.path");
bool result = await canvas.IsPointInPath("window.path", 1, 2, FillRule.NonZero);

Hope that helps, Stefan

bearsystems commented 2 years ago

Stefan –

        Thank you for the concept!  I really appreciate you putting this out for us to use and whatever decisions you made are just not up to me to complaint about!

I am trying to use Graphics Paths which is a C# option and I need to iterate through those on a mouse click on the canvas. That said, when I click on the canvas, the click event is not firing and I know clicks work as I have other objects that respond outside of the canvas without issue.

        Here is my HTML:

        <Excubo.Blazor.Canvas.Canvas @ref="lineCanvas" onclick="CheckForLines" id="underlyingCanvas" style="position: absolute; left: 0; top: 0; z-index: 1;" width="1285px" height="725px" />

        Here is my very simply click event handler and .NET supposedly injects the MouseEventsArgs for me.  I did try without any arguments but that failed as well.

        public void CheckForLines(MouseEventArgs e)

   {

}

        Is there some other way that I should be registering click events?  So you are aware, your canvas does not support the use of dynamic values in Blazor so I have to use standard HTML calls.

        Thank you!

https://www.facebook.com/BearManagedSystems/ https://www.linkedin.com/company/10503817/admin/ https://twitter.com/BearSystems

Ken Tola

CEO of Bear Systems

Email: @.> @.

https://BearSystems.com https://BearSystems.com

From: Stefan Lörwald @.> Sent: Wednesday, December 1, 2021 12:37 AM To: excubo-ag/Blazor.Canvas @.> Cc: bearsystems @.>; Mention @.> Subject: Re: [excubo-ag/Blazor.Canvas] Save Paths and isPointInStroke() (Issue #157)

Hi @bearsystems https://github.com/bearsystems ,

When we implemented this library, we had to make clear decisions about what's included and what's not. We decided to exclude creation of Path2D objects.

It is nonetheless possible. You will have to write your own code to create paths and store them. When you draw them, use Fill/StrokeAsync(string path) (see https://github.com/excubo-ag/Blazor.Canvas/blob/main/Canvas/Contexts/Context2D_DrawingPaths.cs#L27-L40). You can see from the implementation that you can put quite arbitrary things as "path", because it's just pasted into the eval statement (yes, that can be abused! don't let users control that input directly). So if you created a window.path = new Path2D(...) somewhere in javascript, you can pass it to Fill/Stroke as "window.path". IsPointInPath follows the same pattern, so as long as you created that path in JS, you can use it there as well.

Here's how that would roughly look like:

function createPath(dataFromCSharp) { window.path = new Path2D(dataFromCSharp); } await JS.InvokeVoidAsync("createPath", myDataInCsharp); await canvas.StrokeAsync("window.path"); bool result = await canvas.IsPointInPath("window.path", 1, 2, FillRule.NonZero);

Hope that helps, Stefan

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/excubo-ag/Blazor.Canvas/issues/157#issuecomment-983369273 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AK23UOBP6434X7TXR77ELRLUOXGBBANCNFSM5JCZLB5A . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub . https://github.com/notifications/beacon/AK23UOHPVOQX5UWZM6J5AL3UOXGBBA5CNFSM5JCZLB5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOHKOQMOI.gif

stefanloerwald commented 2 years ago

Hi @bearsystems,

have you tried replacing the canvas component by an html canvas element? The library offers the component merely as a slightly more convenient way of initializing the context, otherwise, the canvas element has some better characteristics (e.g. onclick & onclick:preventDefault only work on the element, not the component).

Have a nice weekend, Stefan