`
georgezeng
  • 浏览: 103455 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

(JQuery)通过改写flot的pie插件实现一个speedo meter chart的flot插件

阅读更多

由于项目中需要使用到speedo meter chart,但是又不能使用flash(因为要支持iphone),而speedo的js插件网上貌似很难找到,找到了一个但是却不是很满意,因为没办法灵活的定义UI(如果有需要链接在这里http://plugins.jquery.com/project/speedometer),因为实现起来不是很复杂,而且刚好的flot插件中也有一个pie的plugin,想了一下通过修改这个plugin来实现的话就可以了,下面给出这个代码的api定义:

 

// 这里的API是flot相关的,具体还需参见flot的API定义

series: {

meter:{ // 定义了一个meter object,所有的参数定义都在这里 show: true,  // 是否显示该chart label: { // 是否显示各个段的百分比及名称 show: false },

radius: 1,  // 圆的半径定义,数值是0-1,是一个比例值,基数是整个chart的宽度的一半,默认是1

innerRadius: 0.5,  // 内圆的半径定义,也就是空白部分的范围,通过它来调整遮罩范围,也是一个比例值,同上,默认是0.5

currentValue: 0, // 当前此chart对应指针指定的数值,如果没有默认是0

pointerLength: 0.75, // 指针长度,是一个比例值,基数是radius的长度,默认是0.75

maxScale: 100, // 当前chart反应的最大值标量,如果没有输入默认显示100%,接受一个浮点型的数

title: 'the speedo chart' // chart的title,默认是speedo chart }

 

}

 

你还可以为chart所对应的div做css定义,这样的话就可以有不同的边框和背景了,可以根据你的网站样式作出不同的调整,而meter的颜色定义则还是由flot的定义给出,这里不做修改

 

下面贴出整个插件的源码:

 

 

(function ($) 
{
		function init(plot) // this is the "body" of the plugin
        {
                var canvas = null;
                var target = null;
                var maxRadius = null;
				var currentRadius = null;
                var centerLeft = null;
                var centerTop = null;
                var total = 0;
                var redraw = true;
                var redrawAttempts = 10;
                var shrink = 0.95;
                var legendWidth = 0;
                var processed = false;
                var raw = false;
                
                // interactive variables        
                var highlights = [];    
        
                // add hook to determine if meter plugin in enabled, and then perform necessary operations
                plot.hooks.processOptions.push(checkPieEnabled);
                plot.hooks.bindEvents.push(bindEvents); 

                // check to see if the meter plugin is enabled
                function checkPieEnabled(plot, options)
                {
                        if (options.series.meter.show)
                        {
                                //disable grid
                                options.grid.show = false;
                                
                                // set labels.show
                                if (options.series.meter.label.show=='auto')
                                        if (options.legend.show)
                                                options.series.meter.label.show = false;
                                        else
                                                options.series.meter.label.show = true;
                                
                                // set radius
                                if (options.series.meter.radius=='auto')
                                        if (options.series.meter.label.show)
                                                options.series.meter.radius = 3/4;
                                        else
                                                options.series.meter.radius = 1;
								

								if(!options.series.meter.innerRadius) 
									options.series.meter.innerRadius = options.series.meter.radius/2;

								if (!options.series.meter.title) 
									options.series.meter.title = "Meter Chart";

								if(!options.series.meter.currentValue)
									options.series.meter.currentValue = 0;
                                                
								if(!options.series.meter.pointerLength)
									options.series.meter.pointerLength = options.series.meter.radius*3/4;

                                // ensure sane tilt
                                if (options.series.meter.tilt>1)
                                        options.series.meter.tilt=1;
                                if (options.series.meter.tilt<0)
                                        options.series.meter.tilt=0;							

								if (!options.series.meter.maxScale)
                                        options.series.meter.maxScale="100%"; // treate as percentage value

								options.series.meter.startAngle = 1;
								
                                // add processData hook to do transformations on the data
                                plot.hooks.processDatapoints.push(processDatapoints);
                                plot.hooks.drawOverlay.push(drawOverlay);       
                                
                                // add draw hook
                                plot.hooks.draw.push(draw);
                        }
                }
        
                // bind hoverable events
                function bindEvents(plot, eventHolder)          
                {               
                        var options = plot.getOptions();
                        
                        if (options.series.meter.show && options.grid.hoverable)
                                eventHolder.unbind('mousemove').mousemove(onMouseMove);
                                
                        if (options.series.meter.show && options.grid.clickable)
                                eventHolder.unbind('click').click(onClick);
                }       
                

                // debugging function that prints out an object
                function alertObject(obj)
                {
                        var msg = '';
                        function traverse(obj, depth)
                        {
                                if (!depth)
                                        depth = 0;
                                for (var i = 0; i < obj.length; ++i)
                                {
                                        for (var j=0; j<depth; j++)
                                                msg += '\t';
                                
                                        if( typeof obj[i] == "object")
                                        {       // its an object
                                                msg += ''+i+':\n';
                                                traverse(obj[i], depth+1);
                                        }
                                        else
                                        {       // its a value
                                                msg += ''+i+': '+obj[i]+'\n';
                                        }
                                }
                        }
                        traverse(obj);
                        alert(msg);
                }
                
                function calcTotal(data)
                {
                        for (var i = 0; i < data.length; ++i)
                        {
                                var item = parseFloat(data[i].data[0][1]);
                                if (item)
                                        total += item;
                        }
                }       
                
                function processDatapoints(plot, series, data, datapoints) 
                {       
                        if (!processed)
                        {
                                processed = true;
                        
                                canvas = plot.getCanvas();								
                                target = $(canvas).parent();								
                                options = plot.getOptions();
                        
                                plot.setData(combine(plot.getData()));
                        }
                }
                
                function setupPie()
                {
                        legendWidth = target.children().filter('.legend').children().width();
                
                        // calculate maximum radius and center point
                        maxRadius =  canvas.width/2;
                        centerTop = (canvas.height)+options.series.meter.offset.top;
                        centerLeft = (canvas.width/2);
                        
                        if (options.series.meter.offset.left=='auto')
                                if (options.legend.position.match('w'))
                                        centerLeft += legendWidth/2;
                                else
                                        centerLeft -= legendWidth/2;
                        else
                                centerLeft += options.series.meter.offset.left;
                                        
                        if (centerLeft<maxRadius)
                                centerLeft = maxRadius;
                        else if (centerLeft>canvas.width-maxRadius)
                                centerLeft = canvas.width-maxRadius;
                }
                
                function fixData(data)
                {
                        for (var i = 0; i < data.length; ++i)
                        {
                                if (typeof(data[i].data)=='number')
                                        data[i].data = [[1,data[i].data]];
                                else if (typeof(data[i].data)=='undefined' || typeof(data[i].data[0])=='undefined')
                                {
                                        if (typeof(data[i].data)!='undefined' && typeof(data[i].data.label)!='undefined')
                                                data[i].label = data[i].data.label; // fix weirdness coming from flot
                                        data[i].data = [[1,0]];
                                        
                                }
                        }
                        return data;
                }
                
                function combine(data)
                {
                        data = fixData(data);
                        calcTotal(data);
                        var combined = 0;
                        var numCombined = 0;
                        var color = options.series.meter.combine.color;
                        
                        var newdata = [];
                        for (var i = 0; i < data.length; ++i)
                        {
                                // make sure its a number
                                data[i].data[0][1] = parseFloat(data[i].data[0][1]);
                                if (!data[i].data[0][1])
                                        data[i].data[0][1] = 0;
                                        
                                if (data[i].data[0][1]/total<=options.series.meter.combine.threshold)
                                {
                                        combined += data[i].data[0][1];
                                        numCombined++;
                                        if (!color)
                                                color = data[i].color;
                                }                               
                                else
                                {
                                        newdata.push({
                                                data: [[1,data[i].data[0][1]]], 
                                                color: data[i].color, 
                                                label: data[i].label,
                                                angle: (data[i].data[0][1]*(Math.PI))/total,
                                                percent: (data[i].data[0][1]/total*100)
                                        });
                                }
                        }
                        if (numCombined>0)
                                newdata.push({
                                        data: [[1,combined]], 
                                        color: color, 
                                        label: options.series.meter.combine.label,
                                        angle: (combined*(Math.PI))/total,
                                        percent: (combined/total*100)
                                });
                        return newdata;
                }               
                
                function draw(plot, newCtx)
                {
                        if (!target) return; // if no series were passed
                        ctx = newCtx;
                
                        setupPie();
                        var slices = plot.getData();
                
                        var attempts = 0;
                        while (redraw && attempts<redrawAttempts)
                        {
                                redraw = false;
                                if (attempts>0)
                                        maxRadius *= shrink;
                                attempts += 1;
                                clear();
                                if (options.series.meter.tilt<=0.8)
                                        drawShadow();
                                drawPie();
                        }
                        if (attempts >= redrawAttempts) {
                                clear();
                                target.prepend('<div class="error">Could not draw meter with labels contained inside canvas</div>');
                        }
                        
                        if ( plot.setSeries && plot.insertLegend )
                        {
                                plot.setSeries(slices);
                                plot.insertLegend();
                        }
                        
                        // we're actually done at this point, just defining internal functions at this point
                        
                        function clear()
                        {
                                ctx.clearRect(0,0,canvas.width,canvas.height);
                                target.children().filter('.pieLabel, .pieLabelBackground').remove();
                        }
                        
                        function drawShadow()
                        {
                                var shadowLeft = 5;
                                var shadowTop = 15;
                                var edge = 10;
                                var alpha = 0.02;
                        
                                // set radius
                                if (options.series.meter.radius>1)
                                        var radius = options.series.meter.radius;
                                else
                                        var radius = maxRadius * options.series.meter.radius;
                                        
                                if (radius>=(canvas.width/2)-shadowLeft || radius*options.series.meter.tilt>=(canvas.height/2)-shadowTop || radius<=edge)
                                        return; // shadow would be outside canvas, so don't draw it
                        
                                ctx.save();
                                ctx.translate(shadowLeft,shadowTop);
                                ctx.globalAlpha = alpha;
                                ctx.fillStyle = '#000';

                                // center and rotate to starting position
                                ctx.translate(centerLeft,centerTop);
                                ctx.scale(1, options.series.meter.tilt);
                                
                                //radius -= edge;
                                for (var i=1; i<=edge; i++)
                                {
                                        ctx.beginPath();
                                        ctx.arc(0,0,radius,0,Math.PI,false);
                                        ctx.fill();
                                        radius -= i;
                                }       
                                
                                ctx.restore();
                        }
                        
                        function drawPie()
                        {
                                startAngle = Math.PI*options.series.meter.startAngle;
                                
                                // set radius
                                if (options.series.meter.radius>1)
                                        var radius = options.series.meter.radius;
                                else
                                        var radius = maxRadius * options.series.meter.radius;
                                
                                // center and rotate to starting position
                                ctx.save();
                                ctx.translate(centerLeft,centerTop);
                                ctx.scale(1, options.series.meter.tilt);
                                //ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera
                                
                                // draw slices
                                ctx.save();
                                var currentAngle = startAngle;
                                for (var i = 0; i < slices.length; ++i)
                                {
                                        slices[i].startAngle = currentAngle;
                                        drawSlice(slices[i].angle, slices[i].color, true);
                                }
                                ctx.restore();
                                
                                // draw slice outlines
                                ctx.save();
                                ctx.lineWidth = options.series.meter.stroke.width;
                                currentAngle = startAngle;
                                for (var i = 0; i < slices.length; ++i)
                                        drawSlice(slices[i].angle, options.series.meter.stroke.color, false);
                                ctx.restore();
                                        
                                // draw donut hole
                                drawDonutHole(ctx);
                                
                                // draw labels
                                if (options.series.meter.label.show)
                                        drawLabels();
								printTitle();
                                
                                // restore to original state
                                ctx.restore();

								// print scale
								printScaleText();

								// draw pointer
								drawPointer();

								// print current scale 
								printCurentScaleValue();
                                
                                function drawSlice(angle, color, fill)
                                {       
                                        if (angle<=0)
                                                return;
                                
                                        if (fill)
                                                ctx.fillStyle = color;
                                        else
                                        {
                                                ctx.strokeStyle = color;
                                                ctx.lineJoin = 'round';
                                        }
                                                
                                        ctx.beginPath();
                                        if (Math.abs(angle - Math.PI) > 0.000000001)
                                                ctx.moveTo(0,0); // Center of the meter
                                        else if ($.browser.msie)
                                                angle -= 0.0001;
                                        //ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera
                                        ctx.arc(0,0,radius,currentAngle,currentAngle+angle,false);
                                        ctx.closePath();
                                        //ctx.rotate(angle); // This doesn't work properly in Opera
                                        currentAngle += angle;
                                        
                                        if (fill)
                                                ctx.fill();
                                        else
                                                ctx.stroke();
                                }
                                
                                function drawLabels()
                                {
                                        var currentAngle = startAngle;
                                        
                                        // set radius
                                        if (options.series.meter.label.radius>1)
                                                var radius = options.series.meter.label.radius;
                                        else
                                                var radius = maxRadius * options.series.meter.label.radius;
                                  
                                        for (var i = 0; i < slices.length; ++i)
                                        {
                                                if (slices[i].percent >= options.series.meter.label.threshold*100)
                                                        drawLabel(slices[i], currentAngle, i);
                                                currentAngle += slices[i].angle;
                                        }
                                        
                                        function drawLabel(slice, startAngle, index)
                                        {
                                                if (slice.data[0][1]==0)
                                                        return;
                                                        
                                                // format label text
                                                var lf = options.legend.labelFormatter, text, plf = options.series.meter.label.formatter;
                                                if (lf)
                                                        text = lf(slice.label, slice);
                                                else
                                                        text = slice.label;
                                                if (plf)
                                                        text = plf(text, slice);
                                                        
                                                var halfAngle = ((startAngle+slice.angle) + startAngle)/2;
                                                var x = centerLeft + Math.round(Math.cos(halfAngle) * radius);
                                                var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.meter.tilt;
                                                
                                                var html = '<span class="pieLabel" id="pieLabel'+index+'" style="position:absolute;top:' + y + 'px;left:' + x + 'px;">' + text + "</span>";
                                                target.append(html);
                                                var label = target.children('#pieLabel'+index);
                                                var labelTop = (y - label.height()/2);
                                                var labelLeft = (x - label.width()/2);
                                                label.css('top', labelTop);
                                                label.css('left', labelLeft);
                                                
                                                // check to make sure that the label is not outside the canvas
                                                if (0-labelTop>0 || 0-labelLeft>0 || canvas.height-(labelTop+label.height())<0 || canvas.width-(labelLeft+label.width())<0)
                                                        redraw = true;
                                                
                                                if (options.series.meter.label.background.opacity != 0) {
                                                        // put in the transparent background separately to avoid blended labels and label boxes
                                                        var c = options.series.meter.label.background.color;
                                                        if (c == null) {
                                                                c = slice.color;
                                                        }
                                                        var pos = 'top:'+labelTop+'px;left:'+labelLeft+'px;';
                                                        $('<div class="pieLabelBackground" style="position:absolute;width:' + label.width() + 'px;height:' + label.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').insertBefore(label).css('opacity', options.series.meter.label.background.opacity);
                                                }
                                        } // end individual label function
                                } // end drawLabels function

								function printTitle() {
									var html = "<span class='MeterChart_Title' style='font-size:12px; position:absolute; top:10px;'>"+options.series.meter.title+"</span>";
									$(html).appendTo(target).css("left", (centerLeft-(options.series.meter.title+"").length*getFontSize(html)/4)+"px");
								} // end printTitle function

								function printScaleText() {
									var radius = options.series.meter.radius*maxRadius;
									var innerRadius = options.series.meter.innerRadius*maxRadius;
									// print min scale
									var minScaleHTML = "<span style='font-weight: bold; position:absolute; top:"+centerTop+"px; left: "+(radius-innerRadius)/2*0.9+"px;'>0</span>";
									target.append(minScaleHTML);
									var maxScaleHTML = "<span style='font-weight: bold; position:absolute; top:"+centerTop+"px; left: "+(radius+innerRadius+(radius-innerRadius)/2)*0.95+"px;'>"+options.series.meter.maxScale+"</span>";
									target.append(maxScaleHTML);
								} // end printScale function

								function drawPointer() {
									var value = options.series.meter.currentValue;
									var pointerLength = options.series.meter.pointerLength * maxRadius;
									var maxScale = parseFloat(options.series.meter.maxScale);
									var angle = Math.PI*value/maxScale;
									var pointerWidth = 6;

									var startX = centerLeft - Math.floor(pointerLength*Math.cos(angle))-1;
									var startY = centerTop - Math.floor(pointerLength*Math.sin(angle))-1;
									
									ctx.beginPath();
									ctx.moveTo(startX,startY);
									ctx.lineTo(centerLeft+pointerWidth/2*Math.sin(angle),centerTop-pointerWidth/2*Math.cos(angle));
									ctx.lineTo(centerLeft-pointerWidth/2*Math.sin(angle),centerTop+pointerWidth/2*Math.cos(angle));
									ctx.fill();
								} // end drawPointer function
								
								function printCurentScaleValue() {
									var html = "<div class='MeterChart_Value' style='font-size: 16px; position:absolute; top:"+(centerTop+10)+"px;'>"+options.series.meter.currentValue+"</div>";
									$(html).appendTo(target).css("left", (centerLeft-(options.series.meter.currentValue+"").length*getFontSize(html)/4)+"px");
								} // end printCurentScaleValue function
								
								function getFontSize(html) {
									var fontSize = $(html).css("fontSize");
									if(fontSize.indexOf("px") > -1) {
										fontSize = parseInt(fontSize);
									} else if(fontSize.indexOf("em") > -1) {
										fontSize = Math.floor(parseFloat(fontSize)*16);
									} else if(fontSize.indexOf("pt") > -1) {
										fontSize = Math.floor(parseFloat(fontSize)*4/3);
									} else {
										fontSize = centerLeft;
									}
									return fontSize;
								}
                        } // end drawPie function
                } // end draw function
                
                // Placed here because it needs to be accessed from multiple locations 
                function drawDonutHole(layer)
                {
                        // draw donut hole
                        if(options.series.meter.innerRadius > 0)
                        {
                                // subtract the center
                                layer.save();
                                innerRadius = options.series.meter.innerRadius > 1 ? options.series.meter.innerRadius : maxRadius * options.series.meter.innerRadius;
                                layer.globalCompositeOperation = 'destination-out'; // this does not work with excanvas, but it will fall back to using the stroke color
                                layer.beginPath();
                                layer.fillStyle = options.series.meter.stroke.color;
                                layer.arc(0,0,innerRadius,0,Math.PI*2,false);
                                layer.fill();
                                layer.closePath();
                                layer.restore();
                                
                                // add inner stroke
                                layer.save();
                                layer.beginPath();
                                layer.strokeStyle = options.series.meter.stroke.color;
                                layer.arc(0,0,innerRadius,0,Math.PI*2,false);
                                layer.stroke();
                                layer.closePath();
                                layer.restore();
                                // TODO: add extra shadow inside hole (with a mask) if the meter is tilted.
                        }
                }
                
                //-- Additional Interactive related functions --
                
                function isPointInPoly(poly, pt)
                {
                        for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
                                ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1]))
                                && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
                                && (c = !c);
                        return c;
                }
                
                function findNearbySlice(mouseX, mouseY)
                {
                        var slices = plot.getData(),
                                options = plot.getOptions(),
                                radius = options.series.meter.radius > 1 ? options.series.meter.radius : maxRadius * options.series.meter.radius;
                        
                        for (var i = 0; i < slices.length; ++i) 
                        {
                                var s = slices[i];      
                                
                                if(s.meter.show)
                                {
                                        ctx.save();
                                        ctx.beginPath();
                                        ctx.moveTo(0,0); // Center of the meter
                                        //ctx.scale(1, options.series.meter.tilt);        // this actually seems to break everything when here.
                                        ctx.arc(0,0,radius,s.startAngle,s.startAngle+s.angle,false);
                                        ctx.closePath();
                                        x = mouseX-centerLeft;
                                        y = mouseY-centerTop;
                                        if(ctx.isPointInPath)
                                        {
                                                if (ctx.isPointInPath(mouseX-centerLeft, mouseY-centerTop))
                                                {
                                                        //alert('found slice!');
                                                        ctx.restore();
                                                        return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
                                                }
                                        }
                                        else
                                        {
                                                // excanvas for IE doesn;t support isPointInPath, this is a workaround. 
                                                p1X = (radius * Math.cos(s.startAngle));
                                                p1Y = (radius * Math.sin(s.startAngle));
                                                p2X = (radius * Math.cos(s.startAngle+(s.angle/4)));
                                                p2Y = (radius * Math.sin(s.startAngle+(s.angle/4)));
                                                p3X = (radius * Math.cos(s.startAngle+(s.angle/2)));
                                                p3Y = (radius * Math.sin(s.startAngle+(s.angle/2)));
                                                p4X = (radius * Math.cos(s.startAngle+(s.angle/1.5)));
                                                p4Y = (radius * Math.sin(s.startAngle+(s.angle/1.5)));
                                                p5X = (radius * Math.cos(s.startAngle+s.angle));
                                                p5Y = (radius * Math.sin(s.startAngle+s.angle));
                                                arrPoly = [[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]];
                                                arrPoint = [x,y];
                                                // TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for meter tilt?
                                                if(isPointInPoly(arrPoly, arrPoint))
                                                {
                                                        ctx.restore();
                                                        return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
                                                }                       
                                        }
                                        ctx.restore();
                                }
                        }
                        
                        return null;
                }

                function onMouseMove(e) 
                {
                        triggerClickHoverEvent('plothover', e);
                }
                
        function onClick(e) 
                {
                        triggerClickHoverEvent('plotclick', e);
        }

                // trigger click or hover event (they send the same parameters so we share their code)
                function triggerClickHoverEvent(eventname, e) 
                {
                        var offset = plot.offset(),
                                canvasX = parseInt(e.pageX - offset.left),
                                canvasY =  parseInt(e.pageY - offset.top),
                                item = findNearbySlice(canvasX, canvasY);
                        
                        if (options.grid.autoHighlight) 
                        {
                                // clear auto-highlights
                                for (var i = 0; i < highlights.length; ++i) 
                                {
                                        var h = highlights[i];
                                        if (h.auto == eventname && !(item && h.series == item.series))
                                                unhighlight(h.series);
                                }
                        }
                        
                        // highlight the slice
                        if (item) 
                            highlight(item.series, eventname);
                                
                        // trigger any hover bind events
                        var pos = { pageX: e.pageX, pageY: e.pageY };
                        target.trigger(eventname, [ pos, item ]);       
                }

                function highlight(s, auto) 
                {
                        if (typeof s == "number")
                                s = series[s];

                        var i = indexOfHighlight(s);
                        if (i == -1) 
                        {
                                highlights.push({ series: s, auto: auto });
                                plot.triggerRedrawOverlay();
                        }
                        else if (!auto)
                                highlights[i].auto = false;
                }

                function unhighlight(s) 
                {
                        if (s == null) 
                        {
                                highlights = [];
                                plot.triggerRedrawOverlay();
                        }
                        
                        if (typeof s == "number")
                                s = series[s];

                        var i = indexOfHighlight(s);
                        if (i != -1) 
                        {
                                highlights.splice(i, 1);
                                plot.triggerRedrawOverlay();
                        }
                }

                function indexOfHighlight(s) 
                {
                        for (var i = 0; i < highlights.length; ++i) 
                        {
                                var h = highlights[i];
                                if (h.series == s)
                                        return i;
                        }
                        return -1;
                }

                function drawOverlay(plot, octx) 
                {
                        //alert(options.series.meter.radius);
                        var options = plot.getOptions();
                        //alert(options.series.meter.radius);
                        
                        var radius = options.series.meter.radius > 1 ? options.series.meter.radius : maxRadius * options.series.meter.radius;

                        octx.save();
                        octx.translate(centerLeft, centerTop);
                        octx.scale(1, options.series.meter.tilt);
                        
                        for (i = 0; i < highlights.length; ++i) 
                                drawHighlight(highlights[i].series);
                        
                        drawDonutHole(octx);

                        octx.restore();

                        function drawHighlight(series) 
                        {
                                if (series.angle < 0) return;
                                
                                //octx.fillStyle = parseColor(options.series.meter.highlight.color).scale(null, null, null, options.series.meter.highlight.opacity).toString();
                                octx.fillStyle = "rgba(255, 255, 255, "+options.series.meter.highlight.opacity+")"; // this is temporary until we have access to parseColor
                                
                                octx.beginPath();
                                if (Math.abs(series.angle - Math.PI) > 0.000000001)
                                        octx.moveTo(0,0); // Center of the meter
                                octx.arc(0,0,radius,series.startAngle,series.startAngle+series.angle,false);
                                octx.closePath();
                                octx.fill();
                        }
                        
                }       
                
        } // end init (plugin body)
        
        // define meter specific options and their default values
        var options = {
                series: {
                        meter: {
                                show: false,
                                radius: 'auto', // actual radius of the visible meter (based on full calculated radius if <=1, or hard pixel value)
                                innerRadius:0, /* for donut */
                                startAngle: 3/2,
                                tilt: 1,
                                offset: {
                                        top: 0,
                                        left: 'auto'
                                },
                                stroke: {
                                        color: '#FFF',
                                        width: 1
                                },
                                label: {
                                        show: 'auto',
                                        formatter: function(label, slice){
                                                return '<div style="font-size:x-small;text-align:center;padding:2px;color:'+slice.color+';">'+label+'<br/>'+Math.round(slice.percent)+'%</div>';
                                        },      // formatter function
                                        radius: 1,      // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)
                                        background: {
                                                color: null,
                                                opacity: 0
                                        },
                                        threshold: 0    // percentage at which to hide the label (i.e. the slice is too narrow)
                                },
                                combine: {
                                        threshold: -1,  // percentage at which to combine little slices into one larger slice
                                        color: null,    // color to give the new slice (auto-generated if null)
                                        label: 'Other'  // label to give the new slice
                                },
                                highlight: {
                                        //color: '#FFF',                // will add this functionality once parseColor is available
                                        opacity: 0.5
                                }
                        }
                }
        };
    
        $.plot.plugins.push({
                init: init,
                options: options,
                name: "meter",
                version: "1.0"
        });
})(jQuery);

 

 

使用的前置条件:需要引入flot的jquery组件,然后使用flot的API

 

给出一个简单的结果:

 


 

  • 大小: 9.7 KB
1
2
分享到:
评论

相关推荐

    jquery 图表插件Flot

    7. **社区活跃**:由于其开源性质,Flot有一个活跃的开发者社区,不断有新的插件和扩展被开发出来,如对触摸设备的支持、时间轴插件等,这些扩展极大地丰富了Flot的功能。 在使用Flot时,开发者通常会遵循以下步骤...

    jquery绘图插件-flot

    **jQuery绘图插件Flot详解** Flot是一款强大的基于JavaScript的绘图库,它完全依赖于jQuery,为Web开发者提供了在网页上绘制各种图表的能力。由Ole Laursen精心设计和开发,Flot以其易用性、灵活性和丰富的可视化...

    jquery.flot.js

    Flot类库基于jQuery,支持绘制实时和可进行交互的图表

    flot_基于jQuery的插件

    总结来说,Flot是一个优秀的jQuery图表插件,它的易用性、强大的功能和丰富的图表类型使其成为开发者的首选之一。结合中文API文档,无论是新手还是经验丰富的开发者,都能够高效地利用Flot创建出美观且实用的数据...

    jQueryflot图表插件

    jQuery Flot是一个强大的JavaScript库,专门用于在网页上创建高质量的图表。它是基于jQuery构建的,因此能够充分利用jQuery的简洁API和广泛支持的优势。Flot图表插件以其灵活性、高效性和丰富的自定义选项而受到...

    JQuery Flot 画图插件 +实例源码 使用非常方便,效果非常漂亮

    - **Flot**:作为jQuery的一个插件,Flot专门用于生成各种类型的图表,如折线图、柱状图、饼图等,支持时间序列数据和实时更新的数据流。 2. **特性** - **高效性能**:Flot利用HTML5的canvas元素进行绘图,提供...

    jQuery图表插件Flot.rar

    在Web开发领域,数据可视化是不可或缺的一部分,而jQuery图表插件Flot则是JavaScript库中一个强大且灵活的工具,它为开发者提供了丰富的图表绘制功能。Flot以其出色的性能和易于使用的API,赢得了众多开发者的青睐。...

    jquery之绘图工具flot,统计图表的强大利器。

    总结来说,jQuery的Flot是一个强大而灵活的绘图工具,它简化了Web应用程序中的图表制作,提供了丰富的交互功能和吸引人的外观。借助其对Ajax动态显示的支持,Flot能够帮助开发者创建出既实用又美观的数据展示界面,...

    jquery flot 实现实时折线图

    `jQuery Flot` 是一个基于 jQuery 的开源图表库,它允许开发者轻松地在网页上创建出各种复杂的图形,包括折线图、柱状图、饼图等。在本实例中,我们将关注如何使用 `jQuery Flot` 实现实时更新的折线图。实时更新的...

    jquery flot 使用笔记

    jQuery Flot 是一个用于在网页上绘制高质量图形的开源库,它基于 jQuery,因此易于集成到任何使用 jQuery 的项目中。这个库提供了丰富的选项和插件,可以创建出各种各样的图表,包括折线图、柱状图、饼图等。在本文...

    jquery.flot.axislabels.js

    jquery.flot.axislabels.js

    jQuery_flot的相关文件.rar

    总结,jQuery Flot是一个强大的JavaScript库,它简化了数据可视化的实现过程。通过理解和掌握Flot的基本概念、数据格式、配置选项、事件处理和插件,开发者可以轻松创建出美观且功能丰富的图表,以直观地展示和分析...

    jquery 图表插件highchart,jschart,flot

    Flot是一个基于jQuery的图表库,特别适合那些需要在Web应用中嵌入图表的开发者。"flot-0.7.zip"包含了Flot的0.7版本。Flot的特点是其轻量级,它使用纯JavaScript进行绘图,依赖于HTML5的canvas元素,这使得它在现代...

    flot一个基于jQuery有吸引力的JavaScript图表

    Flot是一个强大的开源JavaScript库,专为jQuery设计,用于创建高质量、吸引人的数据可视化图表。它以其灵活性、易用性和性能而受到开发者们的广泛赞誉。Flot允许开发人员在网页上以动态、交互式的方式展示各种类型的...

    flot-plugins:jQuery绘图库Flot的插件

    浮点插件jQuery绘图库Flot的插件。系列注释使用此插件,您可以显示flot数据集中的特定点,而不是显示数据系列中的所有点。 要在绘图中显示点,必须包括seriesannotation.js文件,并且必须向每个数据集添加一个额外的...

    jquery饼状图效果

    "jQuery饼状图效果"是一个关于利用JavaScript库jQuery实现饼状图展示的技术主题。饼状图是一种常用于显示整体与部分之间比例关系的图表,适用于展现各组成部分在整体中所占的比例。 jQuery是一个广泛使用的...

    JQuery Flot 统计图

    jQuery Flot 是一个基于 JavaScript 的开源库,专门用于在 Web 页面上绘制高质量的统计图表。它充分利用了 jQuery 框架的易用性和灵活性,使得开发者无需深入学习复杂的图形库就能创建出丰富的交互式图表。Flot 的...

    jquery.flot.time.js

    jquery.flot.time.js

    图表插件flot

    Flot 是一个基于 jQuery 的开源图表插件,它提供了丰富的功能,用于在 Web 页面上创建交互式图表。这个库以其轻量级、灵活性和强大的性能而受到广泛的欢迎,尤其适合那些希望在网页上展示数据可视化结果的开发者。 ...

Global site tag (gtag.js) - Google Analytics