今日分享:canvas放大镜功能
思路:
-
准备两个canvas和一个放大镜元素;两个canvas,一个用于原图渲染,一个用于放大查看,放大镜元素跟随鼠标运动
-
在原图渲染的canvas上绑定一个 'mousedown' 事件,用于获取选中查看图片的坐标,同时在window上绑定'mousemove'事件
-
在window上绑定 'mouseup' 事件,用于解绑window的 'mousemove' 事件
-
window上绑定的'mousemove'事件用于监听鼠标的移动距离,从而计算出在放大查看的canvas上的坐标并实时绘图
代码
html 部分
<template>
<div class="magnifying-glass">
<div class="source-box">
<div class="zoom-box"
:style="{
left: zoomPoint.x + 'px',
top: zoomPoint.y + 'px',
}"
v-show="isShow"></div>
<canvas id="source-canvas"></canvas>
</div>
<canvas id="look-canvas" v-show="isShow"
:style="{top: lookPoint.top + 'px', left: lookPoint.left + 'px'}"
></canvas>
</div>
</template>
js 部分
<script setup>
import { onMounted, ref, reactive } from 'vue'
// 要放大查看的图片
import phoneImg from '@/assets/image/phone.png'
let canvas = null;
let lookCanvas = null;
// 桌布
let zoomBox = null;
let canvasWidth = 500;
let canvasHeight = 500;
// look-canvas 的展示位置设置
let lookPoint = reactive({
top: 0,
left: 500,
})
// 原图的坐标
let points = {x: 0, y: 0,}
// 放大 图片的坐标
let showPoint = { x: 0, y: 0 }
// 桌布位置坐标
let zoomPoint = reactive({
x: 0,
y: 0
})
// 鼠标 mousedow 窗口坐标点记录
let startPoint = {x: 0,y: 0,}
// 桌布 和 放大区域是否显示标志位
let isShow = ref(false);
let image = null
// 放大倍数
let multiple = 3;
// 获取图片资源
async function getImage(url) {
const response = await fetch(url);
const blob = await response.blob();
const image = await createImageBitmap(blob);
return image;
}
onMounted(async ()=>{
image = await getImage(phoneImg);
canvas = document.getElementById('source-canvas');
lookCanvas = document.getElementById('look-canvas');
zoomBox = document.querySelector('.zoom-box');
canvas.width = canvasWidth;
canvas.height = canvasHeight;
lookCanvas.width = canvasWidth;
lookCanvas.height = canvasHeight;
let ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0, canvasWidth, canvasHeight)
canvas.addEventListener('mousedown', canvasMousedown)
window.addEventListener('mouseup', windowMouseUp)
})
function canvasMousedown(e){
let {offsetX, offsetY, clientX, clientY } = e;
points = {
x: offsetX,
y: offsetY
}
startPoint = {
x: clientX,
y: clientY
}
setShowPoint(offsetX, offsetY)
isShow.value = true;
lookCanvasDraw(lookCanvas, image, canvasWidth, canvasHeight, multiple);
window.addEventListener('mousemove', windowMouseMove)
}
function windowMouseUp(e){
isShow.value = false;
window.removeEventListener('mousemove', windowMouseMove)
}
function windowMouseMove(e){
let {clientX, clientY} = e;
let x = points.x + clientX - startPoint.x;
let y = points.y + clientY - startPoint.y;
setShowPoint(x, y);
lookCanvasDraw(lookCanvas, image, canvasWidth, canvasHeight, multiple);
}
function lookCanvasDraw(canvas, image, canvasWidth, canvasHeight, multiple=2){
let ctx = canvas.getContext('2d');
ctx.clearRect(0,0, canvasWidth, canvasHeight)
ctx.drawImage(image, showPoint.x, showPoint.y, canvasWidth*multiple, canvasHeight*multiple )
}
// 设置 放大镜查看 图片位置
function setShowPoint(X, Y){
if(X>500){
X = 500;
}
if(X<0){
X = 0;
}
if(Y>500){
Y = 500;
}
if(Y<0){
Y = 0;
}
//
showPoint = {
x: -X*multiple + canvasWidth/2,
y: -Y*multiple + canvasHeight/2,
}
// 桌布桌布设置
zoomPoint.x = X;
zoomPoint.y = Y;
}
</script>
css 部分
<style scoped>
.magnifying-glass{
position: relative;
}
.source-box{
position: relative;
width: 500px;
height: 500px;
}
.zoom-box{
position: absolute;
width: 20%;
height: 20%;
background-color: rgba(255, 0, 0, 0.2);
transform: translate(-50%, -50%);
border-radius: 50%;
}
#source-canvas,
#look-canvas{
background-color: #eee;
}
#look-canvas{
position: absolute;
}
</style>