<template>
  <view class="t-cropper" v-show="props.imageUrl" disable-scroll>
    <!-- #ifdef MP-WEIXIN || MP-ALIPAY-->
    <canvas
      type="2d"
      canvas-id="canvas-cropper"
      id="canvas-cropper"
      class="canvas"
    ></canvas>
    <!-- #endif -->

    <!-- #ifdef APP-PLUS || H5 -->
    <canvas
      :canvas-id="canvasId"
      :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
    ></canvas>
    <!-- #endif -->
    <!-- 裁剪区域 -->
    <view class="t-preview-container" :class="{ showPage: inInit }">
      <view
        class="preview-body"
        @touchstart="(e) => touchStart(e, 'body')"
        @touchmove="touchMove"
        @touchend="touchEnd"
        @touchcancel="touchCancel"
      >
        <!-- 完整背景图片 -->
        <view
          class="image-wrap"
          :class="{ transit: transit }"
          :style="comImageStyle('image-wrap')"
        >
          <image
            class="image"
            :class="{ transit: transit }"
            :src="imageUrl"
            @load="imageLoad"
            :style="comImageStyle('image')"
          />
        </view>
        <view class="mask-model"></view>
        <view
          class="frame-box"
          :class="{ transit: transit }"
          :style="comImageStyle('frame-box')"
        >
          <view class="rect" :style="cirStyle">
            <!-- 裁剪框图片 -->
            <view
              class="image-rect"
              :class="{ transit: transit }"
              :style="comImageStyle('image-rect')"
            >
              <image
                class="rect-img"
                :class="{ transit: transit }"
                :src="imageUrl"
                :style="comImageStyle('image')"
              />
            </view>
          </view>
          <!-- 矩阵框线条 -->
          <view v-if="props.radius < 50" class="line-box">
            <view class="line-one"></view>
            <view class="line-two"></view>
            <view class="line-three"></view>
            <view class="line-four"></view>
          </view>
          <view
            class="frame-left-top"
            @touchstart.stop="(e) => touchStart(e, 'left-top')"
          ></view>
          <view
            class="frame-left-bottom"
            @touchstart.stop="(e) => touchStart(e, 'left-bottom')"
          ></view>
          <view
            class="frame-right-top"
            @touchstart.stop="(e) => touchStart(e, 'right-top')"
          ></view>
          <view
            class="frame-right-bottom"
            @touchstart.stop="(e) => touchStart(e, 'right-bottom')"
          ></view>
        </view>
      </view>
      <!-- 底部工具栏 -->
      <view class="toolbar">
        <view @tap.stop="onCancle" class="btn-cancel">取消</view>
        <view v-if="props.isRotateBtn" @tap.stop="onAngle" class="btn-rotate">
          <image src="@/uni_modules/t-cropper/static/svg/rotate.svg" />
        </view>
        <view @tap.stop="onConfirm" class="btn-confirm">确定</view>
      </view>
    </view>
  </view>
</template>

<script setup>
import {
  reactive,
  ref,
  watchEffect,
  computed,
  getCurrentInstance,
  toRefs,
} from "vue";

/**
 * @property {String} mode 模式
 * @value fixed 固定模式，裁剪出固定大小
 * @value ratio 等比模式，宽高等比缩放
 * @value free 自由模式，不限制宽高比
 * @property {String} imageUrl 图片路径
 * @property {Number} width 宽度
 * @property {Number} height 高度
 * @property {Number} maxWidth 最大宽度
 * @property {Number} minHeight 最大高度
 * @property {Number} scaleRatio 裁剪比列缩放
 * @property {Number} minRatio 最小缩放
 * @property {Number} maxRatio 最大缩放
 * @property {Boolean} isRotateBtn 是否显示旋转
 * @property {Number} radius 裁剪图片圆角半径，单位px
 * @property {Number} delay 快速重复点击时间
 * @property {Boolean} isCutSize 是否导出高清裁剪原图
 */
const props = defineProps({
  mode: {
    type: String,
    default: "ratio",
  },
  imageUrl: {
    type: String,
    default: "",
  },
  width: {
    type: Number,
    default: 200,
  },
  height: {
    type: Number,
    default: 200,
  },
  maxWidth: {
    type: Number,
    default: 1024,
  },
  maxHeight: {
    type: Number,
    default: 1024,
  },
  scaleRatio: {
    type: Number,
    default: 0.7,
  },
  minRatio: {
    type: Number,
    default: 1,
  },
  maxRatio: {
    type: Number,
    default: 3,
  },
  isRotateBtn: {
    type: Boolean,
    default: true,
  },
  isCutSize: {
    type: Boolean,
    default: true,
  },
  radius: {
    type: Number,
    default: 0,
  },
  delay: {
    type: Number,
    default: 250,
  },
});

// 获取组件实例
const instance = getCurrentInstance();
const inInit = ref(false);
const $emit = defineEmits(["confirm", "cancel"]);
const canvasId = ref(Math.random().toString(36).slice(-6));

//获取原始图片的大小
const origin = reactive({
  imageUrl: "", //设置图片url
  real: {
    //原始图片宽高
    width: 100,
    height: 100,
  },
  body: {
    //页面宽高
    width: 100,
    height: 100,
  },
  frame: {
    //矩形框
    left: 50,
    top: 50,
    width: 200,
    height: 300,
  },
  bgImage: {
    //背景框
    left: 20,
    top: 20,
    width: 300,
    height: 400,
  },
  rotate: 0,
  transit: false,
  canvasWidth: 100,
  canvasHeight: 100,
});

const { transit, rotate, imageUrl, canvasWidth, canvasHeight } = toRefs(origin);

//监听原始图片的变动
watchEffect(() => {
  if (props.imageUrl) {
    uni.showLoading({
      title: "请稍候...",
      mask: true,
    });
    origin.imageUrl = props.imageUrl; //设置图片url}
  }
});

//检测图片加载完成
const imageLoad = (e) => {
  const { width, height } = e.detail;
  origin.real.width = width;
  origin.real.height = height;
  var query = uni.createSelectorQuery().in(instance);
  query
    .select(".preview-body")
    .boundingClientRect((data) => {
      origin.body.width = data.width;
      origin.body.height = data.height;
      inInit.value = true;
      imageReset(); //重置图片
    })
    .exec();
};

//重置图片
const imageReset = () => {
  origin.rotate = 0;
  let frameRate = props.width / props.height; //裁剪比列
  let frameHeight = origin.body.height * props.scaleRatio; //裁剪框图片高度 * 缩小0.7倍
  let frameWidth = origin.body.width * props.scaleRatio; //裁剪框图片宽度 * 缩小0.7倍

  // 裁剪框的位置：
  // 缩放后的宽度/高度 > 组件裁剪的比例，就要对宽度重写
  if (frameWidth / frameHeight > frameRate) {
    frameWidth = frameHeight * frameRate;
  } else {
    frameHeight = frameWidth / frameRate;
  }

  // 裁剪框左边距=页面宽度-裁剪框宽度 / 2
  let frameleft = (origin.body.width - frameWidth) / 2;
  let frameTop = (origin.body.height - frameHeight) / 2;
  origin.frame = {
    left: frameleft,
    top: frameTop,
    width: frameWidth,
    height: frameHeight,
  };

  // 背景图片位置：
  let bgRate = origin.real.width / origin.real.height; //背景比列
  let bgWidth = frameWidth;
  let bgHeight = frameHeight;

  // 裁剪框图片宽度/裁剪框图片高度>实际的图片比例
  if (bgWidth / bgHeight > bgRate) {
    bgHeight = bgWidth / bgRate;
  } else {
    bgWidth = bgHeight * bgRate;
  }

  // 背景左边距
  let bgLeft = (frameWidth - bgWidth) / 2 + origin.frame.left;
  // 背景右边距
  let bgTop = (frameHeight - bgHeight) / 2 + origin.frame.top;

  origin.bgImage = {
    left: bgLeft,
    top: bgTop,
    width: bgWidth,
    height: bgHeight,
  };
  uni.hideLoading();
};

//公共图片背景位置
const comImageStyle = computed(() => (source) => {
  const { left, top, width, height } = origin.bgImage;
  if (source == "image-wrap") {
    //计算背景盒子样式
    return `
      top: ${top}px;
      left: ${left}px;
      width: ${width}px;
      height: ${height}px;
    `;
  } else if (source == "image") {
    // 计算背景图片样式
    let left = 0;
    let top = 0;
    let width = origin.bgImage.width;
    let height = origin.bgImage.height;

    if (origin.rotate % 180 != 0) {
      width = origin.bgImage.height;
      height = origin.bgImage.width;
      top = width / 2 - height / 2;
      left = height / 2 - width / 2;
    }
    const style = {};
    style.left = left + "px";
    style.top = top + "px";
    style.width = width + "px";
    style.height = height + "px";
    style.transform = `rotate(${origin.rotate}deg)`;
    return style;
  } else if (source == "image-rect") {
    // 计算裁剪框上显示的图片位置
    return `
      top: ${top - origin.frame.top}px;
      left: ${left - origin.frame.left}px;
      width: ${width}px;
      height: ${height}px;
    `;
  } else if (source == "frame-box") {
    return `
      left: ${origin.frame.left}px;
      top: ${origin.frame.top}px;
      width: ${origin.frame.width}px;
      height: ${origin.frame.height}px;
    `;
  }
});

//计算圆角比列
const cirStyle = computed(() => {
  const { width } = origin.frame;
  let scale = props.width / width;
  let radius = props.radius / scale;
  return `
  border-radius: ${radius}px
  `;
});

// 取消按钮
const onCancle = () => {
  $emit("cancel");
};
// 旋转按钮
const onAngle = () => {
  origin.rotate -= 90;
  var width = origin.bgImage.height;
  var height = origin.bgImage.width;
  var left = origin.bgImage.left;
  var top = origin.bgImage.top;
  var rate = width / height;
  if (width < origin.frame.width) {
    width = origin.frame.width;
    height = width / rate;
  }
  if (height < origin.frame.height) {
    height = origin.frame.height;
    width = height * rate;
  }
  if (left > origin.frame.left) {
    left = origin.frame.left;
  }
  if (top > origin.frame.top) {
    top = origin.frame.top;
  }
  if (left + width < origin.frame.left + origin.frame.width) {
    left = origin.frame.left + origin.frame.width - width;
  }
  if (top + height < origin.frame.top + origin.frame.height) {
    top = origin.frame.top + origin.frame.height - height;
  }
  origin.bgImage = {
    left: left,
    top: top,
    width: width,
    height: height,
  };
  origin.transit = true;
  setTimeout(() => {
    origin.transit = false;
  }, 300);
};

/**
 * @name:防抖
 * @param {function} fn
 * @param {wait} wait
 * @return {function}
 */
const debounce = (fn, wait = 1000) => {
  let time = null;
  return function (...args) {
    if (time) clearTimeout(time);
    time = setTimeout(() => {
      fn.apply(this, args);
    }, wait);
  };
};

// 确定按钮
const onConfirm = debounce(async () => {
  // #ifdef H5 || APP-PLUS
  confirmH5();
  // #endif

  // #ifdef MP-WEIXIN || MP-ALIPAY
  confirmWx();
  // #endif
}, props.delay);

// h5裁剪确认
const confirmH5 = async () => {
  let mx = computeMatrix(); //获取画布的信息
  // 设备画布的宽高
  origin.canvasWidth = mx.tw;
  origin.canvasHeight = mx.th;
  uni.showLoading({
    title: "处理中",
  });

  // 设置宽高后等待更新完成在获取Canvas节点
  await new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, 200);
  });

  // 创建一个画布
  let ctx = uni.createCanvasContext(canvasId.value, instance);
  // 矩形内清除指定的像素
  await ctx.clearRect(0, 0, mx.tw, mx.th);
  //剪切圆角
  await drawClipImage(ctx, mx);
  // 旋转
  ctx.rotate((origin.rotate * Math.PI) / 180);
  //绘制图片
  ctx.drawImage(
    props.imageUrl,
    mx.sx,
    mx.sy,
    mx.sw,
    mx.sh,
    mx.dx,
    mx.dy,
    mx.dw,
    mx.dh
  );
  ctx.restore();

  ctx.draw(false, () => {
    uni.canvasToTempFilePath(
      {
        canvasId: canvasId.value,
        // #ifdef H5
        destWidth: props.isCutSize ? mx.tw : origin.frame.width,
        destHeight: props.isCutSize ? mx.th : origin.frame.height,
        // #endif
        success: (res) => {
          var path = res.tempFilePath;
          // #ifdef H5
          // 暂时去掉转化为blob对象的处理
          // path = parseBlob(path);
          $emit("confirm", {
            errMsg: "parseBlob:ok",
            tempFilePath: path,
          });
          // #endif

          // #ifdef APP-PLUS
          $emit("confirm", res);
          // #endif
        },
        fail: (err) => {
          console.log(err);
        },
        complete: () => {
          uni.hideLoading(); //关闭loading
        },
      },
      instance
    );
  });
};
// 微信确认
const confirmWx = () => {
  uni.showLoading({
    title: "处理中",
  });
  let mx = computeMatrix(); //获取画布的信息
  uni
    .createSelectorQuery()
    // #ifndef MP-ALIPAY
    .in(instance)
    // #endif
    .select("#canvas-cropper")
    .fields({
      node: true,
      size: true,
    })
    .exec(async (res) => {
      const textCanvas = res[0].node;
      const ctx = textCanvas.getContext("2d");

      // 初始化画布大小
      textCanvas.width = mx.tw;
      textCanvas.height = mx.th;
      // //绘制canvas
      await drawClipImage(ctx, mx); //剪切圆角
      await ctx.rotate((origin.rotate * Math.PI) / 180);
      await createImage(origin.imageUrl, mx, ctx, textCanvas);

      // #ifdef MP-WEIXIN
      wx.canvasToTempFilePath({
        canvas: textCanvas,
        canvasId: "canvasID",
        success: (res) => {
          $emit("confirm", res);
        },
        fail: (err) => {
          console.log(err);
        },
      });
      // #endif

      // #ifdef MP-ALIPAY
      textCanvas.toTempFilePath({
        success: (res) => {
          $emit("confirm", res);
        },
        fail: (err) => {
          console.log(err);
        },
      });
      // #endif

      uni.hideLoading(); //关闭loading
    });
};
//剪切图片圆角
const drawClipImage = (ctx, mx) => {
  let { radius } = props;
  if (radius > 0) {
    const w = Math.round(mx.tw); //画布宽度
    const h = Math.round(mx.th); //画布高度

    // 被缩放后的尺寸且裁剪的宽高相同
    if (props.width === props.height && w == h && props.width < w) {
      radius = (w / props.width) * radius;
    }
    // 被缩放后的尺寸且裁剪的宽高不相同
    if (props.width != props.height && w != h && props.width < w) {
      console.log("11111111");
      if (w > h) {
        radius = (w / h) * radius;
      } else {
        radius = (h / w) * radius;
      }
    }
    // 如果裁剪是圆形
    if (w === h && radius >= w / 2) {
      // 圆形
      ctx.arc(w / 2, h / 2, w / 2, 0, 2 * Math.PI);
    } else {
      // 圆角矩形
      if (w !== h) {
        // 限制圆角半径不能超过短边的一半
        radius = Math.min(w / 2, h / 2, radius);
      }
      // 其他形状
      ctx.moveTo(radius, 0);
      ctx.arcTo(w, 0, w, h, radius);
      ctx.arcTo(w, h, 0, h, radius);
      ctx.arcTo(0, h, 0, 0, radius);
      ctx.arcTo(0, 0, w, 0, radius);
      ctx.closePath();
    }
    ctx.clip(); //从原始画布剪切任意形状和尺寸的区域
    ctx.restore(); //返回之前保存过的路径状态和属性
  }
};
// 创建一个图片
const createImage = (img, mx, ctx, textCanvas) => {
  return new Promise((resolve) => {
    const headerImg = textCanvas.createImage();
    headerImg.src = img;
    headerImg.onload = () => {
      let result = ctx.drawImage(
        headerImg,
        mx.sx,
        mx.sy,
        mx.sw,
        mx.sh,
        mx.dx,
        mx.dy,
        mx.dw,
        mx.dh
      );
      resolve(result);
    };
  });
};

//计算矩阵
const computeMatrix = () => {
  let width = props.width;
  let height = props.height;
  let mul = origin.bgImage.width / origin.real.width;
  if (origin.rotate % 180 != 0) {
    mul = origin.bgImage.height / origin.real.width;
  }
  if (props.mode != "fixed") {
    width = origin.frame.width / mul;
    height = origin.frame.height / mul;
  }
  var rate = width / height;
  if (width > props.maxWidth) {
    width = props.maxWidth;
    height = width / rate;
  }
  if (height > props.maxHeight) {
    height = props.maxHeight;
    width = height * rate;
  }
  var sx = (origin.frame.left - origin.bgImage.left) / mul;
  var sy = (origin.frame.top - origin.bgImage.top) / mul;
  var sw = origin.frame.width / mul;
  var sh = origin.frame.height / mul;
  var ox = sx + sw / 2;
  var oy = sy + sh / 2;
  if (origin.rotate % 180 != 0) {
    var temp = sw;
    sw = sh;
    sh = temp;
  }
  var angle = origin.rotate % 360;
  if (angle < 0) {
    angle += 360;
  }
  if (angle == 270) {
    var x = origin.real.width - oy;
    var y = ox;
    ox = x;
    oy = y;
  }
  if (angle == 180) {
    var x = origin.real.width - ox;
    var y = origin.real.height - oy;
    ox = x;
    oy = y;
  }
  if (angle == 90) {
    var x = oy;
    var y = origin.real.height - ox;
    ox = x;
    oy = y;
  }
  sx = ox - sw / 2;
  sy = oy - sh / 2;
  let dr = { x: 0, y: 0, w: width, h: height };
  dr = parseRect(dr, -origin.rotate);
  return {
    tw: width,
    th: height,
    sx: sx,
    sy: sy,
    sw: sw,
    sh: sh,
    dx: dr.x,
    dy: dr.y,
    dw: dr.w,
    dh: dr.h,
  };
};
// 计算矩阵
const parseRect = (rect, angle) => {
  let x1 = rect.x;
  let y1 = rect.y;
  let x2 = rect.x + rect.w;
  let y2 = rect.y + rect.h;
  let p1 = parsePoint({ x: x1, y: y1 }, angle);
  let p2 = parsePoint({ x: x2, y: y2 }, angle);
  let result = {};
  result.x = Math.min(p1.x, p2.x);
  result.y = Math.min(p1.y, p2.y);
  result.w = Math.abs(p2.x - p1.x);
  result.h = Math.abs(p2.y - p1.y);
  return result;
};
// 计算x、y
const parsePoint = (point, angle) => {
  var result = {};
  result.x =
    point.x * Math.cos((angle * Math.PI) / 180) -
    point.y * Math.sin((angle * Math.PI) / 180);
  result.y =
    point.y * Math.cos((angle * Math.PI) / 180) +
    point.x * Math.sin((angle * Math.PI) / 180);
  return result;
};
// base64转blob
const parseBlob = (base64) => {
  var arr = base64.split(",");
  var mime = arr[0].match(/:(.*?);/)[1];
  var bstr = atob(arr[1]);
  var n = bstr.length;
  var u8arr = new Uint8Array(n);
  for (var i = 0; i < n; i++) {
    u8arr[i] = bstr.charCodeAt(i);
  }
  var url = URL || webkitURL;console.log(mime)
  return url.createObjectURL(new Blob([u8arr], { type: mime }));
};
/**
 * 绘制手指触摸
 */
const move = reactive({
  touchType: "body", //移动的类型
  start: {
    //开始的位置
    frame: {
      left: 0,
      top: 0,
      width: 0,
      height: 0,
    },
    bgImage: {
      left: 0,
      top: 0,
      width: 0,
      height: 0,
    },
  },
});

const touch = reactive({
  touchStart: [], //记录开始触摸
});

//  手指触摸动作开始
const touchStart = (e, touchType = "") => {
  // #ifdef APP-PLUS || H5
  if (e.preventDefault) {
    e.preventDefault();
  }
  if (e.stopPropagation) {
    e.stopPropagation();
  }
  // #endif

  switch (touchType) {
    case "body":
      move.touchType = "body";
      break;
    case "left-top":
      move.touchType = "left-top";
      break;
    case "left-bottom":
      move.touchType = "left-bottom";
      break;
    case "right-top":
      move.touchType = "right-top";
      break;
    case "right-bottom":
      move.touchType = "right-bottom";
      break;
    default:
      move.touchType = "body";
      break;
  }

  touch.touchStart = e.touches;
  // 裁剪框的开始位置
  move.start.frame.left = origin.frame.left;
  move.start.frame.top = origin.frame.top;
  move.start.frame.width = origin.frame.width;
  move.start.frame.height = origin.frame.height;

  // 背景图片的开始位置
  move.start.bgImage.left = origin.bgImage.left;
  move.start.bgImage.top = origin.bgImage.top;
  move.start.bgImage.width = origin.bgImage.width;
  move.start.bgImage.height = origin.bgImage.height;
  return false;
};

// 手指触摸后移动
const touchMove = (e) => {
  // #ifdef APP-PLUS || H5
  if (e.preventDefault) {
    e.preventDefault();
  }
  if (e.stopPropagation) {
    e.stopPropagation();
  }
  // #endif
  // 单手操作
  if (touch.touchStart.length == 1) {
    if (move.touchType == "body") {
      // 移动图片
      moveImage(touch.touchStart[0], e.touches[0]);
    } else {
      if (props.mode != "fixed") {
        // 放大缩小图片
        scaleFrame(touch.touchStart[0], e.touches[0]);
      }
    }
  } else if (touch.touchStart.length == 2 && e.touches.length == 2) {
    var ta = touch.touchStart[0];
    var tb = touch.touchStart[1];
    var tc = e.touches[0];
    var td = e.touches[1];
    if (ta.identifier != tc.identifier) {
      var temp = tc;
      tc = td;
      td = temp;
    }
    scaleImage(ta, tb, tc, td);
  }
};

// 移动图片
const moveImage = (ta, tb) => {
  let mx = tb.clientX - ta.clientX;
  let my = tb.clientY - ta.clientY;
  // 开始移动图片背景 + 移动的左边距离
  origin.bgImage.left = move.start.bgImage.left + mx;
  origin.bgImage.top = move.start.bgImage.top + my;

  let frameLeft = origin.frame.left;
  let frameTop = origin.frame.top;
  let frameWidth = origin.frame.width;
  let frameHeight = origin.frame.height;

  // 左边触边
  if (origin.bgImage.left > frameLeft) {
    origin.bgImage.left = frameLeft;
  }
  // 头部触边
  if (origin.bgImage.top > frameTop) {
    origin.bgImage.top = frameTop;
  }
  // 右边触边
  if (origin.bgImage.left + origin.bgImage.width < frameLeft + frameWidth) {
    origin.bgImage.left = frameLeft + frameWidth - origin.bgImage.width;
  }
  // 底部触边：背景距离头部+背景的高度 < 背景高度 + 矩形框顶部
  if (origin.bgImage.top + origin.bgImage.height < frameTop + frameHeight) {
    origin.bgImage.top = frameTop + frameHeight - origin.bgImage.height;
  }
};

//缩放裁剪框
const scaleFrame = (ta, tb) => {
  var mx = tb.clientX - ta.clientX;
  var my = tb.clientY - ta.clientY;
  var x1 = move.start.frame.left;
  var y1 = move.start.frame.top;
  var x2 = move.start.frame.left + move.start.frame.width;
  var y2 = move.start.frame.top + move.start.frame.height;
  var cx1 = false;
  var cy1 = false;
  var cx2 = false;
  var cy2 = false;
  var mix = 30;
  var mix = 30;
  var rate = origin.frame.width / origin.frame.height;

  //左上角
  if (move.touchType == "left-top") {
    x1 += mx;
    y1 += my;
    cx1 = true;
    cy1 = true;
    // 左下角
  } else if (move.touchType == "left-bottom") {
    x1 += mx;
    y2 += my;
    cx1 = true;
    cy2 = true;
    // 右上角
  } else if (move.touchType == "right-top") {
    x2 += mx;
    y1 += my;
    cx2 = true;
    cy1 = true;
    // 右下角
  } else if (move.touchType == "right-bottom") {
    x2 += mx;
    y2 += my;
    cx2 = true;
    cy2 = true;
  }

  if (x1 < origin.bgImage.left) {
    x1 = origin.bgImage.left;
  }
  if (y1 < origin.bgImage.top) {
    y1 = origin.bgImage.top;
  }
  if (x2 > origin.bgImage.left + origin.bgImage.width) {
    x2 = origin.bgImage.left + origin.bgImage.width;
  }
  if (y2 > origin.bgImage.top + origin.bgImage.height) {
    y2 = origin.bgImage.top + origin.bgImage.height;
  }
  if (cx1) {
    if (x1 > x2 - mix) {
      x1 = x2 - mix;
    }
  }
  if (cy1) {
    if (y1 > y2 - mix) {
      y1 = y2 - mix;
    }
  }
  if (cx2) {
    if (x2 < x1 + mix) {
      x2 = x1 + mix;
    }
  }
  if (cy2) {
    if (y2 < y1 + mix) {
      y2 = y1 + mix;
    }
  }
  if (cx1) {
    if (props.mode != "free") {
      var val = x2 - rate * (y2 - y1);
      if (x1 < val) {
        x1 = val;
      }
    }
  }
  if (cy1) {
    if (props.mode != "free") {
      var val = y2 - (x2 - x1) / rate;
      if (y1 < val) {
        y1 = val;
      }
    }
  }
  if (cx2) {
    if (props.mode != "free") {
      var val = rate * (y2 - y1) + x1;
      if (x2 > val) {
        x2 = val;
      }
    }
  }
  if (cy2) {
    if (props.mode != "free") {
      var val = (x2 - x1) / rate + y1;
      if (y2 > val) {
        y2 = val;
      }
    }
  }

  origin.frame.left = x1;
  origin.frame.top = y1;
  origin.frame.width = x2 - x1;
  origin.frame.height = y2 - y1;
};

//双指缩放图片
const scaleImage = (ta, tb, tc, td) => {
  let x1 = ta.clientX;
  let y1 = ta.clientY;
  let x2 = tb.clientX;
  let y2 = tb.clientY;
  let x3 = tc.clientX;
  let y3 = tc.clientY;
  let x4 = td.clientX;
  let y4 = td.clientY;
  let ol = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  let el = Math.sqrt((x3 - x4) * (x3 - x4) + (y3 - y4) * (y3 - y4));
  let ocx = (x1 + x2) / 2;
  let ocy = (y1 + y2) / 2;
  let ecx = (x3 + x4) / 2;
  let ecy = (y3 + y4) / 2;
  let ax = ecx - ocx;
  let ay = ecy - ocy;
  let scale = el / ol;

  // 检测放大/缩小倍率
  if (move.start.bgImage.width * scale < origin.frame.width) {
    scale = origin.frame.width / move.start.bgImage.width;
  }

  if (move.start.bgImage.height * scale < origin.frame.height) {
    scale = origin.frame.height / move.start.bgImage.height;
  }

  // 最大缩放
  if (move.start.bgImage.width * scale > origin.frame.width * props.maxRatio) {
    return;
  }

  origin.bgImage.left =
    move.start.bgImage.left +
    ax -
    (ocx - move.start.bgImage.left) * (scale - 1);

  origin.bgImage.top =
    move.start.bgImage.top + ay - (ocy - move.start.bgImage.top) * (scale - 1);

  origin.bgImage.width = move.start.bgImage.width * scale;
  origin.bgImage.height = move.start.bgImage.height * scale;

  if (origin.bgImage.left > origin.frame.left) {
    origin.bgImage.left = origin.frame.left;
  }
  if (origin.bgImage.top > origin.frame.top) {
    origin.bgImage.top = origin.frame.top;
  }
  if (
    origin.bgImage.left + origin.bgImage.width <
    origin.frame.left + origin.frame.width
  ) {
    origin.bgImage.left =
      origin.frame.left + origin.frame.width - origin.bgImage.width;
  }
  if (
    origin.bgImage.top + origin.bgImage.height <
    origin.frame.top + origin.frame.height
  ) {
    origin.bgImage.top =
      origin.frame.top + origin.frame.height - origin.bgImage.height;
  }
};

// 手指触摸动作结束
const touchEnd = () => {
  touch.touchStart = [];
  resizeImage(); //调整图片的大小
};

// 手指触摸动作被打断，如来电提醒，弹窗
const touchCancel = () => {
  touch.touchStart = [];
};

// 调整图片的大小
const resizeImage = () => {
  var rate = origin.frame.width / origin.frame.height; //比列
  var width = origin.body.width * props.scaleRatio; //裁剪框图片高度 * 缩小0.7倍
  var height = origin.body.height * props.scaleRatio; //裁剪框图片宽度 * 缩小0.7倍
  // 图片的位置：
  // 缩放后的宽度/高度 > 组件裁剪的比例，就要对宽度重写
  if (width / height > rate) {
    width = height * rate;
  } else {
    height = width / rate;
  }
  var left = (origin.body.width - width) / 2;
  var top = (origin.body.height - height) / 2;
  var mul = width / origin.frame.width;
  var ox = origin.frame.left - origin.bgImage.left;
  var oy = origin.frame.top - origin.bgImage.top;

  origin.frame = {
    left: left,
    top: top,
    width: width,
    height: height,
  };

  width = origin.bgImage.width * mul;
  height = origin.bgImage.height * mul;
  left = origin.frame.left - ox * mul;
  top = origin.frame.top - oy * mul;
  origin.bgImage = {
    left: left,
    top: top,
    width: width,
    height: height,
  };
  if (mul != 1) {
    origin.transit = true;
    setTimeout(() => {
      origin.transit = false;
    }, 300);
  }
};

/**
 * 绘制手指触摸结束
 */
</script>

<style>
page {
  overflow: hidden;
  overscroll-behavior: none;
}
</style>
<style lang="scss" scoped>
@import "./t-cropper";
</style>
