站酷设计网站官网入口下载,企业邮箱哪家更好用,湘西建设监理协会网站,网站开发进度把握文章目录 先实现正常的效果实现下载图片改变viewerjs的build函数源码改变之后#xff0c;执行npm i 之后node_modules源码又变回了原样 1、viwerjs所有功能都很完善#xff0c;但唯独缺少了图片的下载 2、需求#xff1a;在用viwerjs旋转图片后#xff0c;可以直接下载旋转… 文章目录 先实现正常的效果实现下载图片改变viewerjs的build函数源码改变之后执行npm i 之后node_modules源码又变回了原样 1、viwerjs所有功能都很完善但唯独缺少了图片的下载 2、需求在用viwerjs旋转图片后可以直接下载旋转后的图片 效果
先实现正常的效果
1、安装v-viewer(一个对viwerjs的使用方式优化的npm包)
npm i v-viewer2、
main.js文件 (vue2版本)
import Vue from vue
import App from ./App.vue
//哪怕使用v-viewer也需要导入正常的viwerjs的css文件
import viewerjs/dist/viewer.css
import Viewer from v-viewerVue.use(Viewer, {defaultOptions: {//里面可以填一些配置项这里我先不填}
})new Vue({render: h h(App),
}).$mount(#app)
app.vue文件中使用组件
templatediv classmainviewer refviewerimgsrchttps://img1.baidu.com/it/u413643897,2296924942fm253fmtautoapp138fJPEG?w800h500altdata-uiduid字段refimg//viewer/div
/template
scriptexport default {data() {return {};},props: {},watch: {},mounted() {},created() {},methods: {},};
/script
style scoped
/style
效果
实现下载图片
在main.js中添加配置项 可以先看下面build函数的改动再看main中的download
import Vue from vue
import App from ./App.vue
import viewerjs/dist/viewer.css
import Viewer from v-viewer
Vue.config.productionTip false
//可以先忽略base64toBlob函数就是个base64文件转blob的函数
function base64toBlob(dataurl) {var arr dataurl.split(,),mime arr[0].match(/:(.*?);/)[1],bstr atob(arr[1]),n bstr.length,u8arr new Uint8Array(n);while (n--) {u8arr[n] bstr.charCodeAt(n);}return new Blob([u8arr], {type: mime});
}
Vue.use(Viewer, {defaultOptions: {//下载事件的回调download(viewer) {//当前显示图片的索引const index viewer.index//所有图片构成的数组const list viewer.images//当前显示的图片const ima list[index]const canvas document.createElement(canvas) //获取canvas//对应的CanvasRenderingContext2D对象(画笔)let img new Image() //创建新的图片对象let base64 ; //base64 img.src ima.src ? new Date().getTime();//如果您仅仅是下载当前图片 img.src便是当前的图片地址 //下面的内容就完全可以不用看了//自行百度:前端拿到图片地址如何下载图片const rotate viewer.imageData.rotatelet x, yconst type rotate / 90 % 4img.setAttribute(crossOrigin, Anonymous)img.onload function () { //图片加载完再draw 和 toDataURLlet width img.widthlet height img.heightconst flg width height//这里写的不是很好(4个if判断)有更好的书写方式可以告知我一下除了(switch、改成object的形式)//0、1、2、3对应旋转0°、90°、180°、270°//0的时候不需要特处理if (type 0) {x 0;y 0} else if (type 1) {//1的时候需要考虑一种清空如果他是个矩形图片也就是宽高不相等//在旋转90°后我们需要调整canvas的宽高、同理270°一样x height;y 0;if (!flg) {const blg widthwidth heightheight blg}} else if (type 2) {x width;y height;} else if (type 3) {x 0;y height;if (!flg) {const blg widthwidth heightheight blg}}canvas.width widthcanvas.height heightlet ctx canvas.getContext(2d)ctx.translate(x, y);ctx.rotate(rotate * Math.PI / 180);ctx.drawImage(img, 0, 0, img.width, img.height);//图片转base64base64 canvas.toDataURL(image/png);//base64转链接该链接便是用户旋转后的图片了//如果想下载该图片直接定义a标签然后触发点击事件下载即可,可自行百度拿到链接如何下载链接的内容console.log(url___, URL.createObjectURL(base64toBlob(base64)));}}}
})new Vue({render: h h(App),router,
}).$mount(#app)
找到viwerjs源文件 /node_modules/viewerjs/dist/viewer.js 为什么不去v-viewer文件下找呢上面说了v-viewer是对viwwerjs的封装使用似乎没有改动源码 在该文件下搜索
toolbar.appendChild(list)该代码存在于build函数下面作用是构建底部的工具按钮
改变viewerjs的build函数
build函数源代码(看我写的注释) 其中注释最多的地方便是对源码的改动
{key: build,value: function build() {if (this.ready) {return;}//关键变量之一当前viewerjs挂载的domvar element this.element,//关键变量当前的viewer的option配置项options this.options;var parent element.parentNode;var template document.createElement(div);template.innerHTML TEMPLATE;var viewer template.querySelector(..concat(NAMESPACE, -container));var title viewer.querySelector(..concat(NAMESPACE, -title));//toolbar 关键变量之一下面代码是获取toolbar的dom元素var toolbar viewer.querySelector(..concat(NAMESPACE, -toolbar));var navbar viewer.querySelector(..concat(NAMESPACE, -navbar));var button viewer.querySelector(..concat(NAMESPACE, -button));var canvas viewer.querySelector(..concat(NAMESPACE, -canvas));this.parent parent;this.viewer viewer;this.title title;this.toolbar toolbar;this.navbar navbar;this.button button;this.canvas canvas;this.footer viewer.querySelector(..concat(NAMESPACE, -footer));this.tooltipBox viewer.querySelector(..concat(NAMESPACE, -tooltip));this.player viewer.querySelector(..concat(NAMESPACE, -player));this.list viewer.querySelector(..concat(NAMESPACE, -list));viewer.id .concat(NAMESPACE).concat(this.id);title.id .concat(NAMESPACE, Title).concat(this.id);addClass(title, !options.title ? CLASS_HIDE : getResponsiveClass(Array.isArray(options.title) ? options.title[0] : options.title));addClass(navbar, !options.navbar ? CLASS_HIDE : getResponsiveClass(options.navbar));toggleClass(button, CLASS_HIDE, !options.button);if (options.keyboard) {button.setAttribute(tabindex, 0);}if (options.backdrop) {addClass(viewer, .concat(NAMESPACE, -backdrop));if (!options.inline options.backdrop ! static) {setData(canvas, DATA_ACTION, hide);}}if (isString(options.className) options.className) {// In case there are multiple class namesoptions.className.split(REGEXP_SPACES).forEach(function (className) {addClass(viewer, className);});}if (options.toolbar) {var list document.createElement(ul);var custom isPlainObject(options.toolbar);var zoomButtons BUTTONS.slice(0, 3);var rotateButtons BUTTONS.slice(7, 9);var scaleButtons BUTTONS.slice(9);if (!custom) {addClass(toolbar, getResponsiveClass(options.toolbar));}//关键函数之一forEach是对传统foreach的1封装//BUTTONS关键变量之一是一个数组里面存放的是底部操作工具栏信息//下面的foreach的解读根据BUTTONS这个数组构建出底部工具栏按钮并且给对应的按钮添加一些属性信息forEach(custom ? options.toolbar : BUTTONS, function (value, index) {var deep custom isPlainObject(value);var name custom ? hyphenate(index) : value;var show deep !isUndefined(value.show) ? value.show : value;if (!show || !options.zoomable zoomButtons.indexOf(name) ! -1 || !options.rotatable rotateButtons.indexOf(name) ! -1 || !options.scalable scaleButtons.indexOf(name) ! -1) {return;}var size deep !isUndefined(value.size) ? value.size : value;var click deep !isUndefined(value.click) ? value.click : value;var item document.createElement(li);if (options.keyboard) {item.setAttribute(tabindex, 0);}item.setAttribute(role, button);addClass(item, .concat(NAMESPACE, -).concat(name));if (!isFunction(click)) {setData(item, DATA_ACTION, name);}if (isNumber(show)) {addClass(item, getResponsiveClass(show));}if ([small, large].indexOf(size) ! -1) {addClass(item, .concat(NAMESPACE, -).concat(size));} else if (name play) {addClass(item, .concat(NAMESPACE, -large));}if (isFunction(click)) {addListener(item, EVENT_CLICK, click);}list.appendChild(item);});toolbar.appendChild(list);} else {addClass(toolbar, CLASS_HIDE);}//代码走到这一步表示toolbar基本按钮已经配置完成了//在这里来添加我们自己想加的按钮//下面代码是我添加的功能//开始//isFunction判断传递的download是不是对象isFunction是viwerjs作者封装好的方法//addListener给某个dom元素添加事件监听同样是viwerjs作者封装好的//addListener(参数一是dom元素参数二是事件名称参数三是事件回调)//addListener会有参数4参数4是元素监听器的一些配置项非必填if(isFunction(options.download)){//创建保存按钮var download document.createElement(li)var that this//给按钮加事件addListener(download,EVENT_CLICK,function(){// options.download就是我上面main.js传递的download函数//在点击该按钮后同时执行download回调//传递参数that.element是viwerjs挂载的dom//that.element.viewerviwerjs挂载后会为挂载的元素添加viewer属性(巨全的属性里面啥都有)可以说我们拿到viewer基本所有的内容都可以拿到了options.download(that.element.viewer)})//addclass是别人封装好的给元素加类名加完类名后直接改变css样式就行了或者直接用行内styleaddClass(download,viewerjs-download)list.appendChild(download)}///结束if (!options.rotatable) {var rotates toolbar.querySelectorAll(li[class*rotate]);addClass(rotates, CLASS_INVISIBLE);forEach(rotates, function (rotate) {toolbar.appendChild(rotate);});}if (options.inline) {addClass(button, CLASS_FULLSCREEN);setStyle(viewer, {zIndex: options.zIndexInline});if (window.getComputedStyle(parent).position static) {setStyle(parent, {position: relative});}parent.insertBefore(viewer, element.nextSibling);} else {addClass(button, CLASS_CLOSE);addClass(viewer, CLASS_FIXED);addClass(viewer, CLASS_FADE);addClass(viewer, CLASS_HIDE);setStyle(viewer, {zIndex: options.zIndex});var container options.container;if (isString(container)) {container element.ownerDocument.querySelector(container);}if (!container) {container this.body;}container.appendChild(viewer);}if (options.inline) {this.render();this.bind();this.isShown true;}this.ready true;if (isFunction(options.ready)) {addListener(element, EVENT_READY, options.ready, {once: true});}if (dispatchEvent(element, EVENT_READY) false) {this.ready false;return;}if (this.ready options.inline) {this.view(this.index);}}/*** Get the no conflict viewer class.* returns {Viewer} The viewer class.*/}源码改变之后执行npm i 之后node_modules源码又变回了原样
利用patch-package解决该问题
安装
npm i patch-package安装完成后执行命令 npx patch-package viewerjs//viewerjs是我们修改node_modules中的源码文件名 npx patch-package为固定内容执行命令后发现项目多了一个patches文件这个便是对源码的补丁我们需要把这个文件上传至项目仓库中然后你同事拉下代码执行npm i后会自动使用我们写的补丁