前言
实现缩放和拖拽,一般我们使用transform 的scale进行放缩,使用translate进行平移,还可以使用定位进行拖拽,综合考虑,此处统一使用transform
获取元素transform属性值
window中的getComputedStyle()方法可以获取元素当前的样式
即可通过getComputedStyle(dom).transform获取transform属性值
-
dom没有该属性,返回:'none'
-
有该属性,返回一个matrix矩阵
'matrix(x向缩放倍数,旋转,拉伸,y向缩放倍数,x偏移量,y偏移量)',再通过split(',')将各个属性值转为数组
为什么不用DOM.style.transform来获取tranform,因为DOM.style.transform会返回css字符串代码,如:
如果只有偏移值那么会返回'translate(100px, 100px)', 如果有偏移值和缩放值时会返回'translate(100px, 100px) scale(2)' 因此这样获取具体的缩放比例、偏移值都不太方便
拖拽步骤
- 鼠标摁下onmousedown,记录鼠标和图片的位置,从而计算鼠标相对图片的坐标
鼠标相对图片的坐标:
鼠标相对浏览器(有效区域)左侧的位置-图片的translateX和translateY的值
-
监听鼠标的移动onmousemove,当鼠标移动时被拖拽的元素跟随鼠标移动,根据鼠标当前坐标和鼠标相对图片的距离计算出图片当前的坐标
图片当前的translateX和translateY的值:
鼠标当前相对浏览器(有效区域)位置-鼠标相对图片的距离 计算出图片移动的距离
代码实现
html部分
picView.html
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片查看器</title>
<link rel="stylesheet" href="./picView.css">
</head>
<body>
<div class="img">
<div class="img_top">
<div class="img_tool">
<!-- <div class="zoomCount" onbind="toPercent(multiples)"></div> -->
<div class="icon bigger_icon" onclick="biggerImg()"></div>
<div class="icon smaller_icon" onclick="smallerImg()"></div>
<div class="returnImg" onclick="returnImg()">还原</div>
</div>
</div>
<div class="img_content" onmousedown="dragImg()" onmousewheel="scrollFunc()">
<!-- 注意的是img标签的draggable属性,draggable属性在img、a标签中默认true,属于浏览器默认拖动,会跟自己写的事件冲突从而导致拖不动、拖动残影等等奇怪的问题
因此先置成false -->
<img id="bigImg" src="./airplane.png" alt="" draggable="false">
</div>
<!-- <div class="left" onclick="afterImg()"></div>
<div class="right" onclick="beforeImg()"></div> -->
</div>
<script src="./picView.js"></script>
</body>
js部分
picView.js
// 图片放大 缩小
let multiples = 1
// 图片拖拽后的偏移
let newTransX = 0
let newTransY = 0
// 鼠标相对图片的位置
let disX = 0
let disY = 0
/**
* 鼠标摁下onmousedown,触发dragImg事件,记录鼠标和图片的位置,从而计算鼠标相对图片的坐标
* 鼠标相对图片的坐标:鼠标相对浏览器(有效区域)左侧的位置-图片的translateX和translateY的值
*
* 监听鼠标的移动onmousemove,当鼠标移动时被拖拽的元素跟随鼠标移动,根据鼠标当前坐标和鼠标相对图片的距离计算出图片当前的坐标
* 图片当前的translateX和translateY的值:鼠标当前相对浏览器(有效区域)位置-鼠标相对图片的距离 计算出图片移动的距离
*
* 是否存在边界限制 暂无
*/
// 改变元素位置的方式有:定位、translate偏移
function dragImg($event) {
let e = $event || event
let dragEl = document.querySelector('#bigImg')
getTransInfo(e)
document.onmousemove = (e) => {
newTransX = e.clientX - disX
newTransY = e.clientY - disY
dragEl.style.transform = `matrix(${multiples}, 0, 0, ${multiples}, ${newTransX}, ${newTransY})`
}
document.onmouseup = () => {
document.onmousemove = null
}
}
function getTransInfo(e) {
// 获取元素当前的宽高
let dragEl = document.querySelector('#bigImg')
// 获取元素当前的偏移量
let translateStr = getComputedStyle(dragEl).transform.split(',')
console.log(translateStr)
// 获取translateX
let transX= isNaN(+translateStr[translateStr.length - 2]) ? 0 : +translateStr[translateStr.length - 2]
// 获取translateY
let transY= isNaN(+translateStr[translateStr.length - 1].split(')')[0]) ? 0 : +translateStr[translateStr.length - 1].split(')')[0]
// 记录鼠标的起始位置
//鼠标指针相对于浏览器页面(或当前窗口)的水平坐标
let startX = e.clientX
//鼠标指针相对于浏览器页面(或当前窗口)的y坐标
let startY = e.clientY
disX = startX - transX //鼠标相对于图片左侧的水平距离
disY = startY - transY
}
// 鼠标滚轮缩放
document.scrollFunc = function(e) {
e = e || window.event
// 火狐下没有wheelDelta,用detail代替,由于detail值的正负和wheelDelta相反,所以取反
e.delta = e.wheelDelta || -e.detail
e.preventDefault()
if (e.delta > 0) {
//当滑轮向上滚动时
biggerImg()
}
if (e.delta < 0) {
//当滑轮向下滚动时
smallerImg()
}
}
function smallerImg() {
let img = document.getElementById('bigImg')
multiples = Number(multiples-0.1)
if(multiples > 0.4) {
img.style.transform = `matrix(${multiples}, 0, 0, ${multiples}, ${newTransX}, ${newTransY})`
} else {
multiples = 0.5
}
}
function biggerImg() {
let img = document.getElementById('bigImg')
// 数字相加一定要注意字符串,一定要防止数字变成字符串数字,请刻入DNA
multiples = Number(multiples+0.1)
if(multiples < 2.1) {
img.style.transform = `matrix(${multiples}, 0, 0, ${multiples}, ${newTransX}, ${newTransY})`
} else {
multiples = 2
}
}
css部分
picView.css
*{
box-sizing: border-box;
}
body {
margin: 0;
/* -webkit-user-select: none;
margin: 0 auto; */
/* background-color: #0d141d; */
font-family: Microsoft YaHei;
overflow: hidden;
font-size: 14px;
}
.img {
position: relative;
height: 100%;
width: 100%;
}
.img .img_top{
position: fixed;
z-index: 999;
height: 35px;
line-height: 35px;
width: 100%;
background-color: #0070B8;
color: #fff;
}
.img .img_top .img_tool{
display: flex;
float: right;
margin-right: 200px;
height: 25px;
margin-top: 4px;
line-height: 35px;
color: #fff;
}
.img .img_top .img_tool .icon{
display: inline-block;
width: 25px;
height: 25px;
cursor: pointer;
}
.img .img_top .img_tool .smaller_icon{
background: url(./small.png);
background-size: 100% 100%;
margin-right: 40px;
}
.img .img_top .img_tool .bigger_icon{
background: url(./big.png);
background-size: 100% 100%;
margin-right: 40px;
}
.img .img_content {
position: fixed;
transform: translate(50%, 50%);
margin-top: 35px;
}
.img img {
/* display: block;
margin: 0 auto;
height: 100%; */
}
.img .img_top .title{
display: inline-block;
font-size: 16px;
text-indent: 1em;
margin-right: 100px;
}
.img .left,
.img .right {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 40px;
height: 40px;
background-color: rgba(33, 33, 33, 0.3);
border-radius: 50%;
background-size: 60% 60%;
background-repeat: no-repeat;
background-position: center center;
background-image: url(./indexpre.png);
cursor: pointer;
}
.img .left {
left: 10px;
}
.img .right {
right: 10px;
background-image: url(./indexnext.png);
}