<!--
 * JavaScript 线性代数：向量
 * https://juejin.cn/post/6844903859689619469
-->
<script setup lang="ts">
import { reactive, onMounted } from 'vue';
import { Vector } from './utils';

interface Point {
  x: number;
  y: number;
  gap?: number;
  [proppName: string]: any;
}

const stageSize = reactive({
  width: 1200,
  height: 800,
  gridGap: 100,
});
const state = reactive({
  canvasDom: null as any,
  pen: null as any,
});

onMounted(() => {
  state.canvasDom = document.getElementById('canvas-grid');
  state.pen = state.canvasDom.getContext('2d');

  drawGrid();

  // const pointO = { x: 600, y: 200, name: 'O' };
  // const pointA = { x: 500, y: 300, name: 'A' };
  // const pointB = { x: 800, y: 300, name: 'B' };
  // drawVector(pointO, pointA);
  // drawVector(pointO, pointB);

  // // 加法
  // const pointC = new Vector(pointO, pointA).add(pointB) as any;
  // pointC.name = 'C';

  // const len = new Vector(pointO, pointB).length;
  // console.log('OB向量长度', len);
  // const len2 = new Vector(pointA, pointB).length;
  // console.log('AB向量的长度', len2);

  // drawVector(pointO, pointC, '#21BA45');

  // // 减
  // const pointD = new Vector(pointO, pointB).subtract(pointA);
  // console.log('pointD', pointD);
  // drawVector(pointO, pointD, '#FFA000');

  // // 求夹角
  // const angle = new Vector(pointO, pointA).dotProduct(pointB);
  // console.log('OA向量到OB向量的夹角', angle);

  const pointP = { x: 400, y: 200, name: 'P' };
  const pointP1 = { x: 700, y: 200, name: 'P1' };
  const pointP2 = { x: 300, y: 400, name: 'P2' };
  drawVector(pointP, pointP1);
  drawVector(pointP, pointP2);

  // 单位化后的向量以(0,0)点为原点
  // 单位化PP1向量
  const pointP1fterUnit = new Vector(pointP, pointP1).unitization();
  // 单位化PP2向量
  const pointP2fterUnit = new Vector(pointP, pointP2).unitization();

  const unitP1 = pointP1fterUnit.point;
  const myUnitP1 = { x: unitP1.x * 100, y: unitP1.y * 100 };
  const _myUnitP1 = { x: myUnitP1.x + pointP.x, y: myUnitP1.y + pointP.y };
  drawVector(pointP, _myUnitP1, 'pink');

  const unitP2 = pointP2fterUnit.point;
  const myUnitP2 = { x: unitP2.x * 100, y: unitP2.y * 100 };
  const _myUnitP2 = { x: myUnitP2.x + pointP.x, y: myUnitP2.y + pointP.y };
  drawVector(pointP, _myUnitP2, 'pink');

  // PQ的单位向量
  // = 单位化PP1向量 + 单位化PP2向量
  const unitPQ = new Vector(pointP, _myUnitP1).add(_myUnitP2);
  drawVector(pointP, unitPQ, 'pink');
  console.log('PQ的单位向量', unitPQ);

  console.log(
    '单位化PP1向量',
    pointP1fterUnit,
    '单位化PP2向量',
    pointP2fterUnit
  );
});

function drawVector(pointX: Point, pointY: Point, color = '#F44336') {
  const pen = state.pen;

  pen.save();
  pen.beginPath();
  pen.moveTo(pointX.x, pointX.y);
  pen.lineTo(pointY.x, pointY.y);
  pen.lineWidth = 4;
  pen.strokeStyle = color;
  pen.stroke();

  pen.fillText(pointX.name, pointX.x, pointX.y);
  pen.fillText(pointY.name, pointY.x, pointY.y);
  pen.restore();
}

// 网格线
function drawGrid() {
  let canvas: any = document.getElementById('canvas-grid');
  let pen = canvas.getContext('2d');

  // 绘制网格
  const step = stageSize.gridGap;
  const h = stageSize.height;
  const w = stageSize.width;
  const w_l = w / step;
  const h_l = h / step;

  // 横着的线
  pen.save();
  for (let i = 0; i <= h_l; i++) {
    pen.beginPath();
    pen.moveTo(0, i * step);
    pen.lineTo(w, i * step);
    pen.stroke();
  }
  // 竖着的线
  for (let i = 0; i <= w_l; i++) {
    pen.beginPath();
    pen.moveTo(i * step, 0);
    pen.lineTo(i * step, h);
    pen.stroke();
  }
  pen.restore();
}
</script>
<template>
  <div class="center">
    <div class="canvas-box">
      <canvas
        id="canvas-grid"
        :width="stageSize.width"
        :height="stageSize.height"
        style="position: absolute"
      ></canvas>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.canvas-box {
  box-sizing: border-box;
  width: 1200px;
  height: 800px;
  border: 1px solid #000;
  position: relative;
}
</style>
