You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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;
  });
});

关键部分说明

  1. 六边形数据存储:用hexagons数组记录每个六边形的中心坐标,是后续点击检测的基础。
  2. 碰撞检测:isPointInHexagon利用正六边形的几何特性,通过坐标差计算快速判断点击位置是否在六边形内。
  3. jQuery事件绑定:通过隐藏的文件上传控件,实现点击六边形触发文件选择的交互,避免默认控件影响页面样式。
  4. 图片裁剪绘制:使用ctx.clip()将绘制区域限制为六边形,保证图片完美适配图形范围。
  5. 上传逻辑:注释部分提供了jQuery Ajax上传的示例,可根据实际后端接口调整参数。

内容的提问来源于stack exchange,提问作者mySun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 16:16:10