Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Tuesday, August 5, 2014

AngularJS directive to wrap Chart.js charting library

Just forked a directive used to wrap Chart.js charting library.
I've made a single change to original code published by earlonrails, which already worked fine.
My directive sensitive to both changing the whole chart object or just data  attribute.
Here is the link for forked version. 

Saturday, May 17, 2014

Linear gauge with gradient fill

In my searches for linear gauge control I didn't find any viable solution.
So I've created one based on D3 stacked bar graph.
See JSFiddle for implementation details

The final result will be something like this:


The Html will be pretty simple, only the container where we will put all the drawing

<div id="linearGaugeContainer"></div>

 I'm using SVG gradients definition in this sample

<!--define svg gradients to be used in java script. make sure the svg tag takes no room on your page=> width and height = 0px-->
<svg style="height: 0px; width: 0px;" xmlns="http://www.w3.org/2000/svg">
    <defs>
        <lineargradient id="NORMAL_COLOR" spreadmethod="pad" x1="0%" x2="0%" y1="0%" y2="100%">
            <stop offset="0%" stop-color="#C1DC99" stop-opacity="1">
            <stop offset="100%" stop-color="#669900" stop-opacity="1">
        </stop></stop></lineargradient>
        <lineargradient id="WARNING_COLOR" spreadmethod="pad" x1="0%" x2="0%" y1="0%" y2="100%">
            <stop offset="0%" stop-color="#84C6F6" stop-opacity="1">
            <stop offset="100%" stop-color="#6FA7CF" stop-opacity="1">
        </stop></stop></lineargradient>
        <lineargradient id="MINOR_COLOR" spreadmethod="pad" x1="0%" x2="0%" y1="0%" y2="100%">
            <stop offset="0%" stop-color="#FFE537" stop-opacity="1">
            <stop offset="100%" stop-color="#F9C328" stop-opacity="1">
        </stop></stop></lineargradient>
        <lineargradient id="MAJOR_COLOR" spreadmethod="pad" x1="0%" x2="0%" y1="0%" y2="100%">
            <stop offset="0%" stop-color="#FF9900" stop-opacity="1">
            <stop offset="100%" stop-color="#FF6700" stop-opacity="1">
        </stop></stop></lineargradient>
        <lineargradient id="CRITICAL_COLOR" spreadmethod="pad" x1="0%" x2="0%" y1="0%" y2="100%">
            <stop offset="0%" stop-color="#E70030" stop-opacity="1">
            <stop offset="100%" stop-color="#B30020" stop-opacity="1">
        </stop></stop></lineargradient>
    </defs>
</svg>

The javascript code is a bit long, just follow the comments within the code:

//Linear gauge
//The way to implement it would be: 
// - To take a stacked bar graph as a basis
// - Ignore all the graph related attributes 
//   (like: axis, ticks and so on)
// - Define a single set of data 
// - Swap the x and y axis values
var margins = {
    top: 12,
    left: 48,
    right: 24,
    bottom: 24
},
width = 700 - margins.left - margins.right
    height = 15,
    dataset = [{
        data: [{
            barId: '1', // we assign some random value, the most important to keep it same for all the entries 
            percent: 0.1, // percentage that we want a specific value to occupy as a part of the gauge: values betwee 0-1
            severity: 'NORMAL_COLOR'// color id that we'll used to reference gradient value
        }]
    }, {
        data: [{
            barId: '1',
            percent: 0.4,
            severity: 'WARNING_COLOR'
        }]
    }, {
        data: [{
            barId: '1',
            percent: 0.22,
            severity: 'MINOR_COLOR'
        }]
    }, {
        data: [{
            barId: '1',
            percent: 0.2,
            severity: 'MAJOR_COLOR'
        }]
    }, {
        data: [{
            barId: '1',
            percent: 0.08,
            severity: 'CRITICAL_COLOR'
        }]
    }],
    dataset = dataset.map(function (d) {
        return d.data.map(function (o, i) {
            // Structure it so that your numeric
            // axis (the stacked amount) is y
            return {
                y: o.percent,
                x: o.barId,
                severity:o.severity
            };
        });
    }),
    stack = d3.layout.stack();

stack(dataset);


var dataset = dataset.map(function (group) {
    return group.map(function (d) {
        // Invert the x and y values, and y0 becomes x0
        return {
            x: d.y,
            y: d.x,
            x0: d.y0,
            severity:d.severity
            
        };
    });
}),
    svg = d3.select('#linearGaugeContainer')
        .append('svg')
        .attr('width', width + margins.left + margins.right)
        .attr('height', height + margins.top + margins.bottom)
        .append('g')
        .attr('transform', 'translate(' + margins.left + ',' + margins.top + ')'),
    xMax = d3.max(dataset, function (group) {
        return d3.max(group, function (d) {
            return d.x + d.x0;
        });
    }),
    xScale = d3.scale.linear()
        .domain([0, xMax])
        .range([0, width]),
    yValue = dataset[0].map(function (d) {
        return d.y;
    }),
    yScale = d3.scale.ordinal()
        .domain(yValue)
        .rangeRoundBands([0, height], .1),
    // this color funciton referencing the linearGradient defind in the HTML part by id 
    color = function (index) {
        console.log(dataset[index][0])
        return "url(#" + dataset[index][0].severity + ")";
    },
    groups = svg.selectAll('g')
        .data(dataset)
        .enter()
        .append('g')
        .style('fill', function (d, i) {
        return color(i);
    });
    var rects = groups.selectAll('rect')
        .data(function (d) {
        return d;
    }).enter();
    rects.append('rect')
        .attr('x', function (d) {
        return xScale(d.x0);
    })
        .attr('y', function (d, i) {
        return yScale(d.y);
    })
        .attr('height', function (d) {
        return yScale.rangeBand();
    })
        .attr('width', function (d) {
        return xScale(d.x);
    });
// locate a label with percentage above each section of the gauge    
rects.append("text")
      .text(function(d,i) { return (d.x * 100) + '%' })
      .attr("x", function(d) { return xScale(d.x0); })
      .style("stroke", '#000000')