# 效果图

# 代码

<template>
    <div id="continer">
        <canvas ref="canvas1" width="300" height="200"></canvas>
        <canvas id="slideBlock" ref="canvas2" width="60" height="60"></canvas>
        <img ref="img" src="../public/bk.png" style="display: none">
        <input v-model="process" type="range" id="range" ref="range">
    </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
const canvas1 = ref(null);
const canvas2 = ref(null);
const range = ref(null);
const process = ref(0);
const startPathX = Math.round(Math.random() * 240);
const startPathY = Math.round(Math.random() * 140);
const img = ref(null);
let isAct = false;
onMounted(() => {
    canvas2.value.style.top = canvas1.value.offsetTop + startPathY + 'px'
    const ctx1 = canvas1.value.getContext("2d");
    const ctx2 = canvas2.value.getContext("2d");
    img.value.onload = () => {
        ctx1.drawImage(img.value, 0, 0, 300, 200);
        draw(ctx1, () => {
            ctx1.fillStyle = '#63eae6';
            ctx1.fill();
        }, startPathX, startPathY);
        draw(ctx2, () => {
            ctx2.clip();
            ctx2.fill();
        }, 0, 0);
        ctx2.drawImage(img.value, startPathX * -1, startPathY * -1, 300, 200);
    }
    range.value.addEventListener("mouseup", () => {
        isAct = false
        if (Math.abs((Number.parseInt(process.value)) * 2.6 - 20 - startPathX) < 5) {
            process.value = 0;
            canvas2.value.style.transform = `translateX(0px)`;
        }
    })
    range.value.addEventListener("mousedown", () => {
        isAct = true
    })
    range.value.addEventListener("mousemove", () => {
        if (isAct) {
            canvas2.value.style.transform = `translateX( ${(Number.parseInt(process.value)) * 2.6}px)`
        }
    })
})

const draw = (ctx, act, startPathX, startPathY) => {
    ctx.beginPath();
    ctx.moveTo(startPathX, startPathY);
    ctx.lineTo(startPathX + 60, startPathY);
    ctx.lineTo(startPathX + 60, startPathY + 60);
    ctx.lineTo(startPathX + 40, startPathY + 60);
    ctx.lineTo(startPathX + 40, startPathY + 55);
    ctx.lineTo(startPathX + 30, startPathY + 55);
    ctx.lineTo(startPathX + 30, startPathY + 60);
    ctx.lineTo(startPathX, startPathY + 60);
    ctx.lineTo(startPathX, startPathY + 40);
    ctx.lineTo(startPathX + 10, startPathY + 40);
    ctx.lineTo(startPathX + 10, startPathY + 30);
    ctx.lineTo(startPathX, startPathY + 30);
    ctx.lineTo(startPathX, startPathY);
    act();
}
</script>

<style scoped>
canvas:first-child {
    height: 200px;
    width: 300px;
    box-shadow: 2px 2px 1px;
}


#slideBlock {
    position: absolute;
    margin-left: -20px;
    z-index: 999;
    height: 60px;
    width: 60px;
    box-shadow: 1px 2px 2px;
}

#range {
    position: relative;
    width: 100%;
}

#continer {
    width: 300px;
}
</style>

# 简述

简单实现了滑动验证,也是对 canvas 的再一次学习。 canvasContext.clip()对画布进行剪切,这个 api 用于需要透明的部分。

# BUG

如果发现 bug 或者其他需求可以联系作者 也十分欢迎 pr 前往 github (opens new window)