Add touch/pointer event support to Blazor views and revamp sample app#3528
Add touch/pointer event support to Blazor views and revamp sample app#3528
Conversation
|
@copilot we need to add this to the GL view as well. |
source/SkiaSharp.Views/SkiaSharp.Views.Blazor/wwwroot/SKTouchInterop.ts
Outdated
Show resolved
Hide resolved
source/SkiaSharp.Views/SkiaSharp.Views.Blazor/Internal/SKTouchCallbackHelper.cs
Outdated
Show resolved
Hide resolved
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
There was a problem hiding this comment.
Pull request overview
Adds opt-in pointer/touch event support to the Blazor SKCanvasView and SKGLView, aligning the event args/enums shape with MAUI for source compatibility and forwarding browser pointer/wheel events via JS interop.
Changes:
- Move/share
SKTouchEventArgs+ related enums intoSkiaSharp.Views.Sharedwith__MAUI__/__BLAZOR__namespace switching. - Add Blazor JS + C# interop (
SKTouchInterop.*,SKTouchCallbackHelper) to capture pointer/wheel events and forward them to .NET. - Add
TouchandEnableTouchEventsparameters toSKCanvasView/SKGLViewand implement async disposal for JS cleanup.
Reviewed changes
Copilot reviewed 9 out of 11 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| source/SkiaSharp.Views/SkiaSharp.Views.Shared/SKTouchEventArgs.cs | Shared touch event args/enums with MAUI/Blazor namespace switching. |
| source/SkiaSharp.Views/SkiaSharp.Views.Blazor/wwwroot/SKTouchInterop.ts | Pointer/wheel event listeners and mapping to touch args payload. |
| source/SkiaSharp.Views/SkiaSharp.Views.Blazor/wwwroot/SKTouchInterop.js | Built JS asset for the touch interop module. |
| source/SkiaSharp.Views/SkiaSharp.Views.Blazor/wwwroot/SKTouchInterop.js.map | Source map for the built touch interop JS. |
| source/SkiaSharp.Views/SkiaSharp.Views.Blazor/SkiaSharp.Views.Blazor.csproj | Includes shared touch types in Blazor build. |
| source/SkiaSharp.Views/SkiaSharp.Views.Blazor/SKCanvasView.razor.cs | Adds Touch/EnableTouchEvents, creates/disposes touch interop. |
| source/SkiaSharp.Views/SkiaSharp.Views.Blazor/SKGLView.razor.cs | Adds Touch/EnableTouchEvents, creates/disposes touch interop. |
| source/SkiaSharp.Views/SkiaSharp.Views.Blazor/Internal/SKTouchInterop.cs | Manages JS module lifetime and listener initialization/disposal. |
| source/SkiaSharp.Views/SkiaSharp.Views.Blazor/Internal/SKTouchCallbackHelper.cs | Receives [JSInvokable] callbacks and forwards payloads to C# handlers. |
| source/SkiaSharp.Views.Maui/SkiaSharp.Views.Maui.Core/SkiaSharp.Views.Maui.Core.csproj | Includes shared touch types in MAUI build. |
| .gitignore | Ignores .nuget/ artifacts. |
Comments suppressed due to low confidence (1)
source/SkiaSharp.Views/SkiaSharp.Views.Shared/SKTouchEventArgs.cs:5
using Microsoft.Maui;is now wrapped in#if __MAUI__, but this file no longer references anyMicrosoft.Mauitypes, so the using is unused and can generate warnings in MAUI builds. Consider removing it (or adding an alias/usage if still intended).
source/SkiaSharp.Views/SkiaSharp.Views.Blazor/SKCanvasView.razor.cs
Outdated
Show resolved
Hide resolved
source/SkiaSharp.Views/SkiaSharp.Views.Blazor/wwwroot/SKTouchInterop.ts
Outdated
Show resolved
Hide resolved
source/SkiaSharp.Views/SkiaSharp.Views.Blazor/wwwroot/SKTouchInterop.ts
Outdated
Show resolved
Hide resolved
source/SkiaSharp.Views/SkiaSharp.Views.Blazor/wwwroot/SKTouchInterop.ts
Outdated
Show resolved
Hide resolved
source/SkiaSharp.Views/SkiaSharp.Views.Blazor/SKCanvasView.razor.cs
Outdated
Show resolved
Hide resolved
source/SkiaSharp.Views/SkiaSharp.Views.Blazor/SKGLView.razor.cs
Outdated
Show resolved
Hide resolved
mattleibow
left a comment
There was a problem hiding this comment.
@copilot Please look at how we did interop for other features and make sure to match that.
source/SkiaSharp.Views/SkiaSharp.Views.Blazor/SKCanvasView.razor.cs
Outdated
Show resolved
Hide resolved
source/SkiaSharp.Views/SkiaSharp.Views.Blazor/Internal/SKTouchInterop.cs
Outdated
Show resolved
Hide resolved
Refactored all touch interop to match the existing patterns in commit d047799:
Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
mattleibow
left a comment
There was a problem hiding this comment.
@copilot Please update the blazor basic sample to now use these touch events and remove the other attributes.
Also address the comments
- Home: gradient background with scattered circles and feature overview - Raster: simplified to pure rendering demo (shapes, gradient, text) - GPU: polished description for animated SKGLView clock - Drawing (NEW): interactive canvas with touch drawing, mouse wheel brush size control (v120 delta), pressure sensitivity, color picker, and clear button — demonstrates touch, wheel, and Handled feedback - NavMenu: updated with all four page links Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Home: gradient + circles landing page (SKCanvasView basics) - GPU: pure SkSL lava lamp with 6 metaballs, touch interaction, SKRuntimeEffect.BuildShader() + Uniforms + Build() pattern - Drawing: touch/pointer drawing with wheel brush size control, pressure sensitivity, color picker, overlaid toolbar - Remove redundant Raster page (covered by Home + Drawing) - Full-viewport flex layout with overflow: hidden - Add detailed comments for new users learning SkiaSharp - Update NavMenu with GPU card and pencil icons Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract all inline CSS from GPU.razor and Drawing.razor into page-scoped stylesheets (GPU.razor.css, Drawing.razor.css). Only dynamic values (color swatch backgrounds) remain inline. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Extract GPU and Drawing code to .razor.cs partial classes - Use C# 11 raw string literal for SkSL shader source - Make DrawingStroke a record - Remove unused SKGLView ref from GPU page - Remove pen pressure logic from Drawing for simplicity - Initialize shader builder as a field instead of lazy in render Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Revert code-behind split — keep everything in single .razor files for simplicity. Use @"" verbatim string for SkSL since Razor doesn't support C# 11 raw string literals. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move @code blocks to .razor.cs code-behind partial classes to enable C# 11 raw string literals (triple-quote) for the SkSL shader source. Razor markup stays in .razor files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Razor compiler doesn't support C# 11 raw string literals until .NET 10. Use @"" verbatim strings for SkSL and keep everything in single .razor files for simplicity. Delete code-behind files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Lift reusable SKPaint to readonly fields with target-typed new() - Use collection expression syntax instead of new[] - Add period-terminated comments on fields - Wrap <p> content across multiple lines - Add blank line after @code { Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run |
|
No pipelines are associated with this pull request. |
|
/azp run |
|
No pipelines are associated with this pull request. |
The file lives in SkiaSharp.Views.Shared which is compiled by SkiaSharp.Views.csproj for native platforms (iOS, Android, etc.) via a wildcard include. Those platforms define neither __MAUI__ nor __BLAZOR__, so the namespace block was stripped and the bare braces caused CS1513/CS1022. Wrapping the entire file ensures it compiles to nothing on native platform builds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run |
|
No pipelines are associated with this pull request. |
Co-authored-by: mattleibow <1096616+mattleibow@users.noreply.github.com>
|
Closing this as we do not want to be adding APIs to platforms. And there is no need to actually, the events are fine. |
Description
Adds touch/pointer event support to the Blazor
SKCanvasViewandSKGLViewcomponents, and revamps the Blazor WebAssembly sample app into a three-page showcase of SkiaSharp capabilities.Touch/pointer event system
Shared touch types
SKTouchAction,SKTouchDeviceType,SKMouseButton, andSKTouchEventArgsare moved fromSkiaSharp.Views.Maui.CoretoSkiaSharp.Views.Sharedwith#if __BLAZOR__/#if __MAUI__namespace switching — the same shared-file pattern used bySKPaintSurfaceEventArgs.JS interop (
SKTouchInterop.ts)A class-based module (matching the
SizeWatcher/DpiWatcherpattern) that:pointer*andwheelevents on the canvas element.SKTouchAction/SKMouseButton/SKTouchDeviceTypeenum values.Handledreturn value.Handledistrue: callspreventDefault()+stopPropagation()(e.g., blocks page scrolling for handled wheel events).Handledisfalse: browser default behavior is preserved.start()adds all listeners withsetPointerCapture;stop()removes them and releases capture.C# interop (
SKTouchInterop.cs)Inherits from
JSModuleInteropwith#if NET7_0_OR_GREATERsplit:[JSImport]static partial methods withFunc<JSObject, bool>callback. TheJSObjectproxy is disposed viausing var _after property extraction to prevent GC/finalizer pressure from high-frequency pointer events.DotNetObjectReference<SKTouchCallbackHelper>with[JSInvokable] bool OnPointerEvent(...).View changes (
SKCanvasView&SKGLView)New component parameters:
TouchAction<SKTouchEventArgs>?EnableTouchEventsboolfalse(default), no JS listeners are attachedThe JS module is imported on first render but listeners are not attached until
EnableTouchEventsis set totrue. Toggling at runtime callsStart()/Stop()to fully connect/disconnect all JS event listeners.Blazor sample app revamp
The basic Blazor WebAssembly sample is rebuilt from the ground up into three pages:
SKFont/SKTextBlob, andSKCanvasViewbasicsSKGLViewwith a real-time SkSL metaball shader, touch interaction (drag to attract blobs), and FPS overlaySample features exercised
SKCanvasViewwithOnPaintSurface(Home)SKGLViewwithEnableRenderLoopandOnPaintSurface(GPU)Pressed,Moved,Released,WheelChanged(Drawing, GPU)Handledfeedback loop — blocks page scroll during drawing, allows scroll on HomeSKRuntimeEffect.BuildShaderwith SkSL (GPU)SKPathstroke recording and replay (Drawing).razor.cssfor component-level styling (GPU, Drawing)API Changes
Added:
enum SKTouchAction { Entered, Pressed, Moved, Released, Cancelled, Exited, WheelChanged }(shared)enum SKTouchDeviceType { Touch, Mouse, Pen }(shared)enum SKMouseButton { Unknown, Left, Middle, Right }(shared)class SKTouchEventArgs : EventArgs— Id, ActionType, DeviceType, MouseButton, Location, InContact, WheelDelta, Pressure, Handled (shared)Action<SKTouchEventArgs>? SKCanvasView.Touchbool SKCanvasView.EnableTouchEventsAction<SKTouchEventArgs>? SKGLView.Touchbool SKGLView.EnableTouchEventsMoved (no breaking change):
SKTouchEventArgs,SKTouchAction,SKTouchDeviceType,SKMouseButtonmoved fromSkiaSharp.Views.Maui.Core/SKTouchEventArgs.cstoSkiaSharp.Views.Shared/SKTouchEventArgs.cswith conditional namespace via#if __BLAZOR__/#if __MAUI__Behavioral Changes
Touch events are opt-in via
EnableTouchEvents="true". Whenfalse(default), no JS event listeners are attached. Existing usage is unaffected.When touch events are enabled:
e.Handled = true→ JS callspreventDefault()/stopPropagation()on the browser evente.Handled = false(default) → browser default behavior is preservedUsage
PR Checklist
tests/SkiaSharp.Views.Blazor.Testswith bUnit)