shop.balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

jquery.flot.image.js (7601B)


      1 /* Flot plugin for plotting images.
      2 
      3 Copyright (c) 2007-2013 IOLA and Ole Laursen.
      4 Licensed under the MIT license.
      5 
      6 The data syntax is [ [ image, x1, y1, x2, y2 ], ... ] where (x1, y1) and
      7 (x2, y2) are where you intend the two opposite corners of the image to end up
      8 in the plot. Image must be a fully loaded Javascript image (you can make one
      9 with new Image()). If the image is not complete, it's skipped when plotting.
     10 
     11 There are two helpers included for retrieving images. The easiest work the way
     12 that you put in URLs instead of images in the data, like this:
     13 
     14 	[ "myimage.png", 0, 0, 10, 10 ]
     15 
     16 Then call $.plot.image.loadData( data, options, callback ) where data and
     17 options are the same as you pass in to $.plot. This loads the images, replaces
     18 the URLs in the data with the corresponding images and calls "callback" when
     19 all images are loaded (or failed loading). In the callback, you can then call
     20 $.plot with the data set. See the included example.
     21 
     22 A more low-level helper, $.plot.image.load(urls, callback) is also included.
     23 Given a list of URLs, it calls callback with an object mapping from URL to
     24 Image object when all images are loaded or have failed loading.
     25 
     26 The plugin supports these options:
     27 
     28 	series: {
     29 		images: {
     30 			show: boolean
     31 			anchor: "corner" or "center"
     32 			alpha: [ 0, 1 ]
     33 		}
     34 	}
     35 
     36 They can be specified for a specific series:
     37 
     38 	$.plot( $("#placeholder"), [{
     39 		data: [ ... ],
     40 		images: { ... }
     41 	])
     42 
     43 Note that because the data format is different from usual data points, you
     44 can't use images with anything else in a specific data series.
     45 
     46 Setting "anchor" to "center" causes the pixels in the image to be anchored at
     47 the corner pixel centers inside of at the pixel corners, effectively letting
     48 half a pixel stick out to each side in the plot.
     49 
     50 A possible future direction could be support for tiling for large images (like
     51 Google Maps).
     52 
     53 */
     54 
     55 (function ($) {
     56     var options = {
     57         series: {
     58             images: {
     59                 show: false,
     60                 alpha: 1,
     61                 anchor: "corner" // or "center"
     62             }
     63         }
     64     };
     65 
     66     $.plot.image = {};
     67 
     68     $.plot.image.loadDataImages = function (series, options, callback) {
     69         var urls = [], points = [];
     70 
     71         var defaultShow = options.series.images.show;
     72         
     73         $.each(series, function (i, s) {
     74             if (!(defaultShow || s.images.show))
     75                 return;
     76             
     77             if (s.data)
     78                 s = s.data;
     79 
     80             $.each(s, function (i, p) {
     81                 if (typeof p[0] == "string") {
     82                     urls.push(p[0]);
     83                     points.push(p);
     84                 }
     85             });
     86         });
     87 
     88         $.plot.image.load(urls, function (loadedImages) {
     89             $.each(points, function (i, p) {
     90                 var url = p[0];
     91                 if (loadedImages[url])
     92                     p[0] = loadedImages[url];
     93             });
     94 
     95             callback();
     96         });
     97     }
     98     
     99     $.plot.image.load = function (urls, callback) {
    100         var missing = urls.length, loaded = {};
    101         if (missing == 0)
    102             callback({});
    103 
    104         $.each(urls, function (i, url) {
    105             var handler = function () {
    106                 --missing;
    107                 
    108                 loaded[url] = this;
    109                 
    110                 if (missing == 0)
    111                     callback(loaded);
    112             };
    113 
    114             $('<img />').load(handler).error(handler).attr('src', url);
    115         });
    116     };
    117     
    118     function drawSeries(plot, ctx, series) {
    119         var plotOffset = plot.getPlotOffset();
    120         
    121         if (!series.images || !series.images.show)
    122             return;
    123         
    124         var points = series.datapoints.points,
    125             ps = series.datapoints.pointsize;
    126         
    127         for (var i = 0; i < points.length; i += ps) {
    128             var img = points[i],
    129                 x1 = points[i + 1], y1 = points[i + 2],
    130                 x2 = points[i + 3], y2 = points[i + 4],
    131                 xaxis = series.xaxis, yaxis = series.yaxis,
    132                 tmp;
    133 
    134             // actually we should check img.complete, but it
    135             // appears to be a somewhat unreliable indicator in
    136             // IE6 (false even after load event)
    137             if (!img || img.width <= 0 || img.height <= 0)
    138                 continue;
    139 
    140             if (x1 > x2) {
    141                 tmp = x2;
    142                 x2 = x1;
    143                 x1 = tmp;
    144             }
    145             if (y1 > y2) {
    146                 tmp = y2;
    147                 y2 = y1;
    148                 y1 = tmp;
    149             }
    150             
    151             // if the anchor is at the center of the pixel, expand the 
    152             // image by 1/2 pixel in each direction
    153             if (series.images.anchor == "center") {
    154                 tmp = 0.5 * (x2-x1) / (img.width - 1);
    155                 x1 -= tmp;
    156                 x2 += tmp;
    157                 tmp = 0.5 * (y2-y1) / (img.height - 1);
    158                 y1 -= tmp;
    159                 y2 += tmp;
    160             }
    161             
    162             // clip
    163             if (x1 == x2 || y1 == y2 ||
    164                 x1 >= xaxis.max || x2 <= xaxis.min ||
    165                 y1 >= yaxis.max || y2 <= yaxis.min)
    166                 continue;
    167 
    168             var sx1 = 0, sy1 = 0, sx2 = img.width, sy2 = img.height;
    169             if (x1 < xaxis.min) {
    170                 sx1 += (sx2 - sx1) * (xaxis.min - x1) / (x2 - x1);
    171                 x1 = xaxis.min;
    172             }
    173 
    174             if (x2 > xaxis.max) {
    175                 sx2 += (sx2 - sx1) * (xaxis.max - x2) / (x2 - x1);
    176                 x2 = xaxis.max;
    177             }
    178 
    179             if (y1 < yaxis.min) {
    180                 sy2 += (sy1 - sy2) * (yaxis.min - y1) / (y2 - y1);
    181                 y1 = yaxis.min;
    182             }
    183 
    184             if (y2 > yaxis.max) {
    185                 sy1 += (sy1 - sy2) * (yaxis.max - y2) / (y2 - y1);
    186                 y2 = yaxis.max;
    187             }
    188             
    189             x1 = xaxis.p2c(x1);
    190             x2 = xaxis.p2c(x2);
    191             y1 = yaxis.p2c(y1);
    192             y2 = yaxis.p2c(y2);
    193             
    194             // the transformation may have swapped us
    195             if (x1 > x2) {
    196                 tmp = x2;
    197                 x2 = x1;
    198                 x1 = tmp;
    199             }
    200             if (y1 > y2) {
    201                 tmp = y2;
    202                 y2 = y1;
    203                 y1 = tmp;
    204             }
    205 
    206             tmp = ctx.globalAlpha;
    207             ctx.globalAlpha *= series.images.alpha;
    208             ctx.drawImage(img,
    209                           sx1, sy1, sx2 - sx1, sy2 - sy1,
    210                           x1 + plotOffset.left, y1 + plotOffset.top,
    211                           x2 - x1, y2 - y1);
    212             ctx.globalAlpha = tmp;
    213         }
    214     }
    215 
    216     function processRawData(plot, series, data, datapoints) {
    217         if (!series.images.show)
    218             return;
    219 
    220         // format is Image, x1, y1, x2, y2 (opposite corners)
    221         datapoints.format = [
    222             { required: true },
    223             { x: true, number: true, required: true },
    224             { y: true, number: true, required: true },
    225             { x: true, number: true, required: true },
    226             { y: true, number: true, required: true }
    227         ];
    228     }
    229     
    230     function init(plot) {
    231         plot.hooks.processRawData.push(processRawData);
    232         plot.hooks.drawSeries.push(drawSeries);
    233     }
    234     
    235     $.plot.plugins.push({
    236         init: init,
    237         options: options,
    238         name: 'image',
    239         version: '1.1'
    240     });
    241 })(jQuery);