<template>
<svg width="400" height="400" class="BG" @mousemove="mousemove">
<!-- 这样拼字符串,少些点加号,方便改一些 -->
<path class="Line"
:d="`M${StartPoint[0]} ${StartPoint[1]} S${ControlPoint[0]} ${ControlPoint[1]} ${EndPoint[0]} ${EndPoint[1]}`" />
<!-- 起始点 -->
<circle :cx="StartPoint[0]" :cy="StartPoint[1]" r="5" style="fill:pink; stroke:red; stroke-width:2;" />
<!-- 结束点示意位置 -->
<circle :cx="EndPoint[0]" :cy="EndPoint[1]" r="5" style="fill:pink; stroke:red; stroke-width:2;" />
<!-- 控制点示意位置 -->
<circle :cx="ControlPoint[0]" :cy="ControlPoint[1]" r="5" style="fill:pink; stroke:red; stroke-width:2;" />
</svg>
</template>
<script setup>
import { nextTick, ref } from 'vue';
const StartPoint = ref([200, 200]);
const EndPoint = ref([400, 200])
const ControlPoint = ref([300, 200])
const ConstantAngle = 45;
// 未优化的计算方法
const ControlPointCompute = () => {
// 计算起始坐标点 的 弧度值
const radian = Math.atan2((EndPoint.value[1] - StartPoint.value[1]), (EndPoint.value[0] - StartPoint.value[0]));
// 用 cos 弧度 来计算 偏移的角度量
// CosRadian 弧度值为 -1 ~ 0 ~ 1 的值,可以用来进行判断坐标点左侧还是右侧
const CosRadian = Math.cos(radian);
// 当前两点之间的角度值
const Angle = radian * (180 / Math.PI);
// 控制点与原点的角度值
const ControlAngle = Angle - (CosRadian * ConstantAngle);
// 三角函数求 两点之间的距离(也就是斜边长)
const distance = Math.sqrt(Math.pow(Math.abs(EndPoint.value[0] - StartPoint.value[0]), 2) + Math.pow(Math.abs(EndPoint.value[1] - StartPoint.value[1]), 2));
// 根据弧度值,计算一个根据距离和角度决定的半径长度来计算控制点
const distanceByCosRadian = distance / (2 - Math.abs(CosRadian) * (1 - 0.414));
// 已知夹角,求临边长及对变长,即为二维坐标值
const X = Math.cos(((2 * Math.PI) / 360) * ControlAngle) * distanceByCosRadian;
const Y = Math.sin(((2 * Math.PI) / 360) * ControlAngle) * distanceByCosRadian;
// 加上原点值,就可得出当前控制点的实际坐标值
ControlPoint.value = [X + 200, Y + 200];
}
// 弧度值转角度值的常量
const R2A = 180 / Math.PI;
// 角度值转弧度值的常量
const A2R = (2 * Math.PI) / 360
// 优化后的计算方法(减少计算为优先)
// 优化原则:1、同样的计算不计算两次(减少计算时间);
// 2、不创建只使用一次的变量(减少创建变量时的内存消耗)
// 3、测试完全部功能再优化(计算优化后的代码基本上是没有可读性的,所以在优化时,尽量先测试)
const TestCompute = (X, Y) => {
// X轴坐标点差值
const DX = Y[0] - X[0];
// Y轴坐标点差值
const DY = Y[1] - X[1];
// 鼠标位置与原点的弧度值
const radian = Math.atan2(DY, DX);
// 鼠标点与坐标点的 余弦 值
const CosRadian = Math.cos(radian);
// 计算控制点与原点的距离
const dis = Math.sqrt(Math.pow(Math.abs(DX), 2) + Math.pow(Math.abs(DY), 2)) / (2 - Math.abs(CosRadian) * (1 - 0.414));
// 计算控制点的弧度值
const ControlRadian = A2R * (radian * R2A - (CosRadian * ConstantAngle));
// 计算控制点位置
ControlPoint.value = [Math.cos(ControlRadian) * dis + X[0], Math.sin(ControlRadian) * dis + X[1]];
}
// ControlPointCompute();
TestCompute(StartPoint.value, EndPoint.value);
const mousemove = (e) => {
// 获取当前鼠标相对父级位置
const { offsetX, offsetY } = e;
EndPoint.value[0] = offsetX;
EndPoint.value[1] = offsetY;
// ControlPointCompute();
TestCompute(StartPoint.value, EndPoint.value);
}
</script>
<style lang="less" scoped>
.BG {
background-color: rgba(255, 255, 255, 0.1);
}
.Line {
fill: none;
stroke: red;
stroke-width: 2;
}
</style>
贝赛尔曲线
最新推荐文章于 2022-11-28 14:47:48 发布