利用gdi绘制动态正弦曲线

Mr_MAO 21天前 329

// 利用 gdi 绘制动态正弦曲线 @Mr_MAO
import win.ui;
/*DSG{{*/
var winform = win.form(text="gdi 绘制动态正弦曲线";right=600;bottom=264)
/*}}*/

var arr = {};    //存储曲线坐标点数组
var x = 0;       //角度
var m = 10;      //每个点的水平间距
var i = 0.25;    //波长系数
var pt  = ::POINTF();

winform.setInterval( 
    function(){
        // 让角度在 0 到 2*PI/i 之间循环
        var period = (2 * math.pi) / i; 
        x = (x + 1) % period; 
        
        var y = math.sin( x * i) ;

        // 移除数组第一个元素(左侧),实现向左滚动
        if(#arr > winform.clientRect.right / m  + 1){
            table.remove(arr); 
        }
        table.push(arr, y);
            
        //强制刷新
        winform.redraw();
    },60 
)

//v43.1新版onPaint()默认支持双缓冲绘图
winform.onPaint  = function(hdc,rcPaint,fErase,width,height){ 
    //填充背景颜色 
    gdi.selectBrush(
        function(hdc,pen,brush){          
            ::FillRect(hdc,::RECT(0, 0, width, height),brush);
        },hdc,0x800000
    )
    
    //画网格线
    gdi.selectPen(
        function(hdc,pen){  
            ::SetBkMode(hdc, 1/*_TRANSPARENT*/)  //消除虚线的背景色
            //1画垂直线
            for(x=30; width; 30){
                ::MoveToEx(hdc, x, 0, pt); 
                ::LineTo(hdc, x, height);
            }        
            //2画水平线
            for(y=30; height; 30){
                ::MoveToEx(hdc, 0, y, pt); 
                ::LineTo(hdc, width, y);
            } 
        },hdc,0x13CED1/*color*/,1/*width*/,4/*_PS_DASHDOTDOT*/
    ) 
    
    //定Y轴起点位置
    var centerY = height / 2;
    //振幅系数 (可随窗体高度变化)
    var n2 = centerY / 3;  
    
    //画曲线阴影 (可省略)
    var offsetX, offsetY = 3, 0;
    gdi.selectPen(
        function(hdc,pen){ 
            for(k, v in arr){
                var px = (k - 1) * m + offsetX; 
                var py = v * n2 + centerY + offsetY;
                if(k == 1) ::MoveToEx(hdc, px, py, pt); 
                else ::LineTo(hdc, px, py);
            }
        },hdc,0x333333/*color*/,6/*width*/,0/*_PS_SOLID*/
    )
    
    //画正弦波
    gdi.selectPen(
        function(hdc,pen){ 
            for(k, v in arr){
                var px = (k - 1) * m; 
                var py = v * n2 + centerY;
                if(k == 1) ::MoveToEx(hdc, px, py, pt); 
                else ::LineTo(hdc, px, py);
            }
        },hdc,0x0000FF/*color*/,3/*width*/,0/*_PS_SOLID*/
    )                
}

winform.show();
win.loopMessage();
最新回复 (4)
  • nanyi 21天前
    0 2
    效果不错
  • 光庆 21天前
    0 3

  • Mr_MAO 2天前
    0 4

    再给一个用 gdip 绘制正弦曲线的例子:

    // 使用 gdip 绘制动态正弦曲线(带填充背景)
    import win.ui;
    /*DSG{{*/
    var winform = win.form(text="GDI+ 绘制动态正弦曲线 (带填充色)";right=759;bottom=469;clipch=1)
    winform.add(
    plus={cls="plus";left=21;top=20;right=705;bottom=444;z=1}
    )
    /*}}*/
    
    var datas = {};
    var x = 0;      // 角度
    var m = 10;     // 每个点的水平间距
    var i = 0.25;   // 波长系数
    
    var dataGenerator = function(arr){
        var period = (2 * math.pi) / i; 
        x = (x + 1) % period; 
    
        var y = math.sin( x * i) ;
    
        // 移除数组第一个元素(左侧),实现向左滚动
        if(#arr > winform.plus.clientWidth / m + 2){
            table.remove(arr, 1); 
        }
        table.push(arr, y); 
    }
    
    winform.setInterval( 
        function(){
            //每 50ms 随机生成一组数据
            dataGenerator(datas);
            //重绘界面,形成动画
            winform.plus.redraw();
        }, 50 
    )
    
    winform.plus.onDrawBackground = function(graphics,rc,backgroundColor,color){
        
        // 1. 绘制背景
        graphics.clear(0xFF000080); 
        
        var width, height  = rc.width, rc.height;
        
        // 2. 绘制网格线
        var gridPen = gdip.pen(0xFF13CED1, 1);
        gridPen.dashStyle = 4;
    
        for(gx = 0; width; 30){
            graphics.drawLine(gridPen, gx, 0, gx, height);
        }       
        for(gy = 0; height; 30){
            graphics.drawLine(gridPen, 0, gy, width, gy);
        } 
        gridPen.delete(); 
    
        // 3. 绘制正弦波
        if(#datas >= 3){ // 闭合曲线至少需要3个点
            var centerY = height / 2;
            var amplitude = centerY / 3;
    
            var points = {};
            for(k, v in datas){
                var px = (k - 1) * m;
                var py = v * amplitude + centerY;
                table.push(points, px, py);
            }
            
            // 创建填充路径
            var fillPoints = table.clone(points);
            table.push(fillPoints, ( (#datas)-1 ) * m, height); // 移动到右下角
            table.push(fillPoints, 0, height); // 移动到左下角
            
            var wavePen = gdip.pen(0xFFFF0000, 3, 0);
            var waveBrush = gdip.solidBrush(0x8819ECEF);
        
            //绘制填充色(使用 Polygon)
            graphics.fillPolygon(waveBrush, fillPoints);
            
            //绘制波浪曲线
            graphics.drawCurve(wavePen, points); 
    
            waveBrush.delete();
            wavePen.delete();
        } 
    }
    
    winform.adjust = function( cx,cy,wParam ) {
        winform.plus.setPos(0,0,cx,cy);
    };
    
    winform.show();
    win.loopMessage();


  • mfk 1天前
    0 5

返回