简体   繁体   English

使用 Javascript 获取 Blazor 页面的大小

[英]Getting the size of a Blazor page with Javascript

I'm learning JSInterop with Blazor. I would like to get the width and the height of a Blazor page in oder to size à canvas.我正在学习 Blazor 的 JSInterop。我想获得 Blazor 页面的宽度和高度,大小为 à canvas。

I'm using the default Blazor template with the menu bar on the left part of the screen.我正在使用默认的 Blazor 模板和屏幕左侧的菜单栏。 在此处输入图像描述

On the html part of the Canvas Test 1 page I have:在 Canvas 测试 1 页的 html 部分,我有:

@page "/canvas_test1"
@inject IJSRuntime JsRuntime
<canvas @ref="canvas1"></canvas>
<button @onclick="SetCanvasSize">Set canvas size</button>

In the code part I have:在代码部分我有:

ElementReference canvas1;
async Task SetCanvasSize()
{
    await JsRuntime.InvokeVoidAsync("SetCanvasSize", canvas1);
}

In the Javascript file I have:在 Javascript 文件中,我有:

function SetCanvasSize(element) {
ctx = element.getContext('2d');
console.log(window.innerWidth);
console.log(document.documentElement.scrollWidth);
}

But both methodes window.innerWidth and document.documentElement.scrollWidth give the width of the entire window not only the page that contains the canvas.但是window.innerWidthdocument.documentElement.scrollWidth这两种方法都给出了整个 window 的宽度,而不仅仅是包含 canvas 的页面。

How can I get the width of only the page without the side menu?如何在没有侧面菜单的情况下仅获取页面的宽度?

Thank you谢谢

I think you're a little confused about what a Page is in Blazor. It's basically a component that you provide a route to for navigation.我认为您对 Blazor 中的页面是什么感到有点困惑。它基本上是您提供导航路径的组件。 If you include a layout (which is usually set by default), that is in fact part of the page.如果您包括布局(通常默认设置),那实际上是页面的一部分。 All the things on the page, like your canvas, are just html elements.页面上的所有内容,例如您的 canvas,都只是 html 个元素。 It is correctly telling you the size of the window, which you can see will change if you resize your browser.它正确地告诉您 window 的大小,如果您调整浏览器的大小,您可以看到它会发生变化。

html elements have the properties "offsetWidth" and "offsetHeight." html 元素具有属性“offsetWidth”和“offsetHeight”。 So, for your use you want to pass the element to measure, and use element.offsetWidth :因此,为了您的使用,您想要传递要测量的元素,并使用element.offsetWidth

function GetCanvasSize(element) {
     alert ("Element measurements: " + element.offsetWidth + ", " + element.offsetHeight);
}

You can see more of the members of html elements here, including common methods and events: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth你可以在这里看到html元素的更多成员,包括常用的方法和事件: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth

Note that this list is missing some important things you'd like to know, especially the various touch events which you'll need for dragging elements on mobile clients (mouse events won't work on phones).请注意,此列表缺少您想要了解的一些重要信息,尤其是您在移动客户端上拖动元素所需的各种触摸事件(鼠标事件在手机上不起作用)。

You need to get the dimensions of the containing element.您需要获取包含元素的尺寸。 You also need to listen for resizing events.您还需要监听调整大小事件。

I use a service that can take a ref for any element and listen for changes.我使用的服务可以为任何元素获取 ref 并监听更改。

bCore.js

export function listenToWindowResize(dotNetHelper) {

    function resizeEventHandler() {
        dotNetHelper.invokeMethodAsync('WindowResizeEvent');
    }

    window.addEventListener("resize", resizeEventHandler);

    dotNetHelper.invokeMethodAsync('WindowResizeEvent');
}

export function getBoundingRectangle(element, parm) {
    return element.getBoundingClientRect();
}

export function getWindowSizeDetails(parm) {

    var e = window, a = 'inner';

    if (!('innerWidth' in window)) {
        a = 'client';
        e = document.documentElement || document.body;
    }

    let windowSize =
    {
        innerWidth: e[a + 'Width'],
        innerHeight: e[a + 'Height'],
        screenWidth: window.screen.width,
        screenHeight: window.screen.height
    };

    return windowSize;
}

JSInteropCoreService.cs

public class JSInteropCoreService : IJSInteropCoreService, IAsyncDisposable
{
    private readonly Lazy<Task<IJSObjectReference>> moduleTask;
    private bool isResizing;
    private System.Timers.Timer resizeTimer;
    private DotNetObjectReference<JSInteropCoreService> jsInteropCoreServiceRef;

    public JSInteropCoreService(IJSRuntime jsRuntime)
    {
        this.resizeTimer = new System.Timers.Timer(interval: 25);
        this.isResizing = false;
        this.resizeTimer.Elapsed += async (sender, elapsedEventArgs) => await DimensionsChanged(sender!, elapsedEventArgs);

        this.moduleTask = new(() => jsRuntime.InvokeAsync<IJSObjectReference>(
          identifier: "import", args: "./_content/BJSInteroptCore/bCore.js").AsTask());
    }

    public event NotifyResizing OnResizing;
    public event NotifyResize OnResize;

    public async ValueTask InitializeAsync()
    {
        IJSObjectReference module = await GetModuleAsync();

        this.jsInteropCoreServiceRef = DotNetObjectReference.Create(this);

        await module.InvokeVoidAsync(identifier: "listenToWindowResize", this.jsInteropCoreServiceRef);

        this.BrowserSizeDetails = await module.InvokeAsync<BrowserSizeDetails>(identifier: "getWindowSizeDetails");

    }

    public async ValueTask<BrowserSizeDetails> GetWindowSizeAsync()
    {
        IJSObjectReference module = await GetModuleAsync();
        return await module.InvokeAsync<BrowserSizeDetails>(identifier: "getWindowSizeDetails");
    }

    public async ValueTask<ElementBoundingRectangle> GetElementBoundingRectangleAsync(ElementReference elementReference)
    {
        IJSObjectReference module = await GetModuleAsync();
        return await module.InvokeAsync<ElementBoundingRectangle>(identifier: "getBoundingRectangle", elementReference);
    }

    [JSInvokable]
    public ValueTask WindowResizeEvent()
    {
        if (this.isResizing is not true)
        {
            this.isResizing = true;
            OnResizing?.Invoke(this.isResizing);
        }
        DebounceResizeEvent();
        return ValueTask.CompletedTask;
    }

    public BrowserSizeDetails BrowserSizeDetails { get; private set; } = new BrowserSizeDetails();

    private void DebounceResizeEvent()
    {
        if (this.resizeTimer.Enabled is false)
        {
            Task.Run(async () =>
            {
                this.BrowserSizeDetails = await GetWindowSizeAsync();
                isResizing = false;
                OnResizing?.Invoke(this.isResizing);
                OnResize?.Invoke();
            });
            this.resizeTimer.Restart();
        }
    }

    private async ValueTask DimensionsChanged(object sender, System.Timers.ElapsedEventArgs e)
    {
        this.resizeTimer.Stop();
        this.BrowserSizeDetails = await GetWindowSizeAsync();
        isResizing = false;
        OnResizing?.Invoke(this.isResizing);
        OnResize?.Invoke();
    }

    public async ValueTask DisposeAsync()
    {
        if (moduleTask.IsValueCreated)
        {
            IJSObjectReference module = await GetModuleAsync();
            await module.DisposeAsync();
        }
    }

    private async Task<IJSObjectReference> GetModuleAsync()
        => await this.moduleTask.Value;
}
public class ElementBoundingRectangle
{
    public double X { get; set; }
    public double Y { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }
    public double Top { get; set; }
    public double Right { get; set; }
    public double Bottom { get; set; }
    public double Left { get; set; }
}
public class BrowserSizeDetails
{
    public double InnerWidth { get; set; }
    public double InnerHeight { get; set; }
    public int ScreenWidth { get; set; }
    public int ScreenHeight { get; set; }
}

I debounce the resize events using a 25ms interval to prevent lag.我使用 25 毫秒的间隔对调整大小事件进行去抖动以防止延迟。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM