Viewer.js库是一个实用的js库,用于图片浏览,放大缩小翻转幻灯片播放等实用操作

本文相关参考链接

  1. JavaScript 模块中的 JavaScript 隔离
  2. Viewer.js工程

Blazor JS 隔离优势

导入的 JS 不再污染全局命名空间。

库和组件的使用者不需要导入相关的 JS。即不需要再在ssr的 Pages/_Host.cshtml 或 Pages/_Layout.cshtml ,wasm的 wwwroot/index.html 里写

第一遍载入静态资产请求包含值为 no-cache 或 max-age(值为零 (0))的 标头。真正页面组件使用才载入真实大小文件。

正式开始

1. 打开VS2020, 新建工程面板, 项目模板搜索 blazor , 选择Blazor Server应用. (wasm也可以,但是不好调试,先从简单的SSR入手)

2. 工程名称改为Blazor100,下一步,默认设置, 保存.



3. 右键点击wwwroot文件夹,添加lib文件夹,添加viewerjs子文件夹,里面添加viewerjs.js文件 . 最终版本参考如下



4. 编写js文件. 首先在这个步骤我们使用在线版本的js库,这样操作和理解都比较简单. 然后是一个title函数,用于使用图片alt和索引信息生成viewer.js组件的标题, viewer.js组件初始化. 接下来是注销组件过程.
viewer.js代码
import 'https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.10.3/viewer.min.js';
var viewer = null;
export function initOptions(options) {
options.title = function (image) {
return image.alt + ' (' + (this.index + 1) + '/' + this.length + ')';
};
//options.hidden= function () {
// viewer.destroy();
//};
if (undefined !== options.toolbarlite && options.toolbarlite == true) {
options.toolbar = {
zoomIn: true,
zoomOut: true,
//rotateLeft: true,
rotateRight: true,
//prev: true,
//next: true,
};
}
if (undefined !== viewer && null !== viewer && options.id == viewer.element.id) {
viewer.destroy();
console.log(viewer.element.id, 'destroy');
}
viewer = new Viewer(document.getElementById(options.id), options);
console.log(viewer.element.id);
}
export function destroy(options) {
if (undefined !== viewer && null !== viewer && options.id == viewer.element.id) {
viewer.destroy();
console.log(viewer.element.id, 'destroy');
}
}
5. 新建Components文件夹 , 新建Viewerjs.razor组件

组件的命名空间统一使用Blazor100.Components,在razor文件和razor.cs都使用统一命名空间,这样不会受到文件夹嵌套各种影响.

Viewerjs.razor代码
@implements IAsyncDisposable
@inject IJSRuntime JS
@namespace Blazor100.Components @if (UseBuiltinImageDiv)
{
<div class="docs-galley mb-3" style="height: @Height;width:@Width; ">
<ul id="@Options.id" class="docs-pictures clearfix">
@{
var i = 0;
foreach (var item in Images)
{
var alt = (Alts != null && Alts.Any() && Alts.Count > i) ? Alts[i] : (item.Split('/').Last());
<li><img src="@item" alt="@alt"></li>
i++;
}
}
</ul>
</div>
} <link href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.10.3/viewer.min.css" rel="stylesheet" /> @code{
/// <summary>
/// 使用内置图片DIV
/// </summary>
[Parameter] public bool UseBuiltinImageDiv { get; set; } = true; /// <summary>
/// 图片列表
/// </summary>
[Parameter] public List<string> Images { get; set; } = new List<string>(); /// <summary>
/// 单图片
/// </summary>
[Parameter] public string? Src { get; set; } /// <summary>
/// 图片名称列表
/// </summary>
[Parameter] public List<string>? Alts { get; set; } /// <summary>
/// 组件初始化参数
/// </summary>
[Parameter] public ViewerOptions Options { get; set; } = new ViewerOptions(); /// <summary>
/// 简化版工具条
/// </summary>
[Parameter] public bool? toolbarlite { get; set; } /// <summary>
/// 高
/// </summary>
[Parameter] public string? Height { get; set; } = "400px"; /// <summary>
/// 宽
/// </summary>
[Parameter] public string? Width { get; set; } = "400px"; /// <summary>
/// 组件ID
/// </summary>
[Parameter] public string? ID { get; set; } private IJSObjectReference? module; protected override void OnInitialized()
{
Options ??= new ViewerOptions();
if (toolbarlite != null) Options.toolbarlite = toolbarlite.Value;
if (!string.IsNullOrEmpty(ID)) Options.id = ID; else Options.id = Guid.NewGuid().ToString();
Images ??= new List<string>();
if (Src != null)
Images.Add(Src);
else if (!Images.Any())
{
for (int i = 1; i <= 9; i++)
{
Images.Add("./favicon.ico");
}
}
} protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import", "/lib/viewerjs/viewerjs.js");
await module.InvokeVoidAsync("initOptions", Options);
}
} public async Task OnOptionsChanged(ViewerOptions options) => await module!.InvokeVoidAsync("initOptions", options); async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
await module.InvokeVoidAsync("destroy", Options);
await module.DisposeAsync();
}
}
}
6. 添加 Viewerjs.razor.css 文件.
Viewerjs.razor.css代码
.docs-galley {
padding: 10px;
width: 400px;
} .docs-pictures {
list-style: none;
margin: 0;
padding: 0;
} .docs-pictures > li {
border: 1px solid transparent;
float: left;
height: calc(100% / 3);
margin: 0 -1px -1px 0;
overflow: hidden;
width: calc(100% / 3);
} .docs-pictures > li > img {
cursor: -webkit-zoom-in;
cursor: zoom-in;
width: 100%;
} img {
vertical-align: middle;
border-style: none;
}
7. 图片浏览器选项类

类命名空间统一使用Blazor100.Components,在.cs都使用统一命名空间.

Viewerjs.razor代码
using System.ComponentModel;

namespace Blazor100.Components;

/// <summary>
/// 图片浏览器选项类
/// </summary>
public class ViewerOptions
{
/// <summary>
/// 图片浏览器选项
/// </summary>
/// <param name="id"></param>
/// <param name="fullscreen"></param>
public ViewerOptions(string id = "images", bool fullscreen = true)
{
this.id = id;
this.fullscreen = fullscreen;
}
public string id { get; set; } = "images"; /// <summary>
/// 简化版工具条
/// </summary>
public bool toolbarlite { get; set; }
public string container { get; set; } = "body"; /// <summary>
/// 背景遮罩
/// </summary>
[DisplayName("背景遮罩")]
public bool backdrop { get; set; } = true; /// <summary>
/// 右上角的关闭按钮
/// </summary>
[DisplayName("关闭按钮")]
public bool button { get; set; } = true; public bool focus { get; set; } = true; /// <summary>
/// 全屏
/// </summary>
[DisplayName("全屏")]
public bool fullscreen { get; set; } = true; /// <summary>
/// 内联/模态模式
/// </summary>
[DisplayName("内联/模态模式")]
public bool inline { get; set; } = false; /// <summary>
///
/// </summary>
public int interval { get; set; } = 5000; /// <summary>
/// 键盘导航快捷键
/// </summary>
[DisplayName("键盘导航快捷键")]
public bool keyboard { get; set; } = true; /// <summary>
///
/// </summary>
public bool loading { get; set; } = true; /// <summary>
/// 循环播放
/// </summary>
[DisplayName("循环播放")]
public bool loop { get; set; } = true; /// <summary>
///
/// </summary>
public int maxZoomRatio { get; set; } = 100; /// <summary>
///
/// </summary>
public int minHeight { get; set; } = 100; /// <summary>
///
/// </summary>
public int minWidth { get; set; } = 200; /// <summary>
///
/// </summary>
public double minZoomRatio { get; set; } = 0.01; /// <summary>
/// 可移动
/// </summary>
[DisplayName("可移动")]
public bool movable { get; set; } = true; /// <summary>
/// 导航
/// </summary>
[DisplayName("导航")]
public bool navbar { get; set; } = true; /// <summary>
/// 可旋转
/// </summary>
[DisplayName("可旋转")]
public bool rotatable { get; set; } = true; /// <summary>
/// 可缩放
/// </summary>
[DisplayName("可缩放")]
public bool scalable { get; set; } = true; /// <summary>
/// 滑动触摸
/// </summary>
[DisplayName("滑动触摸")]
public bool slideOnTouch { get; set; } = true; /// <summary>
/// 标题
/// </summary>
[DisplayName("标题")]
public bool title { get; set; } = true; /// <summary>
/// 双击切换
/// </summary>
[DisplayName("双击切换")]
public bool toggleOnDblclick { get; set; } = true; /// <summary>
/// 工具栏
/// </summary>
[DisplayName("工具栏")]
public bool toolbar { get; set; } = true; /// <summary>
/// 工具提示
/// </summary>
[DisplayName("工具提示")]
public bool tooltip { get; set; } = true; /// <summary>
/// 过渡效果
/// </summary>
[DisplayName("过渡效果")]
public bool transition { get; set; } = true; /// <summary>
/// 触摸缩放
/// </summary>
[DisplayName("触摸缩放")]
public bool zoomOnTouch { get; set; } = true; /// <summary>
/// 滚轮缩放
/// </summary>
[DisplayName("触摸缩放")]
public bool zoomOnWheel { get; set; } = true; /// <summary>
/// 缩放率
/// </summary>
[DisplayName("缩放率")]
public double zoomRatio { get; set; } = 0.1; /// <summary>
/// 可缩放
/// </summary>
[DisplayName("可缩放")]
public bool zoomable { get; set; } = true;
}
8. Pages文件添加ViewerPage.razor文件,用于演示组件调用
Viewerjs.razor代码
@page "/viewer"

<Viewerjs Images="imagesList" />

@code{
List<string>? imagesList; protected override void OnInitialized()
{
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");
}
}
} }
9. _Imports.razor加入一行引用组件的命名空间
@using Blazor100.Components

10. 首页引用组件演示页 <ViewerPage />

11. F5运行程序,将会自动打开浏览器调试

至此,使用JS隔离封装的viewerjs库大功告成!

如果需要断网环境使用此库,需要把库文件和css文件下载放到wwwroot/lib/viewerjs文件夹里面,上面两个文件需要修改一下:

步骤4的viewer.js代码


import 'https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.10.3/viewer.min.js';

import '/lib/viewerjs/viewer.min.js';


步骤5的Viewerjs.razor代码


href="https://cdnjs.cloudflare.com/ajax/libs/viewerjs/1.10.3/viewer.min.css"

href="/lib/viewerjs/viewer.min.css"


Blazor组件自做系列

Blazor组件自做一 : 使用JS隔离封装viewerjs库

Blazor组件自做二 : 使用JS隔离制作手写签名组件

Blazor组件自做三 : 使用JS隔离封装ZXing扫码

Blazor组件自做四: 使用JS隔离封装signature_pad签名组件

Blazor组件自做五: 使用JS隔离封装Google地图<03-24>

Blazor组件自做六: 使用JS隔离封装Baidu地图<03-25>

Blazor组件自做七: 使用JS隔离制作定位/持续定位组件<03-26>

Blazor组件自做八: 使用JS隔离封装屏幕键盘kioskboard.js组件<03-27>

项目源码 Github | Gitee

Blazor组件自做一 : 使用JS隔离封装viewerjs库的更多相关文章

  1. Blazor组件自做八 : 使用JS隔离封装屏幕键盘kioskboard.js组件

    1. 运行截图 演示地址 2. 在文件夹wwwroot/lib,添加kioskboard子文件夹,添加kioskboards.js文件 2.1 常规操作,懒加载js库, export function ...

  2. Blazor组件自做三 : 使用JS隔离封装ZXing扫码

    Blazor组件自做三 : 使用JS隔离封装ZXing扫码 本文基础步骤参考前两篇文章 Blazor组件自做一 : 使用JS隔离封装viewerjs库 Blazor组件自做二 : 使用JS隔离制作手写 ...

  3. Blazor组件自做四 : 使用JS隔离封装signature_pad签名组件

    运行截图 演示地址 响应式演示 感谢szimek写的棒棒的signature_pad.js项目, 来源: https://github.com/szimek/signature_pad 正式开始 1. ...

  4. Blazor组件自做五 : 使用JS隔离封装Google地图

    Blazor组件自做五: 使用JS隔离封装Google地图 运行截图 演示地址 正式开始 1. 谷歌地图API 谷歌开发文档 开始学习 Maps JavaScript API 的最简单方法是查看一个简 ...

  5. Blazor组件自做六 : 使用JS隔离封装Baidu地图

    1. 运行截图 演示地址 2. 在文件夹wwwroot/lib,添加baidu子文件夹,添加baidumap.js文件 2.1 跟上一篇类似,用代码方式异步加载API,脚本生成新的 body > ...

  6. Blazor组件自做二 : 使用JS隔离制作手写签名组件

    Blazor组件自做二 : 使用JS隔离制作手写签名组件 本文相关参考链接 JavaScript 模块中的 JavaScript 隔离 Viewer.js工程 Blazor组件自做一 : 使用JS隔离 ...

  7. Blazor组件自做九: 用20行代码实现文件上传,浏览目录功能 (3)

    接上篇 Blazor组件自做九: 用20行代码实现文件上传,浏览目录功能 (2) 7. 使用配置文件指定监听地址 打开 appsettings.json 文件,加入一行 "UseUrls&q ...

  8. 【Node.js 自己封装的库 http_parse, libuv】

    [Node.js 自己封装的库 http_parse, libuv] Node.js 介绍:一个网络框架,更多:http://www.oschina.net/p/nodejs 官网:http://no ...

  9. Blazor组件自做十一 : File System Access 文件系统访问 组件

    Blazor File System Access 文件系统访问 组件 Web 应用程序与用户本地设备上的文件进行交互 File System Access API(以前称为 Native File ...

随机推荐

  1. 被广泛使用的OAuth2.0的密码模式已经废了,放弃吧

    最近一直有同学在问,OAuth2密码模式为啥Spring Security还没有实现,就连新的Spring Authorization Server也没有这个玩意儿. 其实这里可以告诉大家,OAuth ...

  2. ffmpeg修改视频文件的分辨率

    在本文中,我们将展示如何调整任何视频文件的大小. 这种方法是在Linux系统(几乎任何发行版)中调整视频文件大小的最佳方法之一,也是Windows和Mac用户的绝佳替代方案. 更改视频文件的分辨率将是 ...

  3. 一些JDK自带的性能分析利器

    有时候碰到服务器CPU飙升或者程序卡死之类的问题,一般都不太好定位.这类bug一般都隐藏的比较深并且还可能是偶发性的,比较棘手. 对于此类问题,一般我们都有固定的分析流程.借助于JDK自带的一些分析工 ...

  4. pycharm实用常用快捷键

    我们在实用pycharm时候,可以使用一些快捷键来帮助我们写代码. 1 alt + enter 快速导包,在需要导入包时候可以使用这个快捷键: 2 alt + 1 可以快速打开或者关闭左侧projec ...

  5. CSI 工作原理与JuiceFS CSI Driver 的架构设计详解

    容器存储接口(Container Storage Interface)简称 CSI,CSI 建立了行业标准接口的规范,借助 CSI 容器编排系统(CO)可以将任意存储系统暴露给自己的容器工作负载.Ju ...

  6. RabbitMQ Go客户端教程6——RPC

    本文翻译自RabbitMQ官网的Go语言客户端系列教程,本文首发于我的个人博客:liwenzhou.com,教程共分为六篇,本文是第六篇--RPC. 这些教程涵盖了使用RabbitMQ创建消息传递应用 ...

  7. RDMA相关的技术网站

    https://www.cnblogs.com/vlhn/p/7909893.html https://www.cnblogs.com/vlhn/ 这个家伙的博客写的还不错,可以参考.

  8. 亚马逊云储存器S3 BCUKET安全性学习笔记

    亚马逊云储存器S3 BCUKET安全性学习笔记 Bugs_Bunny CTF – Walk walk CTF 昨天玩了会这个比赛,碰到这题是知识盲点,来记录一下. 先从题目看起吧. http://ww ...

  9. Windows&Linux文件传输方式总结

    在渗透过程中,通常会需要向目标主机传送一些文件,来达到权限提升.权限维持等目的,本篇文章主要介绍一些windows和Linux下常用的文件传输方式. Windows 利用FTP协议上传 在本地或者VP ...

  10. linux安装maven环境

    linux安装maven环境 一. 下载压缩包: 官网地址: http://maven.apache.org/download.cgi 或者百度网盘链接:https://pan.baidu.com/s ...