如何用jQuery实现Canvas中六边形的点击图片上传功能
实现Canvas六边形点击上传图片(jQuery版)
核心思路
- 记录每个六边形的中心坐标与半径,用于点击时的碰撞检测
- 实现点是否在正六边形内的判断逻辑
- 通过jQuery绑定Canvas点击事件,触发隐藏的文件选择控件
- 处理文件选择后的预览(绘制到对应六边形)与上传逻辑
完整代码
HTML部分
<canvas id="canvas" width="800" height="500"></canvas> <!-- 隐藏的文件上传控件 --> <input type="file" id="hexUpload" accept="image/*" style="display:none">
JavaScript(含jQuery)部分
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const a = 2 * Math.PI / 6; const r = 50; // 存储所有六边形的中心坐标 const hexagons = []; // 绘制第一个六边形 let x = r; let y = r; hexagons.push({x, y}); drawHexagon(x, y); // 绘制第二个六边形 x = x + r + r * Math.cos(a); y = y + r * Math.sin(a); hexagons.push({x, y}); drawHexagon(x, y); // 绘制第三个六边形 x = x + r + r * Math.cos(a); y = y - r * Math.sin(a); hexagons.push({x, y}); drawHexagon(x, y); // 绘制第四个六边形 x = x + r + r * Math.cos(a); y = y + r * Math.sin(a); hexagons.push({x, y}); drawHexagon(x, y); function drawHexagon(x, y) { ctx.beginPath(); for (var i = 0; i < 6; i++) { ctx.lineTo(x + r * Math.cos(a * i), y + r * Math.sin(a * i)); } ctx.closePath(); ctx.stroke(); } // 判断点击点是否在目标六边形内 function isPointInHexagon(px, py, hexX, hexY, hexR) { const dx = Math.abs(px - hexX); const dy = Math.abs(py - hexY); return dx <= hexR && dy <= (hexR * Math.sqrt(3)/2) && (dx * Math.sqrt(3) + dy) <= hexR * Math.sqrt(3); } // jQuery处理逻辑 $(function() { let currentHexIndex = -1; // 记录当前点击的六边形索引 // Canvas点击事件处理 $('#canvas').on('click', function(e) { // 转换为Canvas内部的相对坐标 const rect = canvas.getBoundingClientRect(); const clickX = e.clientX - rect.left; const clickY = e.clientY - rect.top; // 遍历所有六边形,找到被点击的那个 for (let i = 0; i < hexagons.length; i++) { const hex = hexagons[i]; if (isPointInHexagon(clickX, clickY, hex.x, hex.y, r)) { currentHexIndex = i; $('#hexUpload').click(); // 触发文件选择框 break; } } }); // 文件选择完成后的处理 $('#hexUpload').on('change', function(e) { if (currentHexIndex === -1) return; const file = e.target.files[0]; if (!file) return; // 读取图片文件 const reader = new FileReader(); reader.onload = function(event) { const img = new Image(); img.onload = function() { const targetHex = hexagons[currentHexIndex]; // 裁剪画布为六边形区域,确保图片只显示在六边形内 ctx.save(); ctx.beginPath(); for (let i = 0; i < 6; i++) { ctx.lineTo(targetHex.x + r * Math.cos(a * i), targetHex.y + r * Math.sin(a * i)); } ctx.closePath(); ctx.clip(); // 绘制图片,适配六边形大小 const imgSize = r * 2; ctx.drawImage(img, targetHex.x - r, targetHex.y - r, imgSize, imgSize); ctx.restore(); // 恢复画布原始状态 } img.src = event.target.result; // 以下是上传示例,替换为你的后端接口即可 /* $.ajax({ url: '你的上传接口地址', type: 'POST', data: new FormData($('#hexUpload').closest('form')[0]), processData: false, contentType: false, success: function(res) { console.log('上传成功', res); }, error: function(err) { console.error('上传失败', err); } }); */ } reader.readAsDataURL(file); // 重置文件输入,允许重复选择同一张图片 $(this).val(''); currentHexIndex = -1; }); });
关键部分说明
- 六边形数据存储:用
hexagons数组记录每个六边形的中心坐标,是后续点击检测的基础。 - 碰撞检测:
isPointInHexagon利用正六边形的几何特性,通过坐标差计算快速判断点击位置是否在六边形内。 - jQuery事件绑定:通过隐藏的文件上传控件,实现点击六边形触发文件选择的交互,避免默认控件影响页面样式。
- 图片裁剪绘制:使用
ctx.clip()将绘制区域限制为六边形,保证图片完美适配图形范围。 - 上传逻辑:注释部分提供了jQuery Ajax上传的示例,可根据实际后端接口调整参数。
内容的提问来源于stack exchange,提问作者mySun
相关产品推荐
相关产品推荐

