Javascript 如何在HTML5画布上绘制曲线弹簧?

Javascript 如何在HTML5画布上绘制曲线弹簧?,javascript,html,html5-canvas,bezier,Javascript,Html,Html5 Canvas,Bezier,我想在HTML5画布上画一个弹簧,并显示弹簧是否处于其静止长度。 我的弹簧附着在某个X-Y坐标的矩形上,定义如下: function Spring(restLenght, width, numRounds){ this.x1 = 0; this.y1 = 0; this.x2 = 0; this.y2 = 0; this.restLenght = restLenght; this.width = width; this.numRounds = numRounds;

我想在HTML5画布上画一个弹簧,并显示弹簧是否处于其静止长度。 我的弹簧附着在某个X-Y坐标的矩形上,定义如下:

function Spring(restLenght, width, numRounds){
  this.x1 = 0;
  this.y1 = 0;
  this.x2 = 0;
  this.y2 = 0;
  this.restLenght = restLenght;
  this.width = width;
  this.numRounds = numRounds;
  this.color = "green";
  this.lineWidth = 6;
}
下图对参数进行了说明:

当弹簧处于其静止长度时,线应相互平行,否则这意味着弹簧被拉伸或压缩。然后,弹簧的状态将立即变得清晰

我现在只能使用bezierCurveTo()方法:

这是我的小提琴:

var cv=document.getElementById('cv'),
ctx=cv.getContext('2d'),
鼠标=捕获(cv),
盒子=新盒子(120,80,0,16),
弹簧=新弹簧(160,20,2,0.03,0.9),
vx=0,
vy=0;
功能弹簧(剩余长度、宽度、numRounds、k、f){
这是0.x1=0;
这是1.y1=0;
这是0.x2=0;
这是0.y2=0;
this.restLenght=restLenght;
这个。宽度=宽度;
this.numRounds=numRounds;
这个。k=k;
这个。f=f;
this.color=“绿色”;
此参数为0.lineWidth=6;
}
Spring.prototype.draw=函数(ctx){
变量sPX、sPY、cP1X、cP1Y、cP2X、cP2Y、ePX、ePY;
ctx.save();
ctx.translate(this.x,this.y);
ctx.旋转(此旋转);
ctx.lineWidth=此.lineWidth;
ctx.strokeStyle=this.color;
ctx.fillStyle=this.color;
ctx.beginPath();
ctx.moveTo(this.x1,this.y1);
//一圈弹簧的长度
var l=此.restength/(此.numRounds+2);
//初始段,从弹簧锚定点到第一轮
sPX=this.x1+l;sPY=this.y2;
ctx.lineTo(sPX,间谍);
//弹簧圈的一半宽度
var hw=0.5*此宽度;
//一个弹簧圆的一半长度
var hl=0.5*l;
对于(变量i=0,n=this.numRounds;i拖动弹簧
我没有使用贝塞尔曲线,因为贝塞尔曲线实际上并不适合弹簧的曲线(但很接近),而是使用简单的路径和trig函数来绘制每个绕组。该函数有一个开始x1、y1和结束x2、y2、绕组(应为整数)、弹簧宽度、偏移量(末端位)、深色和浅色以及笔划宽度(导线的宽度)

该演示画了一个额外的亮点,使弹簧有更多的深度。它可以很容易地删除

该代码来自于一个具有相同函数的更简单版本

功能拉伸弹簧(x1、y1、x2、y2、绕组、宽度、偏移、col1、col2、线宽){
var x=x2-x1;
变量y=y2-y1;
var dist=数学sqrt(x*x+y*y);
var nx=x/dist;
var ny=y/距离;
ctx.strokeStyle=col1
ctx.lineWidth=线宽;
ctx.lineJoin=“圆形”;
ctx.lineCap=“圆形”;
ctx.beginPath();
ctx.moveTo(x1,y1);
x1+=nx*偏移量;
y1+=ny*偏移量;
x2-=nx*偏移量;
y2-=ny*偏移量;
var x=x2-x1;
变量y=y2-y1;
var阶跃=1/(绕组);

对于(var i=0;i要使绘图更容易,请使用
.translate()
.rotate()
移动到对齐的坐标系中

ctx.translate(this.x1, this.y1);
ctx.rotate(Math.atan2(this.y2 - this.y1, this.x2 - this.x1));
然后可以沿局部x轴绘制弹簧,弹簧将显示在正确的位置并旋转

分段间距错误。
hl*i
是弹簧起点距离的一半,而不是分段起点距离的一半

var cv=document.getElementById('cv'),
ctx=cv.getContext('2d'),
鼠标=捕获(cv),
盒子=新盒子(120,80,0,16),
弹簧=新弹簧(160,50,2,0.03,0.9),
vx=0,
vy=0;
功能弹簧(剩余长度、宽度、numRounds、k、f){
这是0.x1=0;
这是1.y1=0;
这是0.x2=0;
这是0.y2=0;
this.restLenght=restLenght;
这个。宽度=宽度;
this.numRounds=numRounds;
这个。k=k;
这个。f=f;
this.color=“绿色”;
此参数为0.lineWidth=6;
}
Spring.prototype.draw=函数(ctx){
变量sPX、sPY、cP1X、cP1Y、cP2X、cP2Y、ePX、ePY;
ctx.save();
ctx.lineWidth=此.lineWidth;
ctx.strokeStyle=this.color;
ctx.fillStyle=this.color;
var vx=this.x2-this.x1;
var vy=this.y2-this.y1;
var vm=Math.sqrt(vx*vx+vy*vy);
ctx.translate(this.x1,this.y1);
ctx.旋转(数学atan2(vy,vx));
ctx.beginPath();
ctx.moveTo(0,0);
//一圈弹簧的长度
var l=vm/(this.numRounds+2);
//初始段,从弹簧锚定点到第一轮
sPX=l;
sPY=0;
ctx.lineTo(sPX,间谍);
//弹簧圈的一半宽度
var hw=0.5*此宽度;
for(var i=0,n=this.numRounds;i