精华内容
下载资源
问答
  • highcharts个性化仪表盘

    2018-04-13 14:45:00
    一、背景:之前使用过echarts图表,最新公司根据客户需求准备开发个仪表盘美工出图如下。  由于公司产品集成highcharts,发现highcharts仪表盘不满足需求,顾个性化开发。 二、过程: echarts:百度开发,...

    一、背景:之前使用过echarts图表,最新公司根据客户需求准备开发个仪表盘美工出图如下。

     

      由于公司产品集成highcharts,发现highcharts仪表盘不满足需求,顾个性化开发。

    二、过程:

    echarts:百度开发,Api目前支持不好,主要采用canvas画图。

    highcharts: 国外产品,Api全面,还有各路大神的个性化图表,主要采用svg画图。 

    也有人说:echarts相当于中国的WPS,而highchart相当于微软office

    建议,如果使用百度地图展示图表,那么使用echarts(ps:支持国产)

    如果以上两款不满足需求,那么可以上手 d3js,图表更多更强大。

      官网地址:  https://github.com/d3/d3/wiki/Gallery

      api地址(中文的):https://github.com/d3/d3/wiki/API--%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C

    三、结果:

    上图:(虽然差别还是有,基本满足需求)

    上代码:https://code.hcharts.cn/demos/hhhhiD 打开地址,直接复制粘贴,运行看结果。

    js:

    // 公共配置
    Highcharts.setOptions({
        chart: {
            type: 'solidgauge'
        },
        title: {
            text: '',
        },
        pane: {
            center: ['50%', '60%'],
            size: '100%',
            startAngle: -140,
            endAngle: 140,
            background: {
                backgroundColor: (Highcharts.theme && Highcharts.theme.background2) || '#fff',
                innerRadius: '60%',
                outerRadius: '100%',
                shape: 'arc'
            }
        },
        tooltip: {
            enabled: false
        },
        yAxis: {
            plotBands: {
                //borderColor:'#000000',
               // borderWidth:0,
                from: 0,
                to: 250,
                color: '#FFCCFF' // green
            },
            stops: [
                [0.1, '#55BF3B'], // green
                [0.5, '#DDDF0D'], // yellow
                [0.7, '#DF5353'] // red
            ],
            lineWidth: 0,
            minorTickInterval: null,
            tickPixelInterval: 100,//像素间隔
            tickWidth: 2,
            tickAmount: 10,//刻度总数
            tickPosition: 'inside',// 刻度线位置 内外
            tickLength: 15,
            //tickmarkPlacement:'between',
            tickColor: '#ffffff',
            // visible:false,//坐标轴是否显示
            title: {
                y: -50
            },
            labels: {
                enabled:false,
                y: 16
            }
        },
        plotOptions: {
            solidgauge: {
                dataLabels: {
                    y: -20,
                    borderWidth: 0,
                    useHTML: true
                }
            }
        }
    });
    // 速度仪表
    var chart1 = Highcharts.chart('container-qtd', {
        yAxis: {
            min: 0,
            max: 200,
            title: {
                text: 'QTD'
            }
        },
        credits: {
            enabled: false
        },
        series: [{
            data: [{
                y:150,
                innerRadius: 80,
                // radius: 98,
                name:'dd',
            }],
            dataLabels: {
                style: {
                    fontWeight: 'bold',
                    fontSize: '20px',
                    color: 'black'
                },
                format: '<div style="text-align:center"><span style="font-size:25px;color:' +
                ((Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black') + '">{y}%</span><br/>' +
                '<span style="font-size:12px;color:silver">2462M</span></div>'
            }
        }]
    });
    // 转速仪表
    var chart2 = Highcharts.chart('container-mtd', {
        yAxis: {
            min: 0,
            max: 150,
            title: {
                text: 'MTD'
            }
        },
        credits: {//取消官网链接highcharts.com
            enabled: false,
            //添加自己的链接地址
            // text: 'www.baidu.com',
            //  href: 'https://www.baidu.com'
        },
        series: [{
            name: 'RPM',
            data: [{
                y:58,
                innerRadius: 80,
                // radius: 98,
                name:'dd',
            }],
            dataLabels: {
                style: {
                    fontWeight: 'bold',
                    fontSize: '20px',
                    color: 'black'
                },
                format: '<div style="text-align:center"><span style="font-size:25px;color:' +
                ((Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black') + '">{y}%</span><br/>' +
                '<span style="font-size:12px;color:silver">58M</span></div>'
            }
        }]
    });

    html:

    <div style="width: 600px; height: 300px; margin: 0 auto">
        <div id="container-qtd" style="width: 300px; height: 200px; float: left">
        </div>
        <div id="container-mtd" style="width: 300px; height: 200px; float: left">
        </div>
    </div>

     

     

    后记:

      当图表值太大,有时间图表显示不全,显示一半,官方解释:https://api.hcharts.cn/highcharts#yAxis.max

      max值自动向上取整问题,刻度线 tickAmount导致的。

       tickAmount不设置就不会影响最大值问题。即max设置多少显示多少,

       tickAmount设置为null、 0、2 都不管用。直接删掉就好!不需要设置!!!

     

    转载于:https://www.cnblogs.com/start-fxw/p/8820279.html

    展开全文
  • android:仪表盘(简单易实现)

    热门讨论 2013-08-26 16:27:23
    很多仪表盘的例子比较复杂,我这个仪表盘的例子将一部分复杂成分转移给了美工人员,而在代码上非常简单明了。
  • Qt编写云台仪表盘控件

    千次阅读 2018-09-04 22:47:02
    界面美工,主要取决于美工的美图能力,缺点是对于各种分辨率的适应性稍微差点,需要不同的图片切图贴图,除非默认做好的是大图自适应看不出差别,可能大部分人所在的公司都是小公司,一般美工人员比较少甚至没有,.....

    做过安防视频监控的同学都清楚,在视频监控系统软件上都可以看到一个云台控制区域,可以对球机进行下下左右等八个方位的运动控制,还可以进行复位,一般都是美工作图好,然后贴图的形式加入到软件中,好处是程序简单,界面美工,主要取决于美工的美图能力,缺点是对于各种分辨率的适应性稍微差点,需要不同的图片切图贴图,除非默认做好的是大图自适应看不出差别,可能大部分人所在的公司都是小公司,一般美工人员比较少甚至没有,都需要程序员一人负责,甚至一开始就要考虑到各种分辨率的应用场景以及后期可能的换肤换色等。
    之前做过很多自定义控件,大部分都采用了qpainter的形式绘制,有个好处就是自适应任意分辨率,所以思考着这个云台控制仪表盘也采用纯painter绘制的形式,据说纯painter绘制还可以轻松移植到qml中,这又坚定了我用qpainter绘制的决心。所谓心中有坐标系,万物皆painter。
    观察云台仪表盘下来,基本上就这几部分组成,圆形底盘,八个角,中间部分按钮,整个的控件的难点就在于八个角的定位,中间部分很好定位,而且八个角不是绝对的位置,都是相对于界面的宽高按照等比例自适应排列的。八个角的鼠标按下要做出对应的反应,发送出对应型号,网上大部分人都是切图或者放置label或者按钮来贴图实现,绑定事件过滤器过滤鼠标按下然后再发出信号。我这里为了提升逼格,直接采用位置坐标计算法。

    设计师designer完整源码(仅限Qt4):https://pan.baidu.com/s/1t9uKOgi7PW34Kdj7rgTlrA 
    设计师designer可执行文件:https://pan.baidu.com/s/1h3oUjqBun2_YD68gry84wQ 
    自定义控件Qt4封装版本:https://pan.baidu.com/s/1JnpCwIW5sY9VtViqHSCi1g 
    自定义控件Qt5封装版本:https://pan.baidu.com/s/1xMGlK0PN-5yckLJI8koSmQ 
    自定义控件属性设计器:https://pan.baidu.com/s/1iZvQe7L0Dfif_p50qodZ8Q 

    头文件代码:

    #ifndef GAUGECLOUD_H
    #define GAUGECLOUD_H
    
    /**
     * 云台仪表盘控件 作者:feiyangqingyun(QQ:517216493) 2018-9-2
     * 1:可设置背景颜色
     * 2:可设置基准颜色
     * 3:可设置边框颜色
     * 4:可设置文本颜色
     * 5:可识别每个角度+中间 鼠标按下并发出信号
     * 6:可设置八个角的图标和中间图标,随便换
     * 7:内置4种云台风格 黑色+白色+蓝色+紫色
     * 8:支持拓展鼠标进入离开时的切换
     */
    
    #include <QWidget>
    
    #ifdef quc
    #if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
    #include <QtDesigner/QDesignerExportWidget>
    #else
    #include <QtUiPlugin/QDesignerExportWidget>
    #endif
    
    class QDESIGNER_WIDGET_EXPORT GaugeCloud : public QWidget
    #else
    class GaugeCloud : public QWidget
    #endif
    
    {
        Q_OBJECT
        Q_ENUMS(CloudStyle)
    
        Q_PROPERTY(QColor baseColor READ getBaseColor WRITE setBaseColor)
        Q_PROPERTY(QColor bgColor READ getBgColor WRITE setBgColor)
        Q_PROPERTY(QColor arcColor READ getArcColor WRITE setArcColor)
        Q_PROPERTY(QColor borderColor READ getBorderColor WRITE setBorderColor)
        Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
        Q_PROPERTY(QColor pressColor READ getPressColor WRITE setPressColor)
    
        Q_PROPERTY(QString iconText READ getIconText WRITE setIconText)
        Q_PROPERTY(QString centerText READ getCenterText WRITE setCenterText)
        Q_PROPERTY(CloudStyle cloudStyle READ getCloudStyle WRITE setCloudStyle)
    
    public:
        enum CloudStyle {
            CloudStyle_Black = 0,   //黑色风格
            CloudStyle_White = 1,   //白色风格
            CloudStyle_Blue = 2,    //蓝色风格
            CloudStyle_Purple = 3   //紫色风格
        };
    
        explicit GaugeCloud(QWidget *parent = 0);
        ~GaugeCloud();
    
    protected:
        void enterEvent(QEvent *);
        void leaveEvent(QEvent *);
        void mousePressEvent(QMouseEvent *);
        void mouseReleaseEvent(QMouseEvent *);
        void paintEvent(QPaintEvent *);
        void drawCircle(QPainter *painter, int radius, const QBrush &brush);
        void drawArc(QPainter *painter);
        void drawText(QPainter *painter);
    
    private:
        QColor bgColor;                 //背景颜色
        QColor baseColor;               //基准颜色
        QColor arcColor;                //圆弧颜色
        QColor borderColor;             //边框颜色
        QColor textColor;               //文字颜色
        QColor pressColor;              //按下文字颜色
    
        QString iconText;               //八个角图标
        QString centerText;             //中间图标
        CloudStyle cloudStyle;          //云台样式
    
        bool enter;                     //鼠标是否进入
        bool pressed;                   //鼠标是否按下
        QPoint lastPoint;               //鼠标按下处的坐标
        QRectF centerRect;              //中间区域
        QRectF leftRect;                //左侧图标区域
        QRectF topRect;                 //上侧图标区域
        QRectF rightRect;               //右侧图标区域
        QRectF bottomRect;              //下侧图标区域
        QRectF leftTopRect;             //左上角图标区域
        QRectF rightTopRect;            //右上角图标区域
        QRectF leftBottomRect;          //左下角图标区域
        QRectF rightBottomRect;         //右下角图标区域
    
        QFont iconFont;                 //图形字体
    
    public:
        QColor getBgColor()             const;
        QColor getBaseColor()           const;
        QColor getArcColor()            const;
        QColor getBorderColor()         const;
        QColor getTextColor()           const;
        QColor getPressColor()          const;
    
        QString getIconText()           const;
        QString getCenterText()         const;
        CloudStyle getCloudStyle()      const;
    
        QSize sizeHint()                const;
        QSize minimumSizeHint()         const;
    
    public Q_SLOTS:
        //设置背景颜色
        void setBgColor(const QColor &bgColor);
        //设置基准颜色
        void setBaseColor(const QColor &baseColor);
        //设置圆弧颜色
        void setArcColor(const QColor &arcColor);
        //设置边框颜色
        void setBorderColor(const QColor &borderColor);
        //设置文本颜色
        void setTextColor(const QColor &textColor);
        //设置按下文本颜色
        void setPressColor(const QColor &pressColor);
    
        //设置八个角图标
        void setIconText(const QString &iconText);
        //设置中间图标
        void setCenterText(const QString ¢erText);
        //设置云台样式
        void setCloudStyle(const CloudStyle &cloudStyle);
    
    Q_SIGNALS:
        //鼠标按下的区域,共9个,从0-8依次表示底部/左下角/左侧/左上角/顶部/右上角/右侧/右下角/中间
        void mousePressed(int position);
    };
    
    #endif //GAUGECLOUD_H

    核心代码:

    void GaugeCloud::paintEvent(QPaintEvent *)
    {
        int width = this->width();
        int height = this->height();
        int side = qMin(width, height);
    
        //以中心点为基准,分别计算八方位区域和中间区域
        QPointF center = this->rect().center();
        double centerSize = (double)side / ((double)100 / 30);
        double iconSize = (double)side / ((double)100 / 10);
        double offset1 = 3.6;
        double offset2 = 2.65;
    
        //中间区域
        centerRect = QRectF(center.x() - centerSize / 2, center.y() - centerSize / 2, centerSize, centerSize);
        //左侧图标区域
        leftRect = QRectF(center.x() - iconSize * offset1, center.y() - iconSize / 2, iconSize, iconSize);
        //上侧图标区域
        topRect = QRectF(center.x() - iconSize / 2, center.y() - iconSize * offset1, iconSize, iconSize);
        //右侧图标区域
        rightRect = QRectF(center.x() + iconSize * (offset1 - 1), center.y() - iconSize / 2, iconSize, iconSize);
        //下侧图标区域
        bottomRect = QRectF(center.x() - iconSize / 2, center.y() + iconSize * (offset1 - 1), iconSize, iconSize);
        //左上角图标区域
        leftTopRect = QRectF(center.x() - iconSize * offset2, center.y() - iconSize * offset2, iconSize, iconSize);
        //右上角图标区域
        rightTopRect = QRectF(center.x() + iconSize * (offset2 - 1), center.y() - iconSize * offset2, iconSize, iconSize);
        //左下角图标区域
        leftBottomRect = QRectF(center.x() - iconSize * offset2, center.y() + iconSize * (offset2 - 1), iconSize, iconSize);
        //右下角图标区域
        rightBottomRect = QRectF(center.x() + iconSize * (offset2 - 1), center.y() + iconSize * (offset2 - 1), iconSize, iconSize);
    
        //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
        QPainter painter(this);
        painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
        painter.translate(width / 2, height / 2);
        painter.scale(side / 200.0, side / 200.0);
    
        if (cloudStyle == CloudStyle_Black) {
            //绘制外圆背景
            drawCircle(&painter, 99, bgColor);
            //绘制圆弧
            drawArc(&painter);
            //绘制中间圆盘背景
            drawCircle(&painter, 83, baseColor);
            //绘制内圆背景
            drawCircle(&painter, 40, arcColor);
            //绘制内圆边框
            drawCircle(&painter, 33, borderColor);
            //绘制内圆
            drawCircle(&painter, 30, (pressed && centerRect.contains(lastPoint)) ? bgColor : baseColor);
        } else if (cloudStyle == CloudStyle_White) {
            //绘制外圆背景
            drawCircle(&painter, 99, QColor(249, 249, 249));
    
            //设置圆锥渐变
            QConicalGradient gradient(0, 0, 100);
            gradient.setColorAt(0, QColor(34, 163, 169));
            gradient.setColorAt(0.4, QColor(240, 201, 136));
            gradient.setColorAt(0.7, QColor(211, 77, 37));
            gradient.setColorAt(1, QColor(34, 163, 169));
    
            //绘制彩色外圆
            drawCircle(&painter, 90, gradient);
            //绘制中间圆盘背景
            drawCircle(&painter, 83, QColor(245, 245, 245));
            //绘制内圆背景
            drawCircle(&painter, 33, QColor(208, 208, 208));
            //绘制内圆边框
            drawCircle(&painter, 32, QColor(208, 208, 208));
            //绘制内圆
            drawCircle(&painter, 30, (pressed && centerRect.contains(lastPoint)) ? QColor(255, 255, 255) : QColor(245, 245, 245));
        } else if (cloudStyle == CloudStyle_Blue) {
            //设置圆锥渐变
            QConicalGradient gradient(0, 0, 100);
            gradient.setColorAt(0, QColor(34, 163, 169));
            gradient.setColorAt(0.4, QColor(240, 201, 136));
            gradient.setColorAt(0.7, QColor(211, 77, 37));
            gradient.setColorAt(1, QColor(34, 163, 169));
    
            //绘制色彩外圆
            drawCircle(&painter, 99, gradient);
            //绘制中间圆盘背景
            drawCircle(&painter, 91, QColor(31, 66, 98));
            //绘制内圆背景
            drawCircle(&painter, 33, QColor(23, 54, 81));
            //绘制内圆边框
            drawCircle(&painter, 30, QColor(150, 150, 150));
            //绘制内圆
            drawCircle(&painter, 30, (pressed && centerRect.contains(lastPoint)) ? QColor(35, 82, 133) : QColor(34, 73, 115));
        } else if (cloudStyle == CloudStyle_Purple) {
            //设置圆锥渐变
            QConicalGradient gradient(0, 0, 100);
            gradient.setColorAt(0, QColor(87, 87, 155));
            gradient.setColorAt(0.4, QColor(129, 82, 130));
            gradient.setColorAt(0.7, QColor(54, 89, 166));
            gradient.setColorAt(1, QColor(87, 87, 155));
    
            //绘制色彩外圆
            drawCircle(&painter, 99, gradient);
            //绘制中间圆盘背景
            drawCircle(&painter, 91, QColor(55, 55, 92));
            //绘制内圆背景
            drawCircle(&painter, 33, QColor(49, 48, 82));
            //绘制内圆边框
            drawCircle(&painter, 30, QColor(82, 78, 131));
            //绘制内圆
            drawCircle(&painter, 30, (pressed && centerRect.contains(lastPoint)) ? QColor(85, 81, 137) : QColor(62, 59, 103));
        }
    
        //绘制八方位+中间图标
        drawText(&painter);
    
    #if 0
        //重置坐标系,并绘制八方位区域及中间区域,判断是否正确
        painter.resetMatrix();
        painter.resetTransform();
        painter.setPen(Qt::white);
        painter.drawRect(centerRect);
        painter.drawRect(leftRect);
        painter.drawRect(topRect);
        painter.drawRect(rightRect);
        painter.drawRect(bottomRect);
        painter.drawRect(leftTopRect);
        painter.drawRect(rightTopRect);
        painter.drawRect(leftBottomRect);
        painter.drawRect(rightBottomRect);
    #endif
    }
    
    void GaugeCloud::drawCircle(QPainter *painter, int radius, const QBrush &brush)
    {
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(brush);
    
        //绘制圆
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
        painter->restore();
    }
    
    void GaugeCloud::drawArc(QPainter *painter)
    {
        int radius = 91;
        painter->save();
        painter->setBrush(Qt::NoBrush);
    
        QPen pen;
        pen.setWidthF(10);
        pen.setColor(arcColor);
        painter->setPen(pen);
    
        QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
        painter->drawArc(rect, 0 * 16, 360 * 16);
    
        painter->restore();
    }
    
    void GaugeCloud::drawText(QPainter *painter)
    {
        bool ok;
        int radius = 100;
        painter->save();
    
        //判断当前按下坐标是否在中心区域,按下则文本不同颜色
        if (pressed && centerRect.contains(lastPoint)) {
            emit mousePressed(8);
            painter->setPen(pressColor);
        } else {
            painter->setPen(textColor);
        }
    
        QFont font;
        font.setPixelSize(25);
    #if (QT_VERSION >= QT_VERSION_CHECK(4,8,0))
        font.setHintingPreference(QFont::PreferNoHinting);
    #endif
        painter->setFont(font);
    
        //绘制中间图标
        QRectF centerRect(-radius, -radius, radius * 2, radius * 2);
        QString centerText = this->centerText.replace("0x", "");
        QChar centerChar = QChar(centerText.toInt(&ok, 16));
        painter->drawText(centerRect, Qt::AlignCenter, centerChar);
    
        //绘制八方位图标
        radius = 70;
        int offset = 15;
        int steps = 8;
        double angleStep = 360.0 / steps;
    
        font.setPixelSize(20);
        painter->setFont(font);
    
        //从下侧图标开始绘制,顺时针旋转
        QRect iconRect(-offset / 2, radius - offset, offset, offset);
        QString iconText = this->iconText.replace("0x", "");
        QChar iconChar = QChar(iconText.toInt(&ok, 16));
        for (int i = 0; i < steps; i++) {
            //判断鼠标按下的是哪个区域
            if (pressed) {
                bool contains = false;
                if (bottomRect.contains(lastPoint) && i == 0) {
                    contains = true;
                } else if (leftBottomRect.contains(lastPoint) && i == 1) {
                    contains = true;
                } else if (leftRect.contains(lastPoint) && i == 2) {
                    contains = true;
                } else if (leftTopRect.contains(lastPoint) && i == 3) {
                    contains = true;
                } else if (topRect.contains(lastPoint) && i == 4) {
                    contains = true;
                } else if (rightTopRect.contains(lastPoint) && i == 5) {
                    contains = true;
                } else if (rightRect.contains(lastPoint) && i == 6) {
                    contains = true;
                } else if (rightBottomRect.contains(lastPoint) && i == 7) {
                    contains = true;
                }
    
                if (contains) {
                    painter->setPen(pressColor);
                    emit mousePressed(i);
                } else {
                    painter->setPen(textColor);
                }
            } else {
                painter->setPen(textColor);
            }
    
            painter->drawText(iconRect, Qt::AlignCenter, iconChar);
            painter->rotate(angleStep);
        }
    
        painter->restore();
    }

     

    展开全文
  • 前言汽车仪表盘几乎是qt写仪表盘控件中最常见的,一般来说先要求美工做好设计图,然后设计效果图给到程序员,由程序员根据效果来实现,主要靠贴图,这种方法有个好处就是做出来的效果比较逼真,和真实效果图基本上...

    54ba5eb13afd5f7d54d058963f6787fb.png

    前言

    汽车仪表盘几乎是qt写仪表盘控件中最常见的,一般来说先要求美工做好设计图,然后设计效果图给到程序员,由程序员根据效果来实现,主要靠贴图,这种方法有个好处就是做出来的效果比较逼真,和真实效果图基本上保持一致,而且程序员也不会那么累,基本上入门级别的程序员都可以搞定,效率比较高,缺点是如果用户需要更改某个部件的颜色,比如指针的颜色等,需要重新做效果图贴图才能实现,比较麻烦,还有一点就是如果效果图原图不是很大,则遇到特殊分辨率情况下,可能会有失真的情况,被强制拉伸等。

    我一贯都喜欢用painter来绘制,以规避后面几点的缺点,也可以锻炼下自己的审美能力,所谓心中有坐标,万物皆painter。

    实现的功能

    * 1:可设置范围值,支持负数值

    * 2:可设置精确度,最大支持小数点后3位

    * 3:可设置大刻度数量/小刻度数量

    * 4:可设置开始旋转角度/结束旋转角度

    * 5:可设置是否启用动画效果以及动画效果每次移动的步长

    * 6:可设置外圆背景/内圆背景/饼圆三种颜色/刻度尺颜色/文字颜色

    * 7:自适应窗体拉伸,刻度尺和文字自动缩放

    * 8:可自由拓展各种渐变色,各圆的半径

    * 9:三色圆环按照比例设置范围角度 用户可以自由设置三色占用比例

    * 10:圆环样式可选择 三色圆环 当前圆环

    * 11:指示器样式可选择 圆形指示器 指针指示器 圆角指针指示器 三角形指示器

    效果图

    637fd36131def993e4f7040ad23f25dd.gif

    头文件代码

    #ifndef GAUGECAR_H
    #define GAUGECAR_H
    
    /**
     * 汽车仪表盘控件 作者:feiyangqingyun(QQ:517216493) 2016-11-20
     * 1:可设置范围值,支持负数值
     * 2:可设置精确度,最大支持小数点后3位
     * 3:可设置大刻度数量/小刻度数量
     * 4:可设置开始旋转角度/结束旋转角度
     * 5:可设置是否启用动画效果以及动画效果每次移动的步长
     * 6:可设置外圆背景/内圆背景/饼圆三种颜色/刻度尺颜色/文字颜色
     * 7:自适应窗体拉伸,刻度尺和文字自动缩放
     * 8:可自由拓展各种渐变色,各圆的半径
     * 9:三色圆环按照比例设置范围角度 用户可以自由设置三色占用比例
     * 10:圆环样式可选择 三色圆环 当前圆环
     * 11:指示器样式可选择 圆形指示器 指针指示器 圆角指针指示器 三角形指示器
     */
    
    #include <QWidget>
    
    #ifdef quc
    #if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
    #include <QtDesigner/QDesignerExportWidget>
    #else
    #include <QtUiPlugin/QDesignerExportWidget>
    #endif
    
    class QDESIGNER_WIDGET_EXPORT GaugeCar : public QWidget
    #else
    class GaugeCar : public QWidget
    #endif
    
    {
        Q_OBJECT
        Q_ENUMS(PieStyle)
        Q_ENUMS(PointerStyle)
    
        Q_PROPERTY(double minValue READ getMinValue WRITE setMinValue)
        Q_PROPERTY(double maxValue READ getMaxValue WRITE setMaxValue)
        Q_PROPERTY(double value READ getValue WRITE setValue)
        Q_PROPERTY(int precision READ getPrecision WRITE setPrecision)
    
        Q_PROPERTY(int scaleMajor READ getScaleMajor WRITE setScaleMajor)
        Q_PROPERTY(int scaleMinor READ getScaleMinor WRITE setScaleMinor)
        Q_PROPERTY(int startAngle READ getStartAngle WRITE setStartAngle)
        Q_PROPERTY(int endAngle READ getEndAngle WRITE setEndAngle)
    
        Q_PROPERTY(bool animation READ getAnimation WRITE setAnimation)
        Q_PROPERTY(double animationStep READ getAnimationStep WRITE setAnimationStep)
    
        Q_PROPERTY(QColor outerCircleColor READ getOuterCircleColor WRITE setOuterCircleColor)
        Q_PROPERTY(QColor innerCircleColor READ getInnerCircleColor WRITE setInnerCircleColor)
    
        Q_PROPERTY(QColor pieColorStart READ getPieColorStart WRITE setPieColorStart)
        Q_PROPERTY(QColor pieColorMid READ getPieColorMid WRITE setPieColorMid)
        Q_PROPERTY(QColor pieColorEnd READ getPieColorEnd WRITE setPieColorEnd)
    
        Q_PROPERTY(QColor coverCircleColor READ getCoverCircleColor WRITE setCoverCircleColor)
        Q_PROPERTY(QColor scaleColor READ getScaleColor WRITE setScaleColor)
        Q_PROPERTY(QColor pointerColor READ getPointerColor WRITE setPointerColor)
        Q_PROPERTY(QColor centerCircleColor READ getCenterCircleColor WRITE setCenterCircleColor)
        Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor)
    
        Q_PROPERTY(bool showOverlay READ getShowOverlay WRITE setShowOverlay)
        Q_PROPERTY(QColor overlayColor READ getOverlayColor WRITE setOverlayColor)
    
        Q_PROPERTY(PieStyle pieStyle READ getPieStyle WRITE setPieStyle)
        Q_PROPERTY(PointerStyle pointerStyle READ getPointerStyle WRITE setPointerStyle)
    
    public:
        enum PieStyle {
            PieStyle_Three = 0,         	//三色圆环
            PieStyle_Current = 1        	//当前圆环
        };
    
        enum PointerStyle {
            PointerStyle_Circle = 0,        //圆形指示器
            PointerStyle_Indicator = 1,     //指针指示器
            PointerStyle_IndicatorR = 2,    //圆角指针指示器
            PointerStyle_Triangle = 3       //三角形指示器
    	};
    
        explicit GaugeCar(QWidget *parent = 0);
        ~GaugeCar();
    
    protected:
        void paintEvent(QPaintEvent *);
        void drawOuterCircle(QPainter *painter);
        void drawInnerCircle(QPainter *painter);
        void drawColorPie(QPainter *painter);
        void drawCoverCircle(QPainter *painter);
        void drawScale(QPainter *painter);
        void drawScaleNum(QPainter *painter);
        void drawPointerCircle(QPainter *painter);
        void drawPointerIndicator(QPainter *painter);
        void drawPointerIndicatorR(QPainter *painter);
        void drawPointerTriangle(QPainter *painter);
        void drawRoundCircle(QPainter *painter);
        void drawCenterCircle(QPainter *painter);
        void drawValue(QPainter *painter);
        void drawOverlay(QPainter *painter);
    
    private slots:
        void updateValue();
    
    private:    
        double minValue;                //最小值
        double maxValue;                //最大值
        double value;                   //目标值
        int precision;                  //精确度,小数点后几位
    
        int scaleMajor;                 //大刻度数量
        int scaleMinor;                 //小刻度数量
        int startAngle;                 //开始旋转角度
        int endAngle;                   //结束旋转角度
    
        bool animation;                 //是否启用动画显示
        double animationStep;           //动画显示时步长
    
        QColor outerCircleColor;        //外圆背景颜色
        QColor innerCircleColor;        //内圆背景颜色
    
        QColor pieColorStart;           //饼圆开始颜色
        QColor pieColorMid;             //饼圆中间颜色
        QColor pieColorEnd;             //饼圆结束颜色
    
        QColor coverCircleColor;        //覆盖圆背景颜色
        QColor scaleColor;              //刻度尺颜色
        QColor pointerColor;            //指针颜色
        QColor centerCircleColor;       //中心圆颜色
        QColor textColor;               //文字颜色
    
        bool showOverlay;               //显示遮罩层
        QColor overlayColor;            //遮罩层颜色
    
        PieStyle pieStyle;              //饼图样式
        PointerStyle pointerStyle;      //指针样式
    
        bool reverse;                   //是否往回走
        double currentValue;            //当前值
        QTimer *timer;                  //定时器绘制动画
    
    public:    
        double getMinValue()            const;
        double getMaxValue()            const;
        double getValue()               const;
        int getPrecision()              const;
    
        int getScaleMajor()             const;
        int getScaleMinor()             const;
        int getStartAngle()             const;
        int getEndAngle()               const;
    
        bool getAnimation()             const;
        double getAnimationStep()       const;
    
        QColor getOuterCircleColor()    const;
        QColor getInnerCircleColor()    const;
    
        QColor getPieColorStart()       const;
        QColor getPieColorMid()         const;
        QColor getPieColorEnd()         const;
    
        QColor getCoverCircleColor()    const;
        QColor getScaleColor()          const;
        QColor getPointerColor()        const;
        QColor getCenterCircleColor()   const;
        QColor getTextColor()           const;
    
        bool getShowOverlay()           const;
        QColor getOverlayColor()        const;
    
        PieStyle getPieStyle()          const;
        PointerStyle getPointerStyle()  const;
    
        QSize sizeHint()                const;
        QSize minimumSizeHint()         const;
    
    public Q_SLOTS:
        //设置范围值
        void setRange(double minValue, double maxValue);
        void setRange(int minValue, int maxValue);
    
        //设置最大最小值
        void setMinValue(double minValue);
        void setMaxValue(double maxValue);
    
        //设置目标值
        void setValue(double value);
        void setValue(int value);
    
        //设置精确度
        void setPrecision(int precision);
    
        //设置主刻度数量
        void setScaleMajor(int scaleMajor);
        //设置小刻度数量
        void setScaleMinor(int scaleMinor);
        //设置开始旋转角度
        void setStartAngle(int startAngle);
        //设置结束旋转角度
        void setEndAngle(int endAngle);
    
        //设置是否启用动画显示
        void setAnimation(bool animation);
        //设置动画显示的步长
        void setAnimationStep(double animationStep);
    
        //设置外圆背景颜色
        void setOuterCircleColor(const QColor &outerCircleColor);
        //设置内圆背景颜色
        void setInnerCircleColor(const QColor &innerCircleColor);
    
        //设置饼圆三种颜色
        void setPieColorStart(const QColor &pieColorStart);
        void setPieColorMid(const QColor &pieColorMid);
        void setPieColorEnd(const QColor &pieColorEnd);
    
        //设置覆盖圆背景颜色
        void setCoverCircleColor(const QColor &coverCircleColor);
        //设置刻度尺颜色
        void setScaleColor(const QColor &scaleColor);
        //设置指针颜色
        void setPointerColor(const QColor &pointerColor);
        //设置中心圆颜色
        void setCenterCircleColor(const QColor &centerCircleColor);
        //设置文本颜色
        void setTextColor(const QColor &textColor);
    
        //设置是否显示遮罩层
        void setShowOverlay(bool showOverlay);
        //设置遮罩层颜色
        void setOverlayColor(const QColor &overlayColor);
    
        //设置饼图样式
        void setPieStyle(const PieStyle &pieStyle);
        //设置指针样式
        void setPointerStyle(const PointerStyle &pointerStyle);
    
    Q_SIGNALS:
        void valueChanged(int value);
    };
    
    #endif //GAUGECAR_H
    

    核心代码

    void GaugeCar::paintEvent(QPaintEvent *)
    {
        int width = this->width();
        int height = this->height();
        int side = qMin(width, height);
    
        //绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
        QPainter painter(this);
        painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
        painter.translate(width / 2, height / 2);
        painter.scale(side / 200.0, side / 200.0);
    
        //绘制外圆
        drawOuterCircle(&painter);
        //绘制内圆
        drawInnerCircle(&painter);
        //绘制饼圆
        drawColorPie(&painter);
        //绘制覆盖圆 用以遮住饼圆多余部分
        drawCoverCircle(&painter);
        //绘制刻度线
        drawScale(&painter);
        //绘制刻度值
        drawScaleNum(&painter);
    
        //根据指示器形状绘制指示器
        if (pointerStyle == PointerStyle_Circle) {
            drawPointerCircle(&painter);
        } else if (pointerStyle == PointerStyle_Indicator) {
            drawPointerIndicator(&painter);
        } else if (pointerStyle == PointerStyle_IndicatorR) {
            drawPointerIndicatorR(&painter);
        } else if (pointerStyle == PointerStyle_Triangle) {
            drawPointerTriangle(&painter);
        }
    
        //绘制指针中心圆外边框
        drawRoundCircle(&painter);
        //绘制指针中心圆
        drawCenterCircle(&painter);
        //绘制当前值
        drawValue(&painter);
        //绘制遮罩层
        drawOverlay(&painter);
    }
    
    void GaugeCar::drawOuterCircle(QPainter *painter)
    {
        int radius = 99;
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(outerCircleColor);
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
        painter->restore();
    }
    
    void GaugeCar::drawInnerCircle(QPainter *painter)
    {
        int radius = 90;
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(innerCircleColor);
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
        painter->restore();
    }
    
    void GaugeCar::drawColorPie(QPainter *painter)
    {
        int radius = 60;
        painter->save();
        painter->setPen(Qt::NoPen);
    
        QRectF rect(-radius, -radius, radius * 2, radius * 2);
    
        if (pieStyle == PieStyle_Three) {
            //计算总范围角度,根据占比例自动计算三色圆环范围角度
            //可以更改比例
            double angleAll = 360.0 - startAngle - endAngle;
            double angleStart = angleAll * 0.7;
            double angleMid = angleAll * 0.15;
            double angleEnd = angleAll * 0.15;
    
            //增加偏移量使得看起来没有脱节
            int offset = 3;
    
            //绘制开始饼圆
            painter->setBrush(pieColorStart);
            painter->drawPie(rect, (270 - startAngle - angleStart) * 16, angleStart * 16);
    
            //绘制中间饼圆
            painter->setBrush(pieColorMid);
            painter->drawPie(rect, (270 - startAngle - angleStart - angleMid) * 16 + offset, angleMid * 16);
    
            //绘制结束饼圆
            painter->setBrush(pieColorEnd);
            painter->drawPie(rect, (270 - startAngle - angleStart - angleMid - angleEnd) * 16 + offset * 2, angleEnd * 16);
        } else if (pieStyle == PieStyle_Current) {
            //计算总范围角度,当前值范围角度,剩余值范围角度
            double angleAll = 360.0 - startAngle - endAngle;
            double angleCurrent = angleAll * ((currentValue - minValue) / (maxValue - minValue));
            double angleOther = angleAll - angleCurrent;
    
            //绘制当前值饼圆
            painter->setBrush(pieColorStart);
            painter->drawPie(rect, (270 - startAngle - angleCurrent) * 16, angleCurrent * 16);
    
            //绘制剩余值饼圆
            painter->setBrush(pieColorEnd);
            painter->drawPie(rect, (270 - startAngle - angleCurrent - angleOther) * 16, angleOther * 16);
        }
    
        painter->restore();
    }
    
    void GaugeCar::drawCoverCircle(QPainter *painter)
    {
        int radius = 50;
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(coverCircleColor);
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
        painter->restore();
    }
    
    void GaugeCar::drawScale(QPainter *painter)
    {
        int radius = 72;
        painter->save();
    
        painter->rotate(startAngle);
        int steps = (scaleMajor * scaleMinor);
        double angleStep = (360.0 - startAngle - endAngle) / steps;
    
        QPen pen;
        pen.setColor(scaleColor);
        pen.setCapStyle(Qt::RoundCap);
    
        for (int i = 0; i <= steps; i++) {
            if (i % scaleMinor == 0) {
                pen.setWidthF(1.5);
                painter->setPen(pen);
                painter->drawLine(0, radius - 10, 0, radius);
            } else {
                pen.setWidthF(0.5);
                painter->setPen(pen);
                painter->drawLine(0, radius - 5, 0, radius);
            }
    
            painter->rotate(angleStep);
        }
    
        painter->restore();
    }
    
    void GaugeCar::drawScaleNum(QPainter *painter)
    {
        int radius = 82;
        painter->save();
        painter->setPen(scaleColor);
    
        double startRad = (360 - startAngle - 90) * (M_PI / 180);
        double deltaRad = (360 - startAngle - endAngle) * (M_PI / 180) / scaleMajor;
    
        for (int i = 0; i <= scaleMajor; i++) {
            double sina = qSin(startRad - i * deltaRad);
            double cosa = qCos(startRad - i * deltaRad);
            double value = 1.0 * i * ((maxValue - minValue) / scaleMajor) + minValue;
    
            QString strValue = QString("%1").arg((double)value, 0, 'f', precision);
            double textWidth = fontMetrics().width(strValue);
            double textHeight = fontMetrics().height();
            int x = radius * cosa - textWidth / 2;
            int y = -radius * sina + textHeight / 4;
            painter->drawText(x, y, strValue);
        }
    
        painter->restore();
    }
    
    void GaugeCar::drawPointerCircle(QPainter *painter)
    {
        int radius = 6;
        int offset = 30;
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(pointerColor);
    
        painter->rotate(startAngle);
        double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
        painter->rotate(degRotate);
        painter->drawEllipse(-radius, radius + offset, radius * 2, radius * 2);
    
        painter->restore();
    }
    
    void GaugeCar::drawPointerIndicator(QPainter *painter)
    {
        int radius = 75;
        painter->save();
        painter->setOpacity(0.8);
        painter->setPen(Qt::NoPen);
        painter->setBrush(pointerColor);
    
        QPolygon pts;
        pts.setPoints(3, -5, 0, 5, 0, 0, radius);
    
        painter->rotate(startAngle);
        double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
        painter->rotate(degRotate);
        painter->drawConvexPolygon(pts);
    
        painter->restore();
    }
    
    void GaugeCar::drawPointerIndicatorR(QPainter *painter)
    {
        int radius = 75;
        painter->save();
        painter->setOpacity(1.0);
    
        QPen pen;
        pen.setWidth(1);
        pen.setColor(pointerColor);
        painter->setPen(pen);
        painter->setBrush(pointerColor);
    
        QPolygon pts;
        pts.setPoints(3, -5, 0, 5, 0, 0, radius);
    
        painter->rotate(startAngle);
        double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
        painter->rotate(degRotate);
        painter->drawConvexPolygon(pts);
    
        //增加绘制圆角直线,与之前三角形重叠,形成圆角指针
        pen.setCapStyle(Qt::RoundCap);
        pen.setWidthF(4);
        painter->setPen(pen);
        painter->drawLine(0, 0, 0, radius);
    
        painter->restore();
    }
    
    void GaugeCar::drawPointerTriangle(QPainter *painter)
    {
        int radius = 10;
        int offset = 38;
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(pointerColor);
    
        QPolygon pts;
        pts.setPoints(3, -5, 0 + offset, 5, 0 + offset, 0, radius + offset);
    
        painter->rotate(startAngle);
        double degRotate = (360.0 - startAngle - endAngle) / (maxValue - minValue) * (currentValue - minValue);
        painter->rotate(degRotate);
        painter->drawConvexPolygon(pts);
    
        painter->restore();
    }
    
    void GaugeCar::drawRoundCircle(QPainter *painter)
    {
        int radius = 18;
        painter->save();
        painter->setOpacity(0.8);
        painter->setPen(Qt::NoPen);
        painter->setBrush(pointerColor);
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
        painter->restore();
    }
    
    void GaugeCar::drawCenterCircle(QPainter *painter)
    {
        int radius = 15;
        painter->save();
        painter->setPen(Qt::NoPen);
        painter->setBrush(centerCircleColor);
        painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
        painter->restore();
    }
    
    void GaugeCar::drawValue(QPainter *painter)
    {
        int radius = 100;
        painter->save();
        painter->setPen(textColor);
    
        QFont font;
        font.setPixelSize(18);
        painter->setFont(font);
    
        QRectF textRect(-radius, -radius, radius * 2, radius * 2);
        QString strValue = QString("%1").arg((double)currentValue, 0, 'f', precision);
        painter->drawText(textRect, Qt::AlignCenter, strValue);
    
        painter->restore();
    }
    
    void GaugeCar::drawOverlay(QPainter *painter)
    {
        if (!showOverlay) {
            return;
        }
    
        int radius = 90;
        painter->save();
        painter->setPen(Qt::NoPen);
    
        QPainterPath smallCircle;
        QPainterPath bigCircle;
        radius -= 1;
        smallCircle.addEllipse(-radius, -radius, radius * 2, radius * 2);
        radius *= 2;
        bigCircle.addEllipse(-radius, -radius + 140, radius * 2, radius * 2);
    
        //高光的形状为小圆扣掉大圆的部分
        QPainterPath highlight = smallCircle - bigCircle;
    
        QLinearGradient linearGradient(0, -radius / 2, 0, 0);
        overlayColor.setAlpha(100);
        linearGradient.setColorAt(0.0, overlayColor);
        overlayColor.setAlpha(30);
        linearGradient.setColorAt(1.0, overlayColor);
        painter->setBrush(linearGradient);
        painter->rotate(-20);
        painter->drawPath(highlight);
    
        painter->restore();
    }

    控件介绍

    1. 超过130个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,flatui、高亮按钮、滑动选择器、农历等。远超qwt集成的控件数量。
    2. 每个类都可以独立成一个单独的控件,零耦合,每个控件一个头文件和一个实现文件,不依赖其他文件,方便单个控件以源码形式集成到项目中,较少代码量。qwt的控件类环环相扣,高度耦合,想要使用其中一个控件,必须包含所有的代码。
    3. 全部纯Qt编写,QWidget+QPainter绘制,支持Qt4.6到Qt5.12的任何Qt版本,支持mingw、msvc、gcc等编译器,不乱码,可直接集成到Qt Creator中,和自带的控件一样使用,大部分效果只要设置几个属性即可,极为方便。
    4. 每个控件都有一个对应的单独的包含该控件源码的DEMO,方便参考使用。同时还提供一个所有控件使用的集成的DEMO。
    5. 每个控件的源代码都有详细中文注释,都按照统一设计规范编写,方便学习自定义控件的编写。
    6. 每个控件默认配色和demo对应的配色都非常精美。
    7. 超过120个可见控件,6个不可见控件。
    8. 部分控件提供多种样式风格选择,多种指示器样式选择。
    9. 所有控件自适应窗体拉伸变化。
    10. 集成自定义控件属性设计器,支持拖曳设计,所见即所得,支持导入导出xml格式。
    11. 自带activex控件demo,所有控件可以直接运行在ie浏览器中。
    12. 集成fontawesome图形字体+阿里巴巴iconfont收藏的几百个图形字体,享受图形字体带来的乐趣。
    13. 所有控件最后生成一个dll动态库文件,可以直接集成到qtcreator中拖曳设计使用。

    SDK下载

    • SDK下载链接:https://pan.baidu.com/s/1tD9v1YPfE2fgYoK6lqUr1Q 提取码:lyhk
    • 自定义控件欣赏:https://pan.baidu.com/s/14iIecP4QLpYvreM1ZDN-dA 提取码:6rj4
    • 属性设计器欣赏:https://pan.baidu.com/s/165aJuS_ukR6VGugbtGaf4g 提取码:6014
    • 下载链接中包含了各个版本的动态库文件,所有控件的头文件,使用demo。
    • 自定义控件插件开放动态库dll使用(永久免费),无任何后门和限制,请放心使用。
    • widget版本(QQ:517216493)qml版本(QQ:373955953)三峰驼(QQ:278969898)。

    48621f73d4e9fd511982d0125216ddd0.png

    50d2f3994e7c21706e11db3ad55d70ec.png
    展开全文
  • 手把手教你玩转iOS的仪表盘

    千次阅读 2016-09-12 10:04:02
    刚开始的时候,万恶的美工告诉我说,每个仪表盘的度数、报警值是一样的,我就贴了一张图片,指针到了报警值就换图片。后来又告诉我说仪表盘是不一样的(内心orz:内心一万只cnm奔腾)好吧,废话不多说了,直入主题

    手把手教你玩转iOS的仪表盘

    最近公司项目需求,要求我做一个仪表盘,指针能工具报警值变换指针颜色的那种。而且仪表盘的量程,报警值都是不一样的(ps:仪表盘个数有点多,几十个的样子,而且每个都不一样)。刚开始的时候,万恶的美工告诉我说,每个仪表盘的度数、报警值是一样的,我就贴了一张图片,指针到了报警值就换图片。后来又告诉我说仪表盘是不一样的(内心orz:内心一万只cnm奔腾)

    好吧,废话不多说了,直入主题。

    我使用UIView的- (void)drawRect:(CGRect)rect方法画的,首先当然就是使用贝塞尔曲线描出两条路径,路径的颜色通过传参的方式传过来
    “` python
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetShadow(context, CGSizeMake(0, 0), 0);

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path addArcWithCenter:CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2) radius:76 startAngle:ANGLE_TO_RADIANS(150) endAngle:ANGLE_TO_RADIANS(390) clockwise:YES];
    UIColor *color  = self.leftColor;
    [color setStroke];
    path.lineWidth = 20;
    [path stroke];
    
    UIBezierPath *path2 = [UIBezierPath bezierPath];
    [path2 addArcWithCenter:CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2) radius:76 startAngle:ANGLE_TO_RADIANS(150 + ((self.warningValue)/(self->maxValue - self->minValue))*240) endAngle:ANGLE_TO_RADIANS(390) clockwise:YES];
    UIColor *color2 = self.rightColor;
    [color2 setStroke];
    path2.lineWidth = 20;
    [path2 stroke];
    

    这些都是次要的,因为iOS开发的基本都会这个吧,那我还贴代码,我是不是多此一举。。。。。。

    其实最主要的当然就是画仪表盘的刻度了,这里有两个重要的方法
    CGContextTranslateCTM(context, center_.x, center_.y);
    CGContextRotateCTM(context, angle);
    第一个是移动函数,将图形上下文的原点在X轴和Y轴方向移动到某个位置,这里我要不要科普一下X轴和Y轴呢??感觉多次一举吧,因为平时开发中设置视图的frame的时候经常使用到呢,原点就是屏幕的左上角了,原点往右就是X轴正方向,原点往下就是Y轴正方向,原点朝正对我我们的方向就是Z轴的正方向了。是不是很脑残的解释哈。。。
    第二个是旋转函数,将图像上下文绕原点旋转angle度。画仪表的刻度就靠他了。
    CGFloat allAngle = 0.0;
    CGFloat cenx = CGRectGetMidX(self.bounds);
    CGFloat ceny = CGRectGetMidY(self.bounds);
    [self rotateContext:context fromCenter:CGPointMake(cenx, ceny) withAngle:ANGLE_TO_RADIANS(174+90)];
    for(int i = 0; i < (8+1); i++)
    {
    CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextSetLineWidth(context, 2.0);
    CGContextMoveToPoint(context, self.bounds.size.width/2, 0);
    CGContextAddLineToPoint(context, self.bounds.size.width/2, 20);
    CGContextStrokePath(context);
    [self rotateContext:context fromCenter:CGPointMake(cenx, ceny) withAngle:ANGLE_TO_RADIANS((276-84)/8)];
    }
    //旋转了角度,画完刻度需要将坐标旋转回初始状态
    allAngle = ANGLE_TO_RADIANS((276-84)/8)*(8+1);
    [self rotateContext:context fromCenter:CGPointMake(cenx, ceny) withAngle:-ANGLE_TO_RADIANS(150+24+90)];
    [self rotateContext:context fromCenter:CGPointMake(cenx, ceny) withAngle:-allAngle];

    • (void)rotateContext:(CGContextRef)context fromCenter:(CGPoint)center_ withAngle:(CGFloat)angle
      {
      CGContextTranslateCTM(context, center_.x, center_.y);
      CGContextRotateCTM(context, angle);
      CGContextTranslateCTM(context, -center_.x, -center_.y);
      }
      这样刻度就换好了,然后加一个指针就可以了,这里的指针就没有自己画了,直接贴了一张图,然后找准锚点和位置,再加一个定时器CADisplayLink,让定时器每次都转一刻度就哦了。这样就有人会有疑惑了,那么我想转快点咋办呢???如果每次转多点度数的话,那么必然导致转的不准啊。。。。。。这还不好解决吗?前面转的快点,当转的度数快到目标度数时,我又换成每次转一度,不就完美解决了。
      最后一个就是刻度的问题了,用我们的三角函数和半径,将一个数组填进去就好了。
      for (NSInteger i = 0; i < _numArray.count; i++) {
      static CGFloat r = 55;
      CGFloat x = 75 + r*cosf(ANGLE_TO_RADIANS(210-24*i));
      CGFloat y = 75 - r*sinf(ANGLE_TO_RADIANS(210-24*i));
      UILabel *numLabel = [[UILabel alloc]initWithFrame:CGRectMake(x, y, 40, 20)];
      numLabel.font = [UIFont systemFontOfSize:12];
      numLabel.textAlignment = NSTextAlignmentLeft;
      numLabel.text = [NSString stringWithFormat:@”%@”,_numArray[i]];
      [self addSubview:numLabel];
      }

    上传两张效果图
    这里写图片描述
    这里写图片描述

    展开全文
  • 仪表盘在很多汽车和物联网相关的系统中很常用,最直观的其实就是汽车仪表盘,这个以前主要是机械的仪表,现在逐步改成了智能的带屏带操作系统的仪表,这样美观性和拓展性功能性大大增强了,上了操作系统的话,除了...
  • Android 仪表盘动画

    千次阅读 2017-02-12 21:23:39
    思路:没错,我们用自定义View可以做,不过比较...换个思路,我们让美工提供一张背景图和一张橙色指针图(这里要注意了,一定要提供多种分辨率的图片,为适配不同分辨率的手机),给橙色指针一个旋转动画不就可以了吗。
  • Qt编写自定义控件1-汽车仪表盘

    千次阅读 2019-04-19 20:51:44
    汽车仪表盘机会是qt写仪表盘控件中最常见的,一般来说先要求美工最好设计图,然后设计效果图给到程序员,由程序员根据效果来实现,主要靠贴图,这种方法有个好处就是做出来的效果比较逼真,和真实效果图基本上保持...
  • ## 一、前言仪表盘在很多汽车和物联网相关的系统中很常用,最直观的其实就是汽车仪表盘,这个以前主要是机械的仪表,现在逐步改成了智能的带屏带操作系统的仪表,这样美观性和拓展性功能性大大增强了,上了操作系统...
  • 一、前言仪表盘在很多汽车和物联网相关的系统中很常用,最直观的其实就是汽车仪表盘,这个以前主要是机械的仪表,现在逐步改成了智能的带屏带操作系统的仪表,这样美观性和拓展性功能性大大增强了,上了操作系统的话...
  • ## 一、前言仪表盘在很多汽车和物联网相关的系统中很常用,最直观的其实就是汽车仪表盘,这个以前主要是机械的仪表,现在逐步改成了智能的带屏带操作系统的仪表,这样美观性和拓展性功能性大大增强了,上了操作系统...
  • 一、前言仪表盘在很多汽车和物联网相关的系统中很常用,最直观的其实就是汽车仪表盘,这个以前主要是机械的仪表,现在逐步改成了智能的带屏带操作系统的仪表,这样美观性和拓展性功能性大大增强了,上了操作系统的话...
  • 前言汽车仪表盘几乎是qt写仪表盘控件中最常见的,一般来说先要求美工做好设计图,然后设计效果图给到程序员,由程序员根据效果来实现,主要靠贴图,这种方法有个好处就是做出来的效果比较逼真,和真实效果图基本上...
  • 手把手带你画一个 时尚仪表盘 Android 自定义View

    万次阅读 多人点赞 2016-01-06 15:29:16
    拿到美工效果图,咱们程序员就得画得一模一样。 为了不被老板喷,只能多练啊。 听说你觉得前面几篇都so easy,那今天就带你做个相对比较复杂的。 今天的效果图如下(左边是ui图 右边是实现图): 自我感觉总体效果还...
  • 界面美工,主要取决于美工的美图能力,缺点是对于各种分辨率的适应性稍微差点,需要不同的图片切图贴图,除非默认做好的是大图自适应看不出差别,可能大部分人所在的公司都是小公司,一般美工人员比较少甚至...
  • 界面美工,主要取决于美工的美图能力,缺点是对于各种分辨率的适应性稍微差点,需要不同的图片切图贴图,除非默认做好的是大图自适应看不出差别,可能大部分人所在的公司都是小公司,一般美工人员比较少甚至没有,.....
  • 界面美工,主要取决于美工的美图能力,缺点是对于各种分辨率的适应性稍微差点,需要不同的图片切图贴图,除非默认做好的是大图自适应看不出差别,可能大部分人所在的公司都是小公司,一般美工人员比较少甚至没...
  • 界面美工,主要取决于美工的美图能力,缺点是对于各种分辨率的适应性稍微差点,需要不同的图片切图贴图,除非默认做好的是大图自适应看不出差别,可能大部分人所在的公司都是小公司,一般美工人员比较少甚至没...
  • 细节方面的美化可以自行通过美工来完善。为了更好的适应新的UI系统,学习NGUI之余也使用UGUI来制作同样效果的东西。首先,我们创建一个Camera对象,改名为MiniMapCamera,设置Rotation让其视野朝下,面向地面,修改...
  • 界面美工,主要取决于美工的美图能力,缺点是对于各种分辨率的适应性稍微差点,需要不同的图片切图贴图,除非默认做好的是大图自适应看不出差别,可能大部分人所在的公司都是小公司,一般美工人员比较少甚至没...
  • 自动布局,任意切换主题颜色,无须专业美工也可轻松驾驭…迈安数据应用开发平台每一项细节功能的优化,都在重新定义敏捷BI。 迈安数据应用开发平台具有强大交互功能,全面升级数据可视化。颜色预警、高亮联动、图标...
  • 拿到美工效果图。咱们程序猿就得画得一模一样。 为了不被老板喷,仅仅能多练啊。 听说你认为前面几篇都so easy,那今天就带你做个相对照较复杂的。 转载请注明出处:...

空空如也

空空如也

1 2
收藏数 34
精华内容 13
关键字:

仪表盘美工