乐趣区

点线面的常识和自定义弧线

一,点线面常识

1. 基本概念

  • 点:0 维对象,没有大小,只有位置 (x,y,z)
  • 线:由无数个点组成,只有长度,没有宽度
  • 面:二维对象,拥有位置,宽高,边界,面积属性,没有厚度

2. 三角函数:这位大神讲得很好,我就不详细说了 https://segmentfault.com/a/11…
注:以后出现跟他一样的知识点,我就直接链接过去 (~~▽~)~

二,将常用的几何方法封装成一个对象

const Util={
    // 已知直角三角形一直角条边的倾斜弧度,求另一条直角边的倾斜弧度
    getRadPositive:(rad)=>{return rad+Math.PI*2;},
    // 两点相减
    getPointBaseOrigin:(p1,p2)=>{
        const dx = p2.x - p1.x;
        const dy = p2.y - p1.y;
        return {x:dx,y:dy};
    },
    // 根据两点获取距离
    getDistance:(p1,p2)=>{const p=Util.getPointBaseOrigin(p1,p2);
        return Math.sqrt(p.x*p.x + p.y*p.y);
    },
    // 根据两点获取一点到另一点的方向
    getRadian:(p1,p2)=>{const p=Util.getPointBaseOrigin(p1,p2);
        return Math.atan2(p.y,p.x);
    },
    // 已知射线起点 point 和方向 rad,求其发射到某段距离 len 时的点位
    getPointByVector:(rad,len,point)=>{
        return {x:Math.cos(rad)*len+point.x,
            y:Math.sin(rad)*len+point.y,
        }
    },
    // 取两点间的中点
    getCenterPoint:(p1,p2)=>{return {x:(p1.x+p2.x)/2,y:(p1.y+p2.y)/2};
    },
    // 根据勾股定理中的锐角和对边长度,获取斜边长度
    getCbyRadA:(rad,a)=>{return a/Math.sin(rad);
    },
    // 根据勾股定理中的锐角和斜边长度,获取临边长度
    getBbyRadC:(rad,c)=>{return Math.cos(rad)*c;
    },
    // 根据勾股定理中的锐角和斜边长度,获取对边长度
    getAbyRadC:(rad,c)=>{return Math.sin(rad)*c;
    },
    // 根据圆弧的起点、端点、弧度,获取圆心位置
    getObyStarEndRad:(startPoint,endPoint,radian)=>{const centerPoint=Util.getCenterPoint(startPoint,endPoint);
        const aLen=Util.getDistance(startPoint,endPoint)/2;
        const aRad=Util.getRadian(startPoint,endPoint);
        const bRad=Util.getRadPositive(aRad);
        const radius=Util.getCbyRadA(radian/2,aLen);
        const bLen=Util.getBbyRadC(radian/2,radius);
        return Util.getPointByVector(bRad,bLen,centerPoint);
    },
    // 根据圆弧的起点、端点、弧度,获取半径
    getRadiusbyStarEndRad:(startPoint,endPoint,radian)=>{const aLen=Util.getDistance(startPoint,endPoint)/2;
        return Util.getCbyRadA(radian/2,aLen);
    },
}
export default Util;

接下来就可以使用 Unit 工具做实例了

三,实例:自定义圆弧模块

canvas 里的 arc 圆弧的形参是:圆点 x,圆点 y,半径,起始弧度,结束弧度,方向(默认 false,即顺时针)

实际上,我们可能需要从一个端点画弧线,而不用在乎圆心在哪里。比如图一中,以 startPoint 为起点,radA 处的点为圆心,顺时针画一段弧线。

这样我们就需要在 arc 基础上,自定义圆弧对象,形参为(起点,终点,弧度,方向)


图一

1. 已知条件:

let startPoint={x:-300,y:100}; // 起始点
let endPoint={x:100,y:-200}; // 端点
let radian=Math.PI/4; // 弧度
let counterclockwise=false; // 是否逆时针

2. 想要用 arc 画图,就需要根据已知条件求 arc 里的形参。
求:圆点,半径,起始弧度,结束弧度

3. 解:
根据起点 startPoint、终点 endPoint,求线段中心点 centerPoint,a 的长度 aLen,a 的倾斜弧度 aRad,a 的垂线倾斜的弧度 bRad(b 的倾斜弧度)

let centerPoint=Util.getCenterPoint(startPoint,endPoint);
let aLen=Util.getDistance(startPoint,endPoint)/2;
let aRad=Util.getRadian(startPoint,endPoint);
let bRad=aRad+Math.PI/2;

根据 a 和 radA,求半径 c(radius)和 b 的长度 bLen

let radius=Util.getRadAtoC(radian/2,aLen);
let bLen=Util.getRadtoB(radian/2,radius);

根据 b 的弧度、b 的长度,求圆点 circleCenter 的位置 (x,y)

let circleCenter=Util.getPointByVector(bRad,bLen,centerPoint);

根据圆点和起点,圆点和终点,求圆弧的起始弧度 startRad,结束弧度 endRad

let startRad=Util.getRadian(circleCenter,startPoint);
let endRad=Util.getRadian(circleCenter,endPoint);

绘制 arc

ctx.beginPath();
ctx.arc(circleCenter.x,circleCenter.y,radius,startRad,endRad);
ctx.stroke();




退出移动版