• 贝赛尔曲线


    在这里插入图片描述

    <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>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
  • 相关阅读:
    王兰去(黑客)自学
    【语言模型生成分子更好】Language models can learn complex molecular distributions
    配置tensorflow时出现的一些问题
    荣耀的野望:智慧世界的“高端平民”
    【Python微信机器人】第一篇:在windows11上编译python
    【Visual Leak Detector】在 VS 高版本中使用 VLD
    UE4 C++设计模式:观察者模式(Observer Pattern)
    【Gradle-9】Gradle插件发布指南
    学习ros1很好的免费教材:wiki.ros.org/cn
    【JAVA】:万字长篇带你了解JAVA并发编程-并发设计模式【五】
  • 原文地址:https://blog.csdn.net/qq_38946996/article/details/127987872