canvas 画出vconsole
<!-- 全屏透明Canvas -->
<canvas id="overlay-canvas"></canvas>
#overlay-canvas {
position: fixed;
top:100px;
left:0;
width: 100%;
height: 50%;
z-index: 1000000;
}
<script>
window.addEventListener('DOMContentLoaded', ()=>{
setTimeout(() => {
canvas.style.display = 'none'; // 允许父元素点击穿透
canvas.style.position = 'relative'; // 允许父元素点击穿透
}, 1500);
const canvas = document.getElementById('overlay-canvas');
const ctx = canvas.getContext('2d');
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// 绘制参数
const V_PATH = [
{x: 0.3, y: 0.2}, // V左起点 (相对坐标)
{x: 0.5, y: 0.4}, // V底部中点
{x: 0.7, y: 0.2} // V右终点
];
// 转换为绝对坐标
function getAbsolutePoints() {
return V_PATH.map(p => ({
x: p.x * canvas.width,
y: p.y * canvas.height
}));
}
// 触摸跟踪变量
let isDrawing = false;
let touchPoints = [];
let lastTouchTime = 0;
// 计算两点距离
function distance(p1, p2) {
return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
}
// 检测是否匹配V路径
function checkVShape(points) {
const absVPath = getAbsolutePoints();
const tolerance = 50; // 匹配容差(像素)
// 1. 检查点数量是否足够
if (points.length < 10) return false;
// 2. 检查总体方向是否先下后上
const firstThird = Math.floor(points.length / 3);
const lastThird = points.length - firstThird;
const startY = points[0].y;
const midY = points[firstThird].y;
const endY = points[points.length-1].y;
if (!(midY > startY + 50 && midY > endY + 50)) {
return false;
}
// 3. 检查是否接近预设V路径
let matchedLeft = false;
let matchedRight = false;
for (let i = 0; i < points.length; i++) {
const p = points[i];
// 检查左斜线
if (!matchedLeft && distance(p, absVPath[0]) < tolerance &&i < points.length/2) {
matchedLeft = true;
}
// 检查底部区域
if (matchedLeft && !matchedRight &&distance(p, absVPath[1]) < tolerance) {
// 继续检查右斜线
for (let j = i; j < points.length; j++) {
if (distance(points[j], absVPath[2]) < tolerance) {
matchedRight = true;
break;
}
}
break;
}
}
return matchedLeft && matchedRight;
}
// 触摸事件处理
canvas.addEventListener('touchstart', (e) => {
e.preventDefault();
const touch = e.touches[0];
const rect = canvas.getBoundingClientRect();
touchPoints = [{
x: touch.clientX - rect.left,
y: touch.clientY - rect.top,
time: Date.now()
}];
isDrawing = true;
lastTouchTime = Date.now();
// 清空Canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
}, { once: true });
canvas.addEventListener('touchmove', (e) => {
if (!isDrawing) return;
e.preventDefault();
const touch = e.touches[0];
const rect = canvas.getBoundingClientRect();
const newPoint = {
x: touch.clientX - rect.left,
y: touch.clientY - rect.top,
time: Date.now()
};
// 过滤太近的点
if (touchPoints.length > 0) {
const lastPoint = touchPoints[touchPoints.length-1];
if (distance(lastPoint, newPoint) < 5) {
return;
}
}
touchPoints.push(newPoint);
lastTouchTime = Date.now();
// 实时绘制路径
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(touchPoints[0].x, touchPoints[0].y);
for (let i = 1; i < touchPoints.length; i++) {
ctx.lineTo(touchPoints[i].x, touchPoints[i].y);
}
ctx.strokeStyle = 'transparent';
ctx.lineWidth = 8;
ctx.lineCap = 'round';
ctx.stroke();
});
canvas.addEventListener('touchend', (e) => {
if (!isDrawing) return;
e.preventDefault();
isDrawing = false;
// 检查是否绘制了V字形
if (checkVShape(touchPoints)) {
console.log("V路径绘制成功!", window.vconsole);
const vconsole = window.vconsole
new vconsole();
// 绘制绿色成功提示
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(touchPoints[0].x, touchPoints[0].y);
for (let i = 1; i < touchPoints.length; i++) {
ctx.lineTo(touchPoints[i].x, touchPoints[i].y);
}
ctx.strokeStyle = 'transparent';
ctx.lineWidth = 10;
ctx.stroke();
// 3秒后清除
setTimeout(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}, 3000);
} else {
console.log("V路径绘制失败!", touchPoints);
setTimeout(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}, 2000);
}
}, { once: true });
// 防止页面滚动
document.addEventListener('touchmove', (e) => {
if (isDrawing) {
e.preventDefault();
}
}, { passive: false });
});
</script>

浙公网安备 33010602011771号