写图片组件
This commit is contained in:
parent
95de096466
commit
a5286fbcd6
@ -148,11 +148,27 @@ export default {
|
||||
store: {
|
||||
scale: 1
|
||||
},
|
||||
|
||||
result: {
|
||||
width: 414,
|
||||
height: 737
|
||||
},
|
||||
x: 0,
|
||||
y: 79,
|
||||
scale: 1,
|
||||
maxScale: 3,
|
||||
minScale: 0.5,
|
||||
point1: {x: 0, y: 0},
|
||||
point2: {x: 0, y: 0},
|
||||
diff: {x: 0, y: 0},
|
||||
lastPointermove: {x: 0, y: 0},
|
||||
lastPoint1: {x: 0, y: 0},
|
||||
lastPoint2: {x: 0, y: 0},
|
||||
lastCenter: {x: 0, y: 0},
|
||||
|
||||
a: {},
|
||||
b: {},
|
||||
x: 0,
|
||||
y: 0,
|
||||
lastCenter: {}
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@ -214,13 +230,10 @@ export default {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
// 第一个触摸点的坐标
|
||||
this.a.x = events.pageX;
|
||||
this.a.y = events.pageY;
|
||||
this.b.x = events2.pageX;
|
||||
this.b.y = events2.pageY;
|
||||
this.lastPoint1 = this.point1 = {x: events.pageX, y: events.pageY};
|
||||
this.lastPoint2 = this.point2 = {x: events2.pageX, y: events2.pageY};
|
||||
|
||||
this.lastCenter = this.getCenter(this.a, this.b)
|
||||
this.lastCenter = this.getCenter(this.lastPoint1, this.lastPoint2)
|
||||
}
|
||||
},
|
||||
move(e) {
|
||||
@ -245,8 +258,8 @@ export default {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
let a = {x: e.touches[0].pageX, y: e.touches[0].pageY}
|
||||
let b = {x: e.touches[1].pageX, y: e.touches[1].pageY}
|
||||
let current1 = {x: e.touches[0].pageX, y: e.touches[0].pageY}
|
||||
let current2 = {x: e.touches[1].pageX, y: e.touches[1].pageY}
|
||||
|
||||
// 获取坐标之间的举例
|
||||
let getDistance = function (start, stop) {
|
||||
@ -254,14 +267,12 @@ export default {
|
||||
};
|
||||
|
||||
// 双指缩放比例计算
|
||||
let ratio = getDistance(a, b) / getDistance(this.a, this.b);
|
||||
let ratio = getDistance(current1, current2) / getDistance(this.lastPoint1, this.lastPoint2);
|
||||
|
||||
let moveX = a.x - this.a.x
|
||||
let moveY = a.y - this.a.y
|
||||
|
||||
// 计算当前双指中心点坐标
|
||||
let center = this.getCenter(a, b)
|
||||
// console.log('center', center)
|
||||
let center = this.getCenter(current1, current2)
|
||||
console.log('center', center)
|
||||
|
||||
// 计算图片中心偏移量,默认transform-origin: 50% 50%
|
||||
// 如果transform-origin: 30% 40%,那origin.x = (ratio - 1) * result.width * 0.3
|
||||
@ -269,30 +280,38 @@ export default {
|
||||
// 如果通过修改宽高或使用transform缩放,但将transform-origin设置为左上角时。
|
||||
// 可以不用计算origin,因为(ratio - 1) * result.width * 0 = 0
|
||||
const origin = {
|
||||
x: (ratio - 1) * 414 * 0.5,
|
||||
y: (ratio - 1) * 737 * 0.5
|
||||
x: (ratio - 1) * this.result.width * 0.5,
|
||||
y: (ratio - 1) * this.result.height * 0.5
|
||||
};
|
||||
// 计算偏移量,认真思考一下为什么要这样计算(带入特定的值计算一下)
|
||||
this.x -= (ratio - 1) * (center.x - this.x) - origin.x - (center.x - this.lastCenter.x);
|
||||
this.y -= (ratio - 1) * (center.y - this.y) - origin.y - (center.y - this.lastCenter.y);
|
||||
|
||||
console.log('this.x',this.x)
|
||||
console.log('this.y',this.y)
|
||||
// console.log('this.x', this.x)
|
||||
// console.log('this.y', this.y)
|
||||
|
||||
// 图像应用缩放效果
|
||||
this.itemRefs[this.index].style.transform =
|
||||
`translate3d(${moveX}px,${moveY}px,0) scale(${this.store.scale * ratio})`;
|
||||
`translate3d(${this.x}px,${this.y}px,0) scale(${this.store.scale * ratio})`;
|
||||
|
||||
this.lastCenter = {x: center.x, y: center.y};
|
||||
this.lastPoint1 = {x: current1.x, y: current1.y};
|
||||
this.lastPoint2 = {x: current2.x, y: current2.y};
|
||||
}
|
||||
},
|
||||
end(e) {
|
||||
console.log('end')
|
||||
console.log('end',e.touches)
|
||||
if (this.isTwo) {
|
||||
this.store.scale = 1
|
||||
this.itemRefs[this.index].style['transition-duration'] = '300ms';
|
||||
this.itemRefs[this.index].style.transform = 'scale(' + 1 + ')';
|
||||
this.itemRefs[this.index].style.transform = `translate3d(0,0,0) scale(1)`;
|
||||
if (this.state !== 'custom') {
|
||||
this.state = 'play'
|
||||
}
|
||||
if (e.touches.length){
|
||||
this.point1 = {x: e.touches[0].pageX, y: e.touches[0].pageY}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (this.index === 0 && !this.isDrawRight) return
|
||||
if (this.index === this.modelValue.imgs.length - 1 && this.isDrawRight) return
|
||||
|
||||
241
src/pages/test/pinch.html
Normal file
241
src/pages/test/pinch.html
Normal file
@ -0,0 +1,241 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||
<title>pinch</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100vh;
|
||||
background: #000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
img {
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.log {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
padding: 5px;
|
||||
color: #FFF;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<img id="image" alt="">
|
||||
</div>
|
||||
<div class="log"></div>
|
||||
|
||||
<script>
|
||||
// 获取dom
|
||||
const image = document.getElementById('image');
|
||||
const log = document.querySelector('.log');
|
||||
// 全局变量
|
||||
let result,
|
||||
x,
|
||||
y,
|
||||
scale = 1,
|
||||
maxScale,
|
||||
minScale = 0.5;
|
||||
// 图片加载完成后再操作,否则naturalWidth为0
|
||||
image.addEventListener('load', function () {
|
||||
result = getImgSize(image.naturalWidth, image.naturalHeight, window.innerWidth, window.innerHeight);
|
||||
image.style.width = result.width + 'px';
|
||||
image.style.height = result.height + 'px';
|
||||
x = (window.innerWidth - result.width) * 0.5;
|
||||
y = (window.innerHeight - result.height) * 0.5;
|
||||
image.style.transform = 'translate3d(' + x + 'px, ' + y + 'px, 0) scale(1)';
|
||||
maxScale = Math.max(Math.round(image.naturalWidth / result.width), 3);
|
||||
log.innerHTML = `x = ${x.toFixed(0)}<br>y = ${y.toFixed(0)}<br>scale = ${scale.toFixed(5)}`;
|
||||
});
|
||||
image.src = 'http://jsdemo.codeman.top/images/liya.jpg';
|
||||
/**
|
||||
* 获取图片缩放尺寸
|
||||
* @param {number} naturalWidth
|
||||
* @param {number} naturalHeight
|
||||
* @param {number} maxWidth
|
||||
* @param {number} maxHeight
|
||||
* @returns
|
||||
*/
|
||||
function getImgSize(naturalWidth, naturalHeight, maxWidth, maxHeight) {
|
||||
const imgRatio = naturalWidth / naturalHeight;
|
||||
const maxRatio = maxWidth / maxHeight;
|
||||
let width, height;
|
||||
// 如果图片实际宽高比例 >= 显示宽高比例
|
||||
if (imgRatio >= maxRatio) {
|
||||
if (naturalWidth > maxWidth) {
|
||||
width = maxWidth;
|
||||
height = maxWidth / naturalWidth * naturalHeight;
|
||||
} else {
|
||||
width = naturalWidth;
|
||||
height = naturalHeight;
|
||||
}
|
||||
} else {
|
||||
if (naturalHeight > maxHeight) {
|
||||
width = maxHeight / naturalHeight * naturalWidth;
|
||||
height = maxHeight;
|
||||
} else {
|
||||
width = naturalWidth;
|
||||
height = naturalHeight;
|
||||
}
|
||||
}
|
||||
return { width: width, height: height }
|
||||
}
|
||||
|
||||
// 全局变量
|
||||
let isPointerdown = false, // 按下标识
|
||||
pointers = [], // 触摸点数组
|
||||
point1 = { x: 0, y: 0 }, // 第一个点坐标
|
||||
point2 = { x: 0, y: 0 }, // 第二个点坐标
|
||||
diff = { x: 0, y: 0 }, // 相对于上一次pointermove移动差值
|
||||
lastPointermove = { x: 0, y: 0 }, // 用于计算diff
|
||||
lastPoint1 = { x: 0, y: 0 }, // 上一次第一个触摸点坐标
|
||||
lastPoint2 = { x: 0, y: 0 }, // 上一次第二个触摸点坐标
|
||||
lastCenter; // 上一次中心点坐标
|
||||
// 绑定 pointerdown
|
||||
image.addEventListener('pointerdown', function (e) {
|
||||
pointers.push(e);
|
||||
point1 = { x: pointers[0].clientX, y: pointers[0].clientY };
|
||||
if (pointers.length === 1) {
|
||||
isPointerdown = true;
|
||||
image.setPointerCapture(e.pointerId);
|
||||
lastPointermove = { x: pointers[0].clientX, y: pointers[0].clientY };
|
||||
} else if (pointers.length === 2) {
|
||||
point2 = { x: pointers[1].clientX, y: pointers[1].clientY };
|
||||
lastPoint2 = { x: pointers[1].clientX, y: pointers[1].clientY };
|
||||
lastCenter = getCenter(point1, point2);
|
||||
}
|
||||
lastPoint1 = { x: pointers[0].clientX, y: pointers[0].clientY };
|
||||
});
|
||||
// 绑定 pointermove
|
||||
image.addEventListener('pointermove', function (e) {
|
||||
if (isPointerdown) {
|
||||
handlePointers(e, 'update');
|
||||
const current1 = { x: pointers[0].clientX, y: pointers[0].clientY };
|
||||
if (pointers.length === 1) {
|
||||
diff.x = current1.x - lastPointermove.x;
|
||||
diff.y = current1.y - lastPointermove.y;
|
||||
lastPointermove = { x: current1.x, y: current1.y };
|
||||
x += diff.x;
|
||||
y += diff.y;
|
||||
image.style.transform = 'translate3d(' + x + 'px, ' + y + 'px, 0) scale(' + scale + ')';
|
||||
log.innerHTML = `x = ${x.toFixed(0)}<br>y = ${y.toFixed(0)}<br>scale = ${scale.toFixed(5)}`;
|
||||
} else if (pointers.length === 2) {
|
||||
const current2 = { x: pointers[1].clientX, y: pointers[1].clientY };
|
||||
// 计算相对于上一次移动距离比例 ratio > 1放大,ratio < 1缩小
|
||||
let ratio = getDistance(current1, current2) / getDistance(lastPoint1, lastPoint2);
|
||||
// 缩放比例
|
||||
const _scale = scale * ratio;
|
||||
if (_scale > maxScale) {
|
||||
scale = maxScale;
|
||||
ratio = maxScale / scale;
|
||||
} else if (_scale < minScale) {
|
||||
scale = minScale;
|
||||
ratio = minScale / scale;
|
||||
} else {
|
||||
scale = _scale;
|
||||
}
|
||||
// 计算当前双指中心点坐标
|
||||
const center = getCenter(current1, current2);
|
||||
// 计算图片中心偏移量,默认transform-origin: 50% 50%
|
||||
// 如果transform-origin: 0% 0%,那origin.x = (ratio - 1) * result.width * 0
|
||||
// origin.y = (ratio - 1) * result.height * 0
|
||||
// 如果transform-origin: 30% 40%,那origin.x = (ratio - 1) * result.width * 0.3
|
||||
// origin.y = (ratio - 1) * result.height * 0.4
|
||||
const origin = { x: (ratio - 1) * result.width * 0.5, y: (ratio - 1) * result.height * 0.5 };
|
||||
// 计算偏移量
|
||||
x -= (ratio - 1) * (center.x - x) - origin.x - (center.x - lastCenter.x);
|
||||
y -= (ratio - 1) * (center.y - y) - origin.y - (center.y - lastCenter.y);
|
||||
image.style.transform = 'translate3d(' + x + 'px, ' + y + 'px, 0) scale(' + scale + ')';
|
||||
lastCenter = { x: center.x, y: center.y };
|
||||
lastPoint1 = { x: current1.x, y: current1.y };
|
||||
lastPoint2 = { x: current2.x, y: current2.y };
|
||||
log.innerHTML = `x = ${x.toFixed(0)}<br>y = ${y.toFixed(0)}<br>
|
||||
scale = ${scale.toFixed(5)}<br>
|
||||
centerX = ${center.x.toFixed(0)}<br>centerY = ${center.y.toFixed(0)}<br>`;
|
||||
}
|
||||
}
|
||||
e.preventDefault();
|
||||
});
|
||||
// 绑定 pointerup
|
||||
image.addEventListener('pointerup', function (e) {
|
||||
if (isPointerdown) {
|
||||
handlePointers(e, 'delete');
|
||||
if (pointers.length === 0) {
|
||||
isPointerdown = false;
|
||||
} else if (pointers.length === 1) {
|
||||
point1 = { x: pointers[0].clientX, y: pointers[0].clientY };
|
||||
lastPointermove = { x: pointers[0].clientX, y: pointers[0].clientY };
|
||||
}
|
||||
}
|
||||
});
|
||||
// 绑定 pointercancel
|
||||
image.addEventListener('pointercancel', function (e) {
|
||||
if (isPointerdown) {
|
||||
isPointerdown = false;
|
||||
pointers.length = 0;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 更新或删除指针
|
||||
* @param {PointerEvent} e
|
||||
* @param {string} type
|
||||
*/
|
||||
function handlePointers(e, type) {
|
||||
for (let i = 0; i < pointers.length; i++) {
|
||||
if (pointers[i].pointerId === e.pointerId) {
|
||||
if (type === 'update') {
|
||||
pointers[i] = e;
|
||||
} else if (type === 'delete') {
|
||||
pointers.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两点间距离
|
||||
* @param {object} a 第一个点坐标
|
||||
* @param {object} b 第二个点坐标
|
||||
* @returns
|
||||
*/
|
||||
function getDistance(a, b) {
|
||||
const x = a.x - b.x;
|
||||
const y = a.y - b.y;
|
||||
return Math.hypot(x, y); // Math.sqrt(x * x + y * y);
|
||||
}
|
||||
/**
|
||||
* 获取中点坐标
|
||||
* @param {object} a 第一个点坐标
|
||||
* @param {object} b 第二个点坐标
|
||||
* @returns
|
||||
*/
|
||||
function getCenter(a, b) {
|
||||
const x = (a.x + b.x) / 2;
|
||||
const y = (a.y + b.y) / 2;
|
||||
return { x: x, y: y };
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Loading…
Reference in New Issue
Block a user