
import "./cutting.less"
import * as htmlToImage from 'html-to-image';
import { Component, useState, createRef } from "react"
import { Button } from "antd"
 
class Cutting extends Component {
  constructor(props: any) {
    super(props)
    this.state = ({
      canvasNode: createRef(),// canvas DOM节点
      buttonGroupNode: createRef(),//裁剪框下的按钮组 DOM节点
      originImg: null,//源图
      startCoordinate: [0, 0], // 开始坐标
      leftTopPoint: [0, 0],//左上角起始点坐标
      dragging: false, //裁剪中
      dragComplate: false,//裁剪框绘制完毕
      trimPositionMap: [0, 0],  // 裁剪框坐标信息
      curPoisition: null,// 当前裁剪框坐标信息
      borderPixelPoisition: null //判断鼠标是否停留在裁剪框上4个点
 
    })
  }
  componentDidMount() {
    let { canvasNode } = this.state
    canvasNode.current.width = window.innerWidth
    canvasNode.current.height = window.innerHeight
  }
  getCanvas() {
    let { canvasNode } = this.state
    var node = document.getElementsByTagName("html")[0]
    htmlToImage.toPng(node).then(dataUrl => {
      canvasNode.current.style.zIndex = 999
 
      const image = new Image();
      image.src = dataUrl
      this.setState({
        originImg: image
      })
    })
  }
  handleMouseDownEvent = (e: any) => {
    let { buttonGroupNode, borderPixelPoisition, dragComplate, curPoisition, leftTopPoint } = this.state
    if (!borderPixelPoisition && dragComplate) {
      return
    }
    this.setState({
      dragComplate: false
    })
    this.setDraging(true)
    buttonGroupNode.current.style.display = "none"
    const { offsetX, offsetY } = e.nativeEvent;
    if (!borderPixelPoisition) {
      this.setState({
        startCoordinate: [offsetX, offsetY]
      })
    } else {
      let ltX = leftTopPoint[0], ltY = leftTopPoint[1], w = Math.abs(curPoisition.w), h = Math.abs(curPoisition.h)
      switch (borderPixelPoisition) {
        case 'lefttop':
          this.setState({
            startCoordinate: [ltX + w, ltY + h]
          })
          break;
        case "leftdown":
          this.setState({
            startCoordinate: [ltX + w, ltY]
          })
          break;
        case "righttop":
          this.setState({
            startCoordinate: [ltX, ltY + h]
          })
          break;
        case 'rightdown':
          this.setState({
            startCoordinate: leftTopPoint
          })
          break;
        default:
          break;
      }
    }
  }
  handleMouseMoveEvent = (e: any) => {
 
    let { dragging, canvasNode, startCoordinate, dragComplate, curPoisition, borderPixelPoisition, leftTopPoint } = this.state
    /** 是否绘制完成，判断鼠标有没有经过绘制的点上 */
    if (dragComplate) {
      const { offsetX, offsetY } = e.nativeEvent;
      let w = Math.abs(curPoisition.w), h = Math.abs(curPoisition.h), startX = leftTopPoint[0], startY = leftTopPoint[1]
      if (offsetX - startX < 2.5 && offsetX - startX > -2.5 && offsetY - startY < 2.5 && offsetY - startY > -2.5) {
        //左上角
        canvasNode.current.style.cursor = "nw-resize"
        this.setState({
          borderPixelPoisition: "lefttop"
        })
      } else if (offsetX - w - startX < 2.5 && offsetX - w - startX > -2.5 && offsetY - startY < 2.5 && offsetY - startY > -2.5) {
        //右上角
        canvasNode.current.style.cursor = "sw-resize"
        this.setState({
          borderPixelPoisition: "righttop"
        })
      } else if (offsetX - startX < 2.5 && offsetX - startX > -2.5 && offsetY - startY - h < 2.5 && offsetY - startY - h > -2.5) {
        //左下角
        canvasNode.current.style.cursor = "sw-resize"
        this.setState({
          borderPixelPoisition: "leftdown"
        })
      } else if (offsetX - w - startX < 2.5 && offsetX - w - startX > -2.5 && offsetY - startY - h < 2.5 && offsetY - startY - h > -2.5) {
        //右下角
        canvasNode.current.style.cursor = "nw-resize"
        this.setState({
          borderPixelPoisition: "rightdown"
        })
      } else {
        canvasNode.current.style.cursor = "default"
        this.setState({
          borderPixelPoisition: null
        })
      }
    }
    /**不在裁剪中 */
    if (!dragging) {
      return
    }
    const ctx = canvasNode.current.getContext('2d');
    // 每一帧都需要清除画布(取最后一帧绘图状态, 否则状态会累加)
    ctx.clearRect(0, 0, canvasNode.current.clientWidth, canvasNode.current.clientHeight);
    let tempWidth = 0, tempHeight = 0
    const { offsetX, offsetY } = e.nativeEvent;
 
    if (borderPixelPoisition && curPoisition) {
      this.setState({
        dragComplate: false
      })
      // 获取不同裁剪点下的高宽
      let { w, h } = this.getPixelTempWH(offsetX, offsetY)
      console.log(w, h)
      tempWidth = w
      tempHeight = h
    } else {
      // 计算临时裁剪框的宽高
      tempWidth = offsetX - startCoordinate[0];
      tempHeight = offsetY - startCoordinate[1];
    }
 
    // console.log(startCoordinate[0], startCoordinate[1])
    // 调用绘制裁剪框的方法
    this.drawTrim(startCoordinate[0], startCoordinate[1], tempWidth, tempHeight);
  }
  handleMouseRemoveEvent = (e: any) => {
    let { curPoisition, buttonGroupNode, borderPixelPoisition, dragComplate } = this.state
    //禁止已经绘画完截图之后，鼠标点击canvas又重新触发以下事件
    if (dragComplate) {
      return
    }
    // 结束裁剪
    this.setDraging(false)
 
    // 处理裁剪按钮样式
    if (curPoisition == null) {
      return;
    }
    if (buttonGroupNode == null) {
      return;
    }
    const { x, y } = e.nativeEvent;
    let ltX = x, ltY = y, w = curPoisition.w, h = curPoisition.h
    switch (borderPixelPoisition) {
      case "lefttop":
        break;
      case "righttop":
        ltX = x - w
        break;
      case "leftdown":
        ltY = y - h
        break;
      case "rightdown":
        ltX = x - w
        ltY = y - h
        break;
      default:
        ltX = x - w
        ltY = y - h
        break;
    }
    this.setState({
      leftTopPoint: [ltX, ltY],
      dragComplate: true
    })
    buttonGroupNode.current.style.display = "block"
    buttonGroupNode.current.style.left = `${ltX}px`
    buttonGroupNode.current.style.top = `${ltY + curPoisition.h + 10}px`;
  }
 
  // 调用绘制裁剪框的方法
  drawTrim(x: number, y: number, w: number, h: number, flag?: boolean) {
    let { canvasNode, originImg } = this.state
    const ctx = canvasNode.current.getContext('2d');
    // 绘制蒙层
    ctx.save();
    ctx.fillStyle = 'rgba(0,0,0,0.4)'; // 蒙层颜色
    ctx.fillRect(0, 0, canvasNode.current.clientWidth, canvasNode.current.clientHeight);
 
    // 将蒙层凿开
    ctx.globalCompositeOperation = 'source-atop';
    // 裁剪选择框
    ctx.clearRect(x, y, w, h);
 
    // 绘制8个边框像素点
    ctx.globalCompositeOperation = 'source-over';
    this.drawBorderPixel(ctx, x, y, w, h);
 
    // 保存当前区域坐标信息
    this.setState({
      curPoisition: {
        w: w,
        h: h,
        startX: x,
        startY: y,
        position: [
          [x, y],
          [x + w, y],
          [x, y + h],//左下角
          [x + w, y + h]
        ]
      }
    });
 
    ctx.restore();
 
    // 再次调用drawImage将图片绘制到蒙层下方
    ctx.save();
    ctx.globalCompositeOperation = 'destination-over';
    ctx.drawImage(originImg, 0, 0, canvasNode.current.clientWidth, canvasNode.current.clientHeight);
    ctx.restore();
  }
  // 绘制边框像素点的方法  
  drawBorderPixel = (ctx: any, x: number, y: number, w: number, h: number) => {
    ctx.fillStyle = '#f5222d';
    const size = 5; // 自定义像素点大小
    ctx.fillRect(x - size / 2, y - size / 2, size, size);
    // ...同理通过ctx.fillRect再画出其余像素点
    ctx.fillRect(x + w - size / 2, y - size / 2, size, size);
    ctx.fillRect(x - size / 2, y + h - size / 2, size, size);
    ctx.fillRect(x + w - size / 2, y + h - size / 2, size, size);
  };
  //获取不同裁剪点下的宽高
  /**
   * @param x 鼠标当前的x轴
   * @param y 鼠标当前的y轴
   */
  getPixelTempWH(x: number, y: number) {
    let { borderPixelPoisition, leftTopPoint, startCoordinate } = this.state
    let result = { w: 0, h: 0 }
    let ltX = leftTopPoint[0], ltY = leftTopPoint[1], startX = startCoordinate[0], startY = startCoordinate[1]
    switch (borderPixelPoisition) {
      case "lefttop":
        result.w = x - startX
        result.h = y - startY
        break;
      case "leftdown":
        result.w = x - startX
        result.h = y - ltY
        break;
      case "righttop":
        result.w = x - ltX
        result.h = y - startY
        break;
      case "rightdown":
        result.w = x - ltX
        result.h = y - ltY
        break;
      default:
        break;
    }
    return result
  }
  //清除画布
  clearCanvas() {
    let { canvasNode, buttonGroupNode } = this.state
    const ctx = canvasNode.current.getContext('2d');
    // 每一帧都需要清除画布(取最后一帧绘图状态, 否则状态会累加)
    ctx.clearRect(0, 0, canvasNode.current.clientWidth, canvasNode.current.clientHeight);
    canvasNode.current.style.zIndex = -1
    buttonGroupNode.current.style.display = "none"
    this.setState({
      dragComplate: false
    })
  }
  //获取裁剪图片输出
  getImageData() {
    let { canvasNode, curPoisition } = this.state
    const trimCanvasNode = document.createElement('canvas')
    trimCanvasNode.width = curPoisition.w;
    trimCanvasNode.height = curPoisition.h;
    const trimCtx = trimCanvasNode.getContext('2d');
    trimCtx.clearRect(0, 0, trimCanvasNode.width, trimCanvasNode.height);
    let ctx = canvasNode.current.getContext('2d')
    let data = ctx.getImageData(curPoisition.startX, curPoisition.startY, curPoisition.w, curPoisition.h)
    trimCtx.putImageData(data, 0, 0);
    const trimData = trimCanvasNode.toDataURL();
    console.log(trimData)
  }
  setDraging(flag: boolean) {
    this.setState({
      dragging: flag
    })
  }
  render() {
    let { canvasNode, buttonGroupNode } = this.state
    return (
      <div>
        <Button onClick={() => this.getCanvas()}>裁剪</Button>
        <canvas
          width="100%" height="100%"
          id="canvas"
          ref={canvasNode}
          onMouseDown={this.handleMouseDownEvent}
          onMouseMove={this.handleMouseMoveEvent}
          onMouseUp={this.handleMouseRemoveEvent}>
        </canvas>
        <div ref={buttonGroupNode} className="btns">
          <Button onClick={() => this.clearCanvas()}>取消</Button>
          <Button type="primary" onClick={() => this.getImageData()}>确定</Button>
        </div>
      </div>
    )
  }
}
export default Cutting