一,点线面常识
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();