我正在使用JavaScript构建病人监护仪模拟器。这涉及在HTML画布上绘制抛物线(半圆)。通常这不是bezierCurveTo()函数的问题,但是这个解决方案在这里不适用,因为我需要逐像素地设置曲线的动画,如此处所示http://www.jet5.com/ecg/。根据我的理解,这将需要曲线中所有点的数组。
我的问题是如何从我想要的曲线所提供的宽度和高度生成这个点阵列。是否有某种特殊的命令或算法可以用来获得这些笛卡尔坐标。有关我需要的更清晰的图片,请参阅下图http://en.ecgpedia.org/wiki/File:Epi_endo_en.png。
一位讲师用以下等式帮助我:y =(x - t1)x(t2 - x)。这是我的代码(我创建了一个点对象,并记住这是一个HTML画布,其中0,0位于左上角):
var y = 0;
var duration = 200;
var t1 = 0;
var t2 = duration;
var x1 = 0;
var x2 = 0;
for (i = 0; i < duration; i++) {
x1 = i;
x2 = duration - i;
var ctx = canvas.getContext("2d");
y = (x1 - t1) * (t2 - x2)
if (i < duration / 2) {
y = -y;
}
data.push(new point(y));
}
虽然这部分起作用我的理解,这个等式不允许我只指定抛物线宽度的高度。
非常感谢任何帮助
答案 0 :(得分:0)
在这种数学情境中,最好的办法是规范化 这意味着,尝试始终回到x介于0和1之间的情况。
所以如果x在[t1; t2]
delta = (x-t1) / (t2 - t1).
现在delta在[0; 1]中移动!魔术
以同样的方式,对于形状函数,使用仅在[0; 1]。
您在代码中提供的示例变为:
function shape(x) { return (x<0.5) ? x*(1-x) : -x*(1-x) }
代码变成了 - 只是为了清楚 -
for ( x = t1; x<t2; x++ ) {
var delta = (x-t1) / (t2 - t1) ;
y = amplitude * shape(delta);
// do something with (x,y)
}
在这里查看一个有效的jsbin:
http://jsbin.com/wodecowibexa/1/edit?js,output
![var cv = document.getElementById('cv');
var ctx = cv.getContext('2d');
ctx.fillStyle = '#C66';
// shift for all the drawings
var plotShift = {x:0, y:200 } ;
// draw between t1 and t2 with an initial y shift.
// expects an easing function i.e. a function \[0;1\] -> \[0;1\]
// yShift should be the last computed value.
// returns the last computed value to allow chaining.
function drawEasingFunction (yShift, t1, t2, amplitude, func) {
var x=0, y=0;
var duration = t2 - t1;
for (x= t1; x < t2; x++) {
// delta is a figure between 0 and 1
var delta = (x - t1) / duration;
//
y = yShift + amplitude*func(delta);
ctx.fillRect(x+plotShift.x,y+plotShift.y,2,2);
}
return y;
}
var easingFunctions = \[
function (x) { return x} , /* line */
function (x) { return x*x} , /* line */
function (x) { return Math.sqrt(x)} , /* line */
function (x) { return Math.sin(Math.PI*x/2)} , /* sin */
function (x) { return x*(1-x)} , /* that's your function */
\];
var lastY = 0;
var currentX = 0;
var length = 50;
// demo of all functions
for (; currentX < cv.width; currentX+=length) {
// take a random function
var fnIndex = Math.floor(Math.random()*easingFunctions.length) ;
var thisEasingFunction = easingFunctions\[fnIndex\];
// take some random amplitude
var amplitude = (60 + Math.random()*10);
// randomly switch the amplitude sign.
if (Math.random() > 0.5) amplitude = -amplitude;
// draw ! (and store last value)
lastY = drawEasingFunction(lastY, currentX, currentX+length, amplitude, thisEasingFunction);
}][2]