SOURCE

console 命令行工具 X clear

                    
>
console
// 渲染进度
let index = 0

// canvas尺寸
const size = {width:800,height:80}

// 心电图中点
const middle = size.height / 2

// canvas DOM对象
let canvas = null

// canvas 2d上下文对象
let ctx= null

// 增益
let gain = 2

// 示例数据
const example = [40,40,40,40,55,35,65]
const ecg = []
for(let i=0;i<300000;i++){
    ecg.push(...example)
}

// 动画帧索引
let frame = null

function loaded(){
    // 创建canvas DOM对象
    canvas = document.createElement('canvas')

    // 设置背景色
    canvas.style.backgroundColor = "#000"
    
    ctx = canvas.getContext('2d')

    // 设置canvas 尺寸
    canvas.width = size.width
    canvas.height = size.height

    // 清空画布
    ctx.clearRect(size.width,size.height,0,0)

    // 心电图线宽
    ctx.lineWidth = 3

    // 线的颜色
    ctx.strokeStyle = 'yellow'
    
    // 等待DOM加载完成
    return new Promise(resolve=>{
        document.addEventListener("DOMContentLoaded",()=>{
            document.body.appendChild(canvas)
            resolve(canvas)
        })
    })
    
}

// 转换点的坐标
function point(x,y){
    x = (x+1)*5
    x%=size.width
    y*=gain
    y-=(middle*(gain-1))
    return [x,y]
}

function draw(){
    if(index>=ecg.length) return
    ctx.beginPath()

    if(index===0){
        ctx.moveTo(0,middle)
    }else{
        ctx.moveTo(...point(index-1,ecg[index-1]))
    }
    const [x,y] = point(index,ecg[index])
    ctx.lineTo(x,y)
    ctx.stroke()
    ctx.closePath()
    
    index++
    
}

// 循环渲染
function loop(){
    if(drawVersion2()){
        requestAnimationFrame(loop)
    }
}

// 绘制点
function drawVersion2(){

    // 超出心电图数据长度时停止渲染
    if(index>=ecg.length) return false

    // 开始绘制
    ctx.beginPath()

    // 区分绘制原坐标
    const move = index===0?[0,middle]:point(index-1,ecg[index-1])
    ctx.moveTo(...move)

    // 清空旧数据
    // ctx.clearRect(move[0],0,size.width*0.05,size.height)
    ctx.clearRect(move[0],0,50
    ,size.height)
    
    // 绘制多个点,避免绘制速度跟不上收到数据的速度
    for(let i=0;i<4;i++){
        const [x,y] = point(index,ecg[index])
        const restart = x<move[0]
        if(restart){
            index++
            break;
        }
        ctx.lineTo(x,y)
        index++
        if(index>=ecg.length) break;
    }
    ctx.stroke()
    ctx.closePath()
    return true
    
}

loaded().then(()=>{
    const CheckedElement = document.querySelector(`input[type="radio"][value="${gain}"]`)
    CheckedElement.setAttribute('checked',true)
    document.querySelectorAll('input[type="radio"]').forEach(ele=>{
        // 监听增益改变
        ele.addEventListener('change',()=>{
            gain = parseFloat(ele.value)
        })
    })
    loop()
})
<!-- <canvas id="canvas"  >

</canvas> -->

<span>增益</span>
<div>
<input id="one" type="radio" name="gain" value="0.5">
<label for="one">0.5</label>
</div>

<div>
<input id="two" type="radio" name="gain" value="1">
<label for="two">1</label>
</div>

<div>
<input id="three" type="radio" name="gain" value="2">
<label for="three">2</label>
</div>