viewerjs+vue3 using typescript

news/2025/10/31 22:16:12/文章来源:https://www.cnblogs.com/geovindu/p/19181370

安装包

npm install v-viewer viewerjs
npm i fontawesome-4.7
npm install @fortawesome/fontawesome-svg-core
npm install @fortawesome/free-solid-svg-icons
npm install @fortawesome/vue-fontawesome@prerelease
npm install @fortawesome/free-regular-svg-icons
npm install @fortawesome/free-brands-svg-icons
npm install viewerjs @types/viewerjs --save

  

main.ts

/** @creater: geovindu* @since: 2025-06-24 20:03:42* @LastAuthor: geovindu* @lastTime: 2025-10-31 22:06:13* @文件相对于项目的路径: \jsstudy\markmapdemo\src\main.ts* @message: geovindu* @IDE: vscode* @Development: node.js 20, vuejs3.0* @package: * @ISO: windows10* @database: mysql 8.0 sql server 2019 postgresSQL 16 * Copyright (c) 2025 by geovindu email:geovindu@163.com, All Rights Reserved.*/
import './assets/main.css'import { createApp } from 'vue'
import { createPinia } from 'pinia'import App from './App.vue'
import router from './router'
import Viewer from 'viewerjs';
import "fontawesome-4.7/css/font-awesome.css";
import { library } from '@fortawesome/fontawesome-svg-core';
import { faUserSecret } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';import 'viewerjs/dist/viewer.css';
Viewer.setDefaults({navbar: true,title: true,toolbar: {prev: true,next: true,},
});const app = createApp(App)
.component('font-awesome-icon', FontAwesomeIcon)
app.use(createPinia())
app.use(router)
app.use(() => Viewer); 
app.mount('#app')

  

<template><div class="about"><h1>This is an about page</h1></div>
<!-- 图片容器 -->
<div ref="viewerContainer" style="margin: 20px;"><imgv-for="src in images":key="src":src="getThumbnail(src)":data-src="src":alt="extractFilename(src)"class="viewer-image"/></div></template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import Viewer from 'viewerjs';
import 'viewerjs/dist/viewer.css';// 🔹 定义类型
type ImageSrc = string;// 🔹 图片列表(类型化)
const images = ref<ImageSrc[]>(['1.png','2.jpg','3.jpg',
]);// 🔹 提取文件名(带类型)
const extractFilename = (url: string): string => {try {const pathname = new URL(url, location.origin).pathname;const filename = pathname.split('/').pop() || 'image';return filename.split('?')[0].split('#')[0]; // 去除查询参数} catch (e) {const match = url.match(/[^/\\?#]+(?=[^/\\]*$)/);return match ? match[0] : 'image';}
};// 🔹 缩略图生成函数
const getThumbnail = (url: string): string => {if (url.includes('picsum.photos')) {return url.replace(/(\d+)\/(\d+)/, '200/150');}return url;
};// 🔹 Viewer 容器引用
const viewerContainer = ref<HTMLDivElement | null>(null);
let viewer: Viewer | null = null;// 🔹 下载处理函数
const handleDownload = (): void => {if (!viewer || !viewer.image) return;const currentImage = viewer.image;const filename = extractFilename(currentImage.src);const tempImage = new Image();tempImage.crossOrigin = 'Anonymous';tempImage.onload = () => {const canvas = document.createElement('canvas');canvas.width = tempImage.width;canvas.height = tempImage.height;const ctx = canvas.getContext('2d');if (!ctx) return;ctx.drawImage(tempImage, 0, 0);const ext = filename.split('.').pop()?.toLowerCase() || 'jpeg';const mimeTypeMap: Record<string, string> = {jpg: 'image/jpeg',jpeg: 'image/jpeg',png: 'image/png',gif: 'image/gif',webp: 'image/webp',bmp: 'image/bmp',};const mimeType = mimeTypeMap[ext] || 'image/jpeg';const dataUrl = canvas.toDataURL(mimeType, 0.95);const a = document.createElement('a');a.href = dataUrl;a.download = filename;document.body.appendChild(a);a.click();document.body.removeChild(a);};tempImage.onerror = () => {const a = document.createElement('a');a.href = currentImage.src;a.download = filename;a.target = '_blank';a.rel = 'noopener noreferrer';document.body.appendChild(a);a.click();document.body.removeChild(a);};tempImage.src = currentImage.src;
};// 🔹 组件生命周期
onMounted(() => {if (viewerContainer.value) {viewer = new Viewer(viewerContainer.value, {url: 'data-src',toolbar: {zoomIn: true,zoomOut: true,oneToOne: true,reset: true,prev: true,next: true,download: {show: true,//size: 'large',click() {handleDownload();},},},navbar: true,title: (image: HTMLImageElement) => extractFilename(image.src),viewed() {console.log('查看:', extractFilename(viewer?.image.src || ''));},});}
});onUnmounted(() => {if (viewer) {viewer.destroy();viewer = null;}
});
</script>
<style>
@media (min-width: 1024px) {.about {min-height: 100vh;display: flex;align-items: center;}
}
</style>

  

输出:

c1a72cfd5fcc1a2591e5fbaae74a91ed

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/952255.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

题解:B4207 [常州市赛 2021] 战士

题解:B4207 [常州市赛 2021] 战士 前言 题目传送门 思路讲解 思路其实很好想,因为怪物的攻击是固定的,所以战士的死亡时间也是固定的,我们就需要通过计算战士每次死亡前能造成的最大伤害如果可以击败怪物,那就直接…

最小二乘问题详解7:正则化最小二乘

本文系统阐述了正则化最小二乘(岭估计)的动机、理论推导、求解方法与数值实例,揭示其通过L2惩罚项改善病态问题和过拟合的机制。1. 引言 在之前的文章《最小二乘问题详解4:非线性最小二乘》、《最小二乘问题详解5:…

什么是重组蛋白?

重组蛋白的定义与基本概念 重组蛋白是指通过基因工程技术,将外源基因导入宿主细胞,利用细胞的生物合成系统表达产生的蛋白质分子。这项技术的核心在于基因重组,即通过人工手段将编码目标蛋白的DNA序列插入表达载体,…

Day9文字颜色

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">…

代码大全2{3}

高质量代码要易理解、易扩展。书中关于类设计、接口定义的原则,结合具体示例讲解如何降低代码耦合度,逻辑清晰且实用性强。“单一职责原则” 避免 “万能类 / 函数”带来的问题,划分职责界限,比如一个 “用户管理”…

work3

这个作业属于哪个课程:https://edu.cnblogs.com/campus/fzu/gjyycx 这个作业要求在哪里: https://edu.cnblogs.com/campus/fzu/gjyycx/homework/13574 学号:102500331 姓名:余武 一.书本第4章4.8编程练习题目中的第…

25.10.31

AGC001D 很早之前看到一度怀疑是错题,然后今天发现我看错题了,原来是说这个序列只包含一种元素啊…… 一个 \(l\) 长的回文串定下了 \(\frac{l}{2}\) 的等价关系,可以视作连边,于是转化出图论模型。 考虑无解是为什…

关于计数

随时施工( 不欢迎来看感觉必须开一个记录计数trick的专栏了,md计数题的式子太e心了(((((

游记2

等出分了,进NOIP了写。

JSON Web Token安全漏洞实战:无需确认令牌验证邮箱与密码重置

本文详细介绍了如何通过篡改JSON Web Token实现邮箱验证绕过、密码重置和账户接管,包含具体的技术操作步骤和漏洞利用方法,展示了JWT在未正确验证签名时的安全风险。玩转JSON Web Token:乐趣与收益并存 大家好,希望…

软考-关于《网络安全法》修订相关题目(10道)

根据2025年10月28日通过的《网络安全法》修改决定,该修正案将于何时正式施行?A. 2025年11月1日 B. 2025年12月1日 C. 2026年1月1日 D. 2026年3月1日 答案:C 解析:文章明确指出"自2026年1月1日起施行"。新…

【算法初步】1插入排序

【算法初步】1插入排序using System;class InsertionSortExample {static void Main(){// 测试数组int[] array = { 12, 11, 13, 5, 6 };Console.WriteLine("排序前的数组:");PrintArray(array);// 执行插入…

WebRTC实时音视频通信核心原理

寻常的WebSocket流程是这样的如果都与服务器进行交流,会造成服务器压力大,通讯时间长,实时效果不好,那么怎么解决? 这就要用到我们接下来讲的WebRTC实时通讯 拿出笔记本,让我们开冲!! 概念 WebRTC(Web Real-Ti…

Python高阶和匿名函数 _ 脱了马甲也要认识

Python高阶和匿名函数 _ 脱了马甲也要认识def calculate_and_print(num, calculator, formatter): result = calculator(num) formatter(num, result)def print_with_vertical_bar(num, result): print(f&quo…

第11天(中等题 滑动窗口)

打卡第十一天 1道简单题+2道中等题越短越合法型滑动窗口: 实例由于子数组越长,乘积越大,越不能满足题目要求;反之,子数组越短,乘积越小,越能满足题目要求。有这种性质的题目,可以用滑动窗口解决。内层循环结束后…

麒麟 V10系统中离线安装python的setuptools和pip,并使用python代码查询达梦数据库,并上传文件到minio

麒麟 V10系统中默认安装了python3.7版本,但是没有安装pip命令 1.python 环境安装1.下载Python版本对用的 setuptools和pip版本 源码包下载地址:setuptools:https://pypi.org/project/setuptools/#files(选择.tar.g…

如何选择陶瓷放电管

陶瓷放电管GDT原理:气体放电。电管有一脉冲击穿电压,不工作状态是电路处于断路,电阻大,电容小。一旦脉冲过压达到放电管的脉冲击穿电压,极间的电场强度超过气体的击穿强度时,就引起间隙放电,管内气体电离,放电…

10.31每日总结

10.31每日总结学习了软考的知识,总结回顾了周一学的画图的东西

对称密钥算法 非对称密钥算法 Hash函数 公钥和私钥在网络安全中的应用流程超超超详细,清楚,简单!!!

不是哥们,理解了半天,感觉自己是天才😎😎😎 一、对称密钥算法(私钥加密) 对称密钥算法也称为私钥加密,这里的 “私钥” 指的是 “秘密的、需要保密的密钥” ,而不是非对称体系中的“私钥”。它强调的是这个…

读《代码大全2》读后感3

书中对 “变量命名与代码逻辑梳理” 的讲解。之前在写小程序的报名统计功能时,我把存储用户信息的变量命名为 “user1”“user2”,还把数据筛选、统计、导出的逻辑揉在一个函数里。后来社团换届,新成员接手代码时,…