带有html5画布的Ecg图

时间:2013-12-05 12:36:09

标签: javascript html5 graph html5-canvas

我需要在画布上绘制一张ECG数据图,用于每次数据迭代时的套接字数据。

enter image description here

我试图查看几个使用画布绘制图形的图形插件,尝试http://www.flotcharts.org/但没有成功。

我尝试使用以下基本的html5画布画线和样本数据绘制图表。

var fps = 60;
var n = 1;

drawWave();
    function drawWave() {
        setTimeout(function() {
                requestAnimationFrame(drawWave2);
                ctx.lineWidth = "2";
                ctx.strokeStyle = 'green';
                // Drawing code goes here
                n += 1;
                if (n >= data.length) {
                    n = 1;
                }
                ctx.beginPath();
                ctx.moveTo(n - 1, data[n - 1] * 2);
                ctx.lineTo(n, data[n] * 2);
                ctx.stroke();
                ctx.clearRect(n + 1, 0, 10, canvas.height);
            }, 1000 / fps);
    }

但它没有给我一个精确的图表视图作为附加图像。我无法理解如何实现像ecg图这样的图形。请帮我摆脱这个问题。

4 个答案:

答案 0 :(得分:8)

心电图的特征是绘制水平朝向空白间隙的信号。当到达右侧的末端时返回到左侧并透过现有的图形。

DEMO

ECG

<强>设置

var ctx = demo.getContext('2d'),
    w = demo.width,
    h = demo.height,

    /// plot x and y, old plot x and y, speed and scan bar width
    speed = 3,
    px = 0, opx = 0, 
    py = h * 0.8, opy = py,
    scanBarWidth = 20;

ctx.strokeStyle = '#00bd00';
ctx.lineWidth = 3;

/// for demo we use mouse as signal input source    
demo.onmousemove = function(e) {
    var r = demo.getBoundingClientRect();
    py = e.clientY - r.top;
}
loop();

主循环:

循环将绘制任何时刻信号幅度的任何值。您可以通过Web插座等注入窦或其他信号或从实际传感器读取。

function loop() {

    /// move forward at defined speed
    px += speed;

    /// clear ahead (scan bar)
    ctx.clearRect(px,0, scanBarWidth, h);

    /// draw line from old plot point to new
    ctx.beginPath();
    ctx.moveTo(opx, opy);
    ctx.lineTo(px, py);
    ctx.stroke();

    /// update old plot point
    opx = px;
    opy = py;

    /// check if edge is reached and reset position
    if (opx > w) {
        px = opx = -speed;
    }

    requestAnimationFrame(loop);
}

注入一个值只需更新py(外部循环)。

答案 1 :(得分:1)

由于您的实时数据是不间断的流式传输,因此您需要一个计划来处理溢出画布的图形。

这是一个平移画布的解决方案,始终只显示最新数据。

演示:http://jsfiddle.net/m1erickson/f5sT4/

以下是说明此解决方案的起始代码:

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    #canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    // capture incoming socket data in an array
    var data=[];

    // TESTING: fill data with some test values
    for(var i=0;i<5000;i++){
        data.push(Math.sin(i/10)*70+100);
    }

    // x is your most recent data-point in data[]
    var x=0;

    // panAtX is how far the plot will go rightward on the canvas
    // until the canvas is panned

    var panAtX=250;

    var continueAnimation=true;
    animate();


    function animate(){

        if(x>data.length-1){return;}

        if(continueAnimation){
            requestAnimationFrame(animate);
        }

        if(x++<panAtX){

            ctx.fillRect(x,data[x],1,1);

        }else{

            ctx.clearRect(0,0,canvas.width,canvas.height);

            // plot data[] from x-PanAtX to x 

            for(var xx=0;xx<panAtX;xx++){
                var y=data[x-panAtX+xx];
                ctx.fillRect(xx,y,1,1)
            }
        }
    }


    $("#stop").click(function(){continueAnimation=false;});

}); // end $(function(){});
</script>

</head>

<body>
    <button id="stop">Stop</button><br>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

答案 2 :(得分:0)

如果你包含了所产生的图像,那将会更有帮助,而不是声明它不会那样做。无论如何,看起来你每帧只画了一行。你需要在里面运行一个带有lineTo的循环,遍历n的所有值。

除了声音合成器之外,还有下面的内容。请注意有一个绘制循环的事实。就我而言,通常需要在仅几百像素宽的画布上绘制40,000或50,000个样本。在我的情况下,它似乎是多余的绘图,但是直观的是,每个像素的单个点会导致图像不准确。它的输出看起来像(每1024像素88200个样本)

enter image description here

function drawFloatArray(samples, canvas)
{
    var i, n = samples.length;
    var dur = (n / 44100 * 1000)>>0;
    canvas.title = 'Duration: ' +  dur / 1000.0 + 's';

    var width=canvas.width,height=canvas.height;
    var ctx = canvas.getContext('2d');
    ctx.strokeStyle = 'yellow';
    ctx.fillStyle = '#303030';
    ctx.fillRect(0,0,width,height);
    ctx.moveTo(0,height/2);
    ctx.beginPath();
    for (i=0; i<n; i++)
    {
        x = (i*width) / n;
        y = (samples[i]*height/2)+height/2;
        ctx.lineTo(x, y);
    }
    ctx.stroke();
    ctx.closePath();
}

答案 3 :(得分:0)

我认为the documentation Web组件既漂亮又易于使用。它使用画布作为绘制的后端。如果要使用它,您要做的就是在每个出现的节拍上呼叫bang()

document.body.innerHTML += '<ecg-line></ecg-line>';
ecgLine((bang) => setInterval(() => bang(), 1000));

this