canvas放大镜功能

116 阅读2分钟

今日分享:canvas放大镜功能

思路:

  1. 准备两个canvas和一个放大镜元素;两个canvas,一个用于原图渲染,一个用于放大查看,放大镜元素跟随鼠标运动

  2. 在原图渲染的canvas上绑定一个 'mousedown' 事件,用于获取选中查看图片的坐标,同时在window上绑定'mousemove'事件

  3. 在window上绑定 'mouseup' 事件,用于解绑window的 'mousemove' 事件

  4. 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>