我的项目使用的是vue,接到新的需求要在图片预览的时候,添加旋转保存按钮。需要做的无非为iview添加按钮,为按钮添加事件。
在上述图片的default.js中有iviewJs的所有配置项,在iview.js文件与你传入的合并
this.options = assign({}, DEFAULTS, isPlainObject(options) && options);复制代码
一、在工具栏中添加保存按钮
配置项中有几个钩子函数
show可以在展示之前执行绑定一下函数,在函数里我们通过使用insertAdjacentHTML()对工具栏进行样式的重新设定,并绑定函数触发相关
addPre () { var dom = document.querySelector('.viewer-container') if (this.list.length > 1) { dom.insertAdjacentHTML('beforeend', '<a class="bh_pre bh_iconbutton" onclick="viewer.cprev()"><i class="ivu-icon ivu-icon-ios-arrow-back"></i></a>') dom.insertAdjacentHTML('beforeend', '<a class="bh_next bh_iconbutton" onclick="viewer.cnext()"><i class="ivu-icon ivu-icon-ios-arrow-forward"></i></a>') } dom.insertAdjacentHTML('beforeend', '<div class="btn-show-big-img" onclick="viewer.setShowBigImg()">查看原图</div>') dom.insertAdjacentHTML('beforeend', `<div class="bottonContent"> <a onclick="viewer.zoom(0.1)"><i class="ivu-icon ivu-icon-md-add"></i></a> <a onclick="viewer.zoom(-0.1)"><i class="ivu-icon ivu-icon-md-remove"></i></a> <a class="refresh-cover" onclick="viewer.crotate(-90)"><i class="ivu-icon ivu-icon-md-refresh"></i></a> <a onclick="viewer.crotate(90)"><i class="ivu-icon ivu-icon-md-refresh"></i></a> <a onclick="viewer.save()" class="btn-save-img" style="visibility:hidden"><i class="ivu-icon ivu-icon-md-checkmark"></i></a> </div> `) },复制代码
window.viewer = new Viewer() window.viewer.crotate = function (val) { _this.rotateNum += val _this.isShowSave() window.viewer.rotate(val) } window.viewer.cprev = function () { _this.isLoad = false _this.rotateNum = 0 _this.isShowSave() window.viewer.prev() } window.viewer.cnext = function () { _this.isLoad = false _this.rotateNum = 0 _this.isShowSave() window.viewer.next() }复制代码
二、添加保存事件
渲染的基本流程:
- view.js中实例调用class view中的init()函数
- 函数获取页面Dom读取img和页面的信息进行储存
- 调用build函数进行组件的构建
- build函数会调用render中的render函数,对页面进行渲染。
- 用户交互操作会通过handler判断交互类型去调用method中的方法
观看源码viewer一些存储数据位置:
document.querySelector('.viewer-canvas img')
//当前展示的图片信息
image{
naturalHeight//应该是存储的图片原始大小
naturalWigth
complete //图片是否加载完成
}复制代码
//存储当前图片位置展示大小形变等初始化信息。(每次切换图片必然刷新)
imageData{
aspectRatio: 0.625 // naturalHeight/naturalHeight的比值
height: 788 //图片初始化要展示的大小
width: 453.125
left: 382.09375 //图片的位置position的top,left的值
top: 7.899999999999977
naturalHeight: 800 //image的natureHeight,natureWidth
naturalWidth: 500
ratio: 0.90625 // width/natureWidth 当前图片初始化的放缩比例
rotate: 0 //当前用户操作图片旋转的角度
scaleX: 1 //当前用户操作图片放缩比例
scaleY: 1
}复制代码
//在初始化时候生成,存储展示的图片列表信息(通过读取传入id里的img信息)
images[
img:{
dataset:{
originalUrl:src //这里的数据会在切换图片的时候在这里取放在src
}
}
]复制代码
//存储当前页面的宽度和长度
viewData{
width:000,
height:000
}
//存储一开始的imageData的信息
initialImageData{
}复制代码
//下面缩略图导航列表的数据
items[
li,li
]复制代码
viewJs会在打开的时候会有读取我们id内的DOM,并做初始化。这时在DOM中读取数据就会放在以上几个对象中。
所以当我保存后,图片是不能够实时刷新的。需要我们手动去改变,把保存后的数据放入以上图片中。
1、首先我们只是改变了当前图片的src。
需要注意的是如果保存后的图片路径没有改变需要给src加一时间戳保证图片重新去请求。
let imgEl = document.querySelector('.viewer-canvas img')//返回的数据可能有date参数
imgEl.src = newUrl复制代码
2、相应的缩略图的src也需要改变
//修改选中缩略图的src及当前展示图片的src
const imageActive = document.querySelector('.viewer-list .viewer-active img')
imageActive.src = httpUrl复制代码
3、这样我们需要做相应改变的有图片展示的宽高(宽高是经过比例设置的,保证不超过屏幕)
我们只需要在图片旋转为90,270的时候,img的宽高进行调换并对imageData中的数据进行重新赋值,并调用renderImage对当前图片进行重置。
//当图片旋转保存时,需要对当前展示的图片进行宽高重新计算和渲染
if(rotate % 180 === 90) {
let viewer = window.viewer
let imageData = viewer.imageData
let viewerData = viewer.viewerData
let b = imageData.naturalHeight
imageData.naturalHeight = imageData.naturalWidth
imageData.naturalWidth = b
imageData.aspectRatio = imageData.naturalWidth / imageData.naturalHeight
const footerHeight = viewer.footer.offsetHeight
let viewerHeight = Math.max(viewerData.height - footerHeight, footerHeight)
if (viewerHeight * imageData.aspectRatio > viewerData.width) {
imageData.height = Math.min((viewerData.width / imageData.aspectRatio), imageData.naturalHeight)
imageData.width = Math.min(viewerData.width, imageData.naturalWidth)
} else {
imageData.width = Math.min((viewerHeight * imageData.aspectRatio), imageData.naturalWidth)
imageData.height = Math.min(viewerData.height, imageData.naturalHeight)
}
imageData.ratio = imageData.width / imageData.naturalWidth
imageData.left = ( viewerData.width - Math.min( imageData.width*0.9, imageData.naturalWidth))/2
imageData.top = (viewerHeight - Math.min( imageData.height*0.9, imageData.naturalHeight))/2
}
window.viewer.imageData.rotate = 0
window.viewer.imageData.scaleX = 1
window.viewer.imageData.scaleY = 1
console.log(window.viewer.element)
// window.viewer.rotateTo(0)
window.viewer.renderImage()复制代码
4、我们还需要考虑当左右切换的时候,这里有一个坑。这里他取的img的datset.originalUrl中的数据,不是直接去的img的src。在替换的时候需要把originUrl进行替换
//修改viewer组件中的缓存数据
for(let i=0;i -1){
window.viewer.images[i].src = httpUrl
window.viewer.items[i].querySelector('img').setAttribute(`data-original-url`, httpUrl)
break
}
}复制代码
到这里这个需求大致修补完成,勉强能用了
优化:点击旋转的时候,会改变imageData的rotate。在renderImage的时候会发现有旋转。交互不太
需要保存的时候先隐藏img,添加加载项。再image.onload函数中再复现img
let canvas = document.querySelector('.viewer-canvas')
let imgEl = document.querySelector('.viewer-canvas img')//返回的数据可能有date参数
canvas.classList.add('viewer-loading')
imgEl.style.display = 'none'//使用visibility,并能及时隐藏
imgEl.onload = function () {
canvas.classList.remove('viewer-loading')
imgEl.style.display = 'block'
}复制代码
总结:
经过添加保存按钮,把viewJs进行了一次系统的学习。对其中的原理有了更清晰的认识。初始化的拆分,工具函数的拆分,渲染函数的拆分都给了我很大的启发。
附: