<!-- 子组件 transform-canvas.vue -->
<template>
  <view>
    <canvas 
      id="myCanvas" 
      canvas-id="myCanvas" 
      type="2d" 
      :style="{
        width: `${canvasDisplayWidth}px`, 
        height: `${canvasDisplayHeight}px`,
        border: '1px solid #eee'
      }"
    ></canvas>
  </view>
</template>

<script>
export default {
  props: {
    width: Number,    // 画布实际宽度(像素)
    height: Number,   // 画布实际高度(像素)
    imgUrl: String,   // 图片URL
    matrix: {         // 变换矩阵
      type: Object,
      default: () => ({
        a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0
      })
    },
		areaData:{}
  },
  data() {
    return {
      canvasContext: null,
      image: null,
      dpr: 1,
      canvasDisplayWidth: 800,  // 默认显示尺寸
      canvasDisplayHeight: 600,
      canvasActualWidth: 800,  // 实际像素尺寸
      canvasActualHeight: 600
    };
  },
  watch: {
    imgUrl: {
      handler(newUrl) {
        if (newUrl) this.loadImage(newUrl);
      },
      immediate: true
    },
    width: {
      handler() {
        this.updateCanvasSize();
      },
      immediate: true
    },
    height: {
      handler() {
        this.updateCanvasSize();
      },
      immediate: true
    },
    matrix: {
			deep: true,
			immediate: true, // 添加立即触发
			handler() {
				this.$nextTick(this.redraw); // 确保在下一个tick重绘
			}
		},
  },
  mounted() {
    this.initCanvas();
  },
  methods: {
		// 添加点击检测方法
		checkHitArea(x, y) {
			if (!this.areaData) return null;
			
			// 转换坐标到原始画布空间
			const inverted = this.matrix.invertPoint(x, y);
			console.log('checkHitArea',inverted)
			// 遍历所有区域检测
			for (const area of this.areaData) {
				if (this.pointInPolygon(inverted.x, inverted.y, area.polygon)) {
					return area.areacode;
				}
			}
			return null;
		},
		// 射线法判断点是否在多边形内
		// pointInPolygon(x, y, polygon) {
		// 	// console.log('pointInPolygon',x, y, polygon)
		//   // 确保多边形有足够的点构成
		//   if (!polygon || polygon.length < 6) return false;
		  
		//   let inside = false;
		//   const length = polygon.length;
		  
		//   // 不需要遍历最后一个点，因为它是闭合点（与第一个点相同）
		//   for (let i = 0, j = length - 2; i < length; j = i, i += 2) {
		//     const xi = polygon[i], yi = polygon[i + 1];
		//     const xj = polygon[j], yj = polygon[j + 1];
		    
		//     // 检查点是否在边的y值范围内
		//     const intersect = ((yi > y) !== (yj > y));
		    
		//     // 检查点是否在边的左侧
		//     if (intersect) {
		//       const slope = (xj - xi) / (yj - yi); // 边的斜率
		//       const intersectX = xi + (y - yi) * slope;
		      
		//       if (x < intersectX) {
		//         inside = !inside;
		//       }
		//     }
		//   }
		//   return inside;
		// },
		
		// 在 transform-canvas.vue 中替换 pointInPolygon 方法
		pointInPolygon(x, y, polygon) {
		  // 确保多边形的点数是偶数且至少有3个顶点
		  if (!polygon || polygon.length < 6 || polygon.length % 2 !== 0) {
		    return false;
		  }
		  
		  let inside = false;
		  // 转换多边形点数为顶点数
		  const vertexCount = polygon.length / 2;
		  let j = vertexCount - 1;
		  
		  for (let i = 0; i < vertexCount; j = i++) {
		    // 获取当前顶点和上一个顶点
		    const xi = polygon[i * 2];
		    const yi = polygon[i * 2 + 1];
		    const xj = polygon[j * 2];
		    const yj = polygon[j * 2 + 1];
		    
		    // 检查点是否在边界上 - 提高精度避免浮点数误差
		    const onLine = this.pointOnLineSegment(x, y, xi, yi, xj, yj);
		    if (onLine) return true;
		    
		    // 检查点是否在两个顶点之间（射线法）
		    if ((yi < y && yj >= y) || (yj < y && yi >= y)) {
		      // 计算射线与边界的交点
		      const slope = (xj - xi) / (yj - yi);
		      const intersectX = xi + (y - yi) * slope;
		      
		      // 如果交点在点右侧，标记为穿越
		      if (x < intersectX) {
		        inside = !inside;
		      }
		    }
		  }
		  
		  return inside;
		},
		
		// 添加点是否在线段上的检查
		pointOnLineSegment(x, y, x1, y1, x2, y2) {
		  // 线段的长度
		  const dx = x2 - x1;
		  const dy = y2 - y1;
		  const segmentLength = Math.sqrt(dx * dx + dy * dy);
		  
		  // 点到线段起点的向量
		  const vx = x - x1;
		  const vy = y - y1;
		  
		  // 向量在方向上的投影
		  const dotProduct = vx * dx + vy * dy;
		  
		  // 计算参数t (0-1之间表示在线段上)
		  const t = dotProduct / (segmentLength * segmentLength);
		  
		  // 点在线段上
		  if (t >= 0 && t <= 1) {
		    // 计算点在线段上的位置
		    const projX = x1 + t * dx;
		    const projY = y1 + t * dy;
		    
		    // 检查点与投影点的距离（容差5px）
		    const distance = Math.sqrt((x - projX) ** 2 + (y - projY) ** 2);
		    return distance < 5;
		  }
		  
		  return false;
		},
		
    initCanvas() {
      const query = uni.createSelectorQuery().in(this);
      query.select('#myCanvas')
        .fields({ node: true, size: true })
        .exec(async (res) => {
          if (!res[0]) return;
          
          this.canvas = res[0].node;
          this.ctx = res[0].node.getContext('2d');
          
          // 获取设备像素比
          this.dpr = uni.getSystemInfoSync().pixelRatio;
          
          // 更新画布尺寸
          this.updateCanvasSize();
          
          // 如果已有图片URL，加载图片
          if (this.imgUrl) {
            await this.loadImage(this.imgUrl);
          }
        });
    },
    
    updateCanvasSize() {
      // 显示尺寸使用prop传入的width/height
      this.canvasDisplayWidth = this.width;
      this.canvasDisplayHeight = this.height;
      
      // 实际像素尺寸考虑DPR
      this.canvasActualWidth = this.width * this.dpr;
      this.canvasActualHeight = this.height * this.dpr;
      
      if (this.canvas) {
        this.canvas.width = this.canvasActualWidth;
        this.canvas.height = this.canvasActualHeight;
        this.ctx.scale(this.dpr, this.dpr);
        this.redraw();
      }
    },
    async loadImage(src) {
      try {
        // 等待canvas初始化
        if (!this.canvas) {
          await this.initCanvas();
        }
        
        this.image = await new Promise((resolve, reject) => {
          if (!this.canvas) {
            // reject(new Error("Canvas not initialized"));
            return;
          }
          
          const image = this.canvas.createImage();
          image.src = src;
          image.onload = () => resolve(image);
          image.onerror = reject;
        });
        this.redraw();
      } catch (e) {
        console.error("图片加载失败:", e);
        this.image = null;
      }
    },
		
  //   async loadImage(src) {
  //     try {
  //       this.image = await new Promise((resolve, reject) => {
  //         const image = this.canvas.createImage();
  //         image.src = src;
  //         image.onload = () => resolve(image);
  //         image.onerror = reject;
  //       });
  //       this.redraw();
  //     } catch (e) {
  //       console.error("图片加载失败:", e);
  //       this.image = null;
  //       this.redraw(); // 加载失败时也需要重绘画布
  //     }
  //   },
    
    redraw() {
      if (!this.ctx) return;
      
      // 保存当前状态
      this.ctx.save();
      
      // 重置为初始状态
      this.ctx.resetTransform();
      this.ctx.clearRect(0, 0, this.canvasActualWidth, this.canvasActualHeight);
      
      // 应用设备像素比缩放
      this.ctx.scale(this.dpr, this.dpr);
      
      // 应用变换矩阵
      const { a, b, c, d, tx, ty } = this.matrix;
      this.ctx.setTransform(a, b, c, d, tx, ty);
      
      // 绘制图片（或错误信息）
      if (this.image) {
        this.ctx.drawImage(
          this.image, 
          0, 
          0, 
          this.canvasDisplayWidth, 
          this.canvasDisplayHeight
        );
      } 
			// this.ctx.restore();
      
      // 恢复上下文状态
			  if (this.areaData && this.areaData.length > 0) {
			    this.areaData.forEach(area => {
			      // if (!area.polygon || area.polygon.length < 6) return;
			      
			      this.ctx.beginPath();
			      
			      for (let i = 0; i < area.polygon.length; i += 2) {
			        // 使用标准API
			        if (i === 0) {
			          this.ctx.moveTo(area.polygon[i], area.polygon[i + 1]);
			        } else {
			          this.ctx.lineTo(area.polygon[i], area.polygon[i + 1]);
			        }
			      }
			      
			      this.ctx.closePath();
			      this.ctx.strokeStyle = 'rgba(255, 0, 0, 0.7)';
			      this.ctx.lineWidth = 2;
			      this.ctx.stroke();
			      this.ctx.fillStyle = 'rgba(0, 255, 0, 0.2)';
			      this.ctx.fill();
			    });
			  }
			  
    }
  }
}
</script>