赞
踩
本文基础步骤参考前两篇文章
Blazor组件自做一 : 使用JS隔离封装viewerjs库
+zxing
|-qrcode.min.js
|-zxing.min.js
+zxing
|-zxingjs.js
import '/lib/zxing/zxing.min.js'; var codeReader = null; export function init(autostop, wrapper, options) { console.log('autostop' + autostop); let selectedDeviceId; //const codeReader = new ZXing.BrowserBarcodeReader() codeReader = new ZXing.BrowserMultiFormatReader() console.log('ZXing code reader initialized') codeReader.getVideoInputDevices() .then((videoInputDevices) => { const sourceSelect = document.getElementById('sourceSelect') selectedDeviceId = videoInputDevices[0].deviceId console.log('videoInputDevices:' + videoInputDevices.length); if (videoInputDevices.length > 1) { videoInputDevices.forEach((element) => { const sourceOption = document.createElement('option') sourceOption.text = element.label sourceOption.value = element.deviceId sourceSelect.appendChild(sourceOption) selectedDeviceId = element.deviceId; }) sourceSelect.onchange = () => { selectedDeviceId = sourceSelect.value; codeReader.reset(); StartScan(); } const sourceSelectPanel = document.getElementById('sourceSelectPanel') sourceSelectPanel.style.display = 'block' } StartScan(autostop); document.getElementById('startButton').addEventListener('click', () => { StartScan(); }) function StartScan(autostop) { codeReader.decodeOnceFromVideoDevice(selectedDeviceId, 'video').then((result) => { console.log(result) document.getElementById('result').textContent = result.text var supportsVibrate = "vibrate" in navigator; if (supportsVibrate) navigator.vibrate(1000); if (autostop) { console.log('autostop'); codeReader.reset(); return wrapper.invokeMethodAsync("invokeFromJS", result.text); } else { console.log('None-stop'); codeReader.reset(); wrapper.invokeMethodAsync("invokeFromJS", result.text); } }).catch((err) => { console.error(err) document.getElementById('result').textContent = err }) console.log(`Started continous decode from camera with id ${selectedDeviceId}`) } document.getElementById('resetButton').addEventListener('click', () => { document.getElementById('result').textContent = ''; codeReader.reset(); console.log('Reset.') }) document.getElementById('closeButton').addEventListener('click', () => { document.getElementById('result').textContent = ''; codeReader.reset(); console.log('closeButton.') wrapper.invokeMethodAsync("invokeFromJSClose"); }) }) .catch((err) => { console.error(err) }) } export function destroy(options) { if (undefined !== codeReader && null !== codeReader && options.id == codeReader.element.id) { codeReader.destroy(); console.log(codeReader.element.id, 'destroy'); } }
参考阅读:ASP.NET Core Blazor 路由和导航
同理,Pages/HandwrittenPage.razor文件的 @page “/handwritten” 也是一样作用
<Viewerjs Images="imagesList" /> 直接调用Viewerjs组件,Images是组件的参数,打开文件Components/Viewerjs.razor可以查看定义
/// <summary>
/// 图片列表
/// </summary>
[Parameter] public List<string> Images { get; set; } = new List<string>();
@page "/viewer" //页面的路由地址 <Viewerjs Images="imagesList" /> //调用Viewerjs组件,指定组件图片列表数据来源 @code{ List<string>? imagesList; protected override void OnInitialized() //组件初始化 , [参考阅读:组件生命周期](https://docs.microsoft.com/zh-cn/aspnet/core/blazor/components/lifecycle?view=aspnetcore-6.0) { //生成演示图片数据 imagesList = new List<string>(); if (!imagesList.Any()) { for (int i = 1; i <= 9; i++) { imagesList.Add($"https://fengyuanchen.github.io/viewerjs/images/thumbnails/tibet-{i}.jpg"); } } } }
现在Pages/Index.razor已经直接放置了两个占用空间比较大的组件,再加入今天的组件势必很难看,我们将对首页以及左侧导航菜单做一些调整,以便条理更加清晰.
删除Pages/Index.razor文件中以下代码
<ViewerPage />
<hr />
<HandwrittenPage />
打开Shared/NavMenu.razor添加相关导航,NavLink组件是Blazor默认自带导航组件, 参考阅读:NavLink 类
<div class="nav-item px-3"> <NavLink class="nav-link" href="viewer"> <span class="oi oi-plus" aria-hidden="true"></span> 图片浏览 </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="handwritten"> <span class="oi oi-plus" aria-hidden="true"></span> 手写签名 </NavLink> </div> <div class="nav-item px-3"> <NavLink class="nav-link" href="barcodescanner"> <span class="oi oi-plus" aria-hidden="true"></span> 条码扫描 </NavLink> </div>
DotNetObjectReference.Create(this)
[JSInvokable("invokeFromJS")]
public async Task ChangeValue(string val)
{
Result = val;
StateHasChanged();
await ScanResult.InvokeAsync(val);
}
import '/lib/zxing/zxing.min.js' //模块的方式加载zxing库
//定义一个函数init供blazor组件调用
export function init(autostop, wrapper, options) {} //wrapper为blazor组件的实例
//扫码结果通过blazor组件的实例调用DotNet.invokeMethodAsync实现
wrapper.invokeMethodAsync("invokeFromJS", result.text);
private IJSObjectReference? module;
module = await JS.InvokeAsync<IJSObjectReference>("import", "./lib/zxing/zxingjs.js");
module.InvokeVoidAsync("init", true, DotNetObjectReference.Create(this), null);
@implements IAsyncDisposable @namespace Blazor100.Components @inject IJSRuntime JS <div class="modal alert-popup" tabindex="-1" style="display:block" role="dialog"> <div class="modal-dialog"> <div class="modal-content"> <!-- Edit form for the current item --> <div class="modal-body"> <button class="btn btn-primary p-2 m-1 w-25" id="startButton">@ScanBtnTitle</button> <button class="btn btn-secondary p-2 m-1 w-25" id="resetButton">@ResetBtnTitle</button> <button type="button" class="btn btn-info p-2 m-1 w-25" id="closeButton">@CloseBtnTitle</button> <div id="sourceSelectPanel" style="display:none"> <label for="sourceSelect">@SelectDeviceBtnTitle:</label><span class="text-dark" id="result"></span> <select id="sourceSelect" style="max-width:100%" class="form-control"> </select> </div> <div> <video id="video" style="min-height:150px;max-height:60%; max-width: 100%;border: 1px solid gray"></video> </div> </div> </div> </div> </div> @Result @code { /// <summary> /// BarcodeScanner 条码扫描 /// </summary> /// <summary> /// 扫码按钮文本/Scan button title /// </summary> [Parameter] public string ScanBtnTitle { get; set; } = "扫码"; /// <summary> /// 复位按钮文本/Reset button title /// </summary> [Parameter] public string ResetBtnTitle { get; set; } = "复位"; /// <summary> /// 关闭按钮文本/Close button title /// </summary> [Parameter] public string CloseBtnTitle { get; set; } = "关闭"; /// <summary> /// 选择设备按钮文本/Select device button title /// </summary> [Parameter] public string SelectDeviceBtnTitle { get; set; } = "选择设备"; /// <summary> /// 扫码结果回调方法/Scan result callback method /// </summary> [Parameter] public EventCallback<string> ScanResult { get; set; } /// <summary> /// 关闭扫码框回调方法/Close scan code callback method /// </summary> [Parameter] public EventCallback Close { get; set; } /// <summary> /// 扫码结果/Scan result /// </summary> [Parameter] public string? Result { get; set; } /// <summary> /// 显示扫码框/Show scan box /// </summary> [Parameter] public bool ShowScanBarcode { get; set; } private IJSObjectReference? module; // To prevent making JavaScript interop calls during prerendering protected override async Task OnAfterRenderAsync(bool firstRender) { try { if (!firstRender) return; module = await JS.InvokeAsync<IJSObjectReference>("import", "./lib/zxing/zxingjs.js"); await module.InvokeVoidAsync("init", true, DotNetObjectReference.Create(this), null); //组件实例封装:DotNetObjectReference.Create(this) } catch (Exception e) { if (OnError != null) await OnError.Invoke(e.Message); } } [JSInvokable("invokeFromJS")] public async Task ChangeValue(string val) { Result = val; StateHasChanged(); await ScanResult.InvokeAsync(val); } [JSInvokable("invokeFromJSClose")] public async Task CloseScan() { await Close.InvokeAsync(null); } /// <summary> /// 获得/设置 错误回调方法 /// </summary> [Parameter] public Func<string, Task>? OnError { get; set; } async ValueTask IAsyncDisposable.DisposeAsync() { if (module is not null) { //await module.InvokeVoidAsync("destroy", Options); await module.DisposeAsync(); } } }
@page "/barcodescanner" <h3>条码扫描 BarcodeReader</h3> <h4>扫描条码/QR码。</h4> <button class="btn btn-primary" type="button" @onclick="(() => ShowScanBarcode = !ShowScanBarcode)"> 扫码 </button> <input type="text" class="form-control" style="min-width: 100px;" @bind-value="BarCode" placeholder="条码" /> @if (ShowScanBarcode) { <BarcodeScanner ScanResult="((e) => { BarCode=e; ShowScanBarcode = !ShowScanBarcode; })" ShowScanBarcode="ShowScanBarcode" Close="(()=>ShowScanBarcode=!ShowScanBarcode)" /> } <p>@message</p> @code{ /// <summary> /// 显示扫码界面 /// </summary> bool ShowScanBarcode { get; set; } = false; /// <summary> /// 条码 /// </summary> public string? BarCode { get; set; } private string? message; private Task OnError(string message) { this.message = message; StateHasChanged(); return Task.CompletedTask; } }
@using Blazor100.Components
<BarcodeScannerPage />
或者Shared/NavMenu.razor添加导航 <div class="nav-item px-3">
<NavLink class="nav-link" href="barcodescanner">
<span class="oi oi-plus" aria-hidden="true"></span> 条码扫描
</NavLink>
</div>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。