You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Blazor Web App WASM客户端项目中添加鼠标平移与缩放功能

实现Blazor布局的鼠标平移与Ctrl+滚轮缩放功能

1. 创建JavaScript工具文件

在客户端项目的wwwroot目录下新建js文件夹,创建zoomPan.js文件并写入以下代码:

let zoomPanState = {
    isDragging: false,
    startX: 0,
    startY: 0,
    currentTranslateX: 0,
    currentTranslateY: 0,
    currentScale: 1,
    targetElement: null
};

export function initZoomPan(element) {
    zoomPanState.targetElement = element;
    
    // 绑定平移相关事件
    element.addEventListener('mousedown', handleMouseDown);
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
    // 绑定缩放事件
    element.addEventListener('wheel', handleWheel);
}

export function destroyZoomPan() {
    if (!zoomPanState.targetElement) return;
    
    // 移除事件监听,避免内存泄漏
    zoomPanState.targetElement.removeEventListener('mousedown', handleMouseDown);
    document.removeEventListener('mousemove', handleMouseMove);
    document.removeEventListener('mouseup', handleMouseUp);
    zoomPanState.targetElement.removeEventListener('wheel', handleWheel);
    zoomPanState.targetElement = null;
}

function handleMouseDown(e) {
    e.preventDefault();
    zoomPanState.isDragging = true;
    // 记录鼠标初始位置与元素当前偏移的差值
    zoomPanState.startX = e.clientX - zoomPanState.currentTranslateX;
    zoomPanState.startY = e.clientY - zoomPanState.currentTranslateY;
    zoomPanState.targetElement.style.cursor = 'grabbing';
}

function handleMouseMove(e) {
    if (!zoomPanState.isDragging) return;
    e.preventDefault();
    
    // 计算新的偏移量
    zoomPanState.currentTranslateX = e.clientX - zoomPanState.startX;
    zoomPanState.currentTranslateY = e.clientY - zoomPanState.startY;
    
    updateElementTransform();
}

function handleMouseUp() {
    zoomPanState.isDragging = false;
    zoomPanState.targetElement.style.cursor = 'grab';
}

function handleWheel(e) {
    if (!e.ctrlKey) return;
    e.preventDefault();
    
    // 控制缩放比例,每次滚轮调整10%,限制缩放范围在0.1-5倍
    const scaleFactor = e.deltaY > 0 ? 0.9 : 1.1;
    zoomPanState.currentScale = Math.max(0.1, Math.min(5, zoomPanState.currentScale * scaleFactor));
    
    // 基于鼠标位置计算缩放后的偏移,保证缩放围绕鼠标点
    const rect = zoomPanState.targetElement.getBoundingClientRect();
    const mouseX = e.clientX - rect.left;
    const mouseY = e.clientY - rect.top;
    
    zoomPanState.currentTranslateX = mouseX - (mouseX - zoomPanState.currentTranslateX) * scaleFactor;
    zoomPanState.currentTranslateY = mouseY - (mouseY - zoomPanState.currentTranslateY) * scaleFactor;
    
    updateElementTransform();
}

function updateElementTransform() {
    zoomPanState.targetElement.style.transform = `translate(${zoomPanState.currentTranslateX}px, ${zoomPanState.currentTranslateY}px) scale(${zoomPanState.currentScale})`;
    zoomPanState.targetElement.style.transformOrigin = '0 0';
    zoomPanState.targetElement.style.willChange = 'transform';
}

2. 在自定义布局中集成功能

修改你的布局组件代码,添加JS互操作与元素引用:

@inherits LayoutComponentBase
@inject IJSRuntime JSRuntime
@implements IAsyncDisposable

<main @ref="mainElement" style="cursor: grab; overflow: hidden; touch-action: none;">
    <article>
        @Body
    </article>
</main>

@code {
    private ElementReference mainElement;
    private IJSObjectReference? _zoomPanModule;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            // 加载JS模块并初始化功能
            _zoomPanModule = await JSRuntime.InvokeAsync<IJSObjectReference>(
                "import", "./js/zoomPan.js");
            await _zoomPanModule.InvokeVoidAsync("initZoomPan", mainElement);
        }
    }

    public async ValueTask DisposeAsync()
    {
        // 组件销毁时清理资源
        if (_zoomPanModule is not null)
        {
            await _zoomPanModule.InvokeVoidAsync("destroyZoomPan");
            await _zoomPanModule.DisposeAsync();
        }
    }
}

3. 功能说明

  • 平移操作:按住鼠标左键拖动main区域即可平移页面内容,松开鼠标结束平移。
  • 缩放操作:按住Ctrl键滚动鼠标滚轮,将围绕当前鼠标位置进行缩放,缩放范围限制在0.1-5倍(可自行修改JS代码中的Math.max和Math.min参数调整范围)。
  • 体验优化:添加了拖拽状态的光标样式,禁用触摸设备默认手势避免干扰,开启硬件加速提升动画流畅度。

内容的提问来源于stack exchange,提问作者user27339040

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 19:51:17