src/pyams_skin/resources/js/ext/flot/jquery.flot.image.js
changeset 566 a1707c607eec
parent 565 318533413200
child 567 bca1726b1d85
equal deleted inserted replaced
565:318533413200 566:a1707c607eec
     1 /* Flot plugin for plotting images.
       
     2 
       
     3 Copyright (c) 2007-2014 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 
       
    78             if (s.data) {
       
    79                 s = s.data;
       
    80             }
       
    81 
       
    82             $.each(s, function (i, p) {
       
    83                 if (typeof p[0] === "string") {
       
    84                     urls.push(p[0]);
       
    85                     points.push(p);
       
    86                 }
       
    87             });
       
    88         });
       
    89 
       
    90         $.plot.image.load(urls, function (loadedImages) {
       
    91             $.each(points, function (i, p) {
       
    92                 var url = p[0];
       
    93                 if (loadedImages[url]) {
       
    94                     p[0] = loadedImages[url];
       
    95                 }
       
    96             });
       
    97 
       
    98             callback();
       
    99         });
       
   100     }
       
   101 
       
   102     $.plot.image.load = function (urls, callback) {
       
   103         var missing = urls.length, loaded = {};
       
   104         if (missing === 0) {
       
   105             callback({});
       
   106         }
       
   107 
       
   108         $.each(urls, function (i, url) {
       
   109             var handler = function () {
       
   110                 --missing;
       
   111                 loaded[url] = this;
       
   112 
       
   113                 if (missing === 0) {
       
   114                     callback(loaded);
       
   115                 }
       
   116             };
       
   117 
       
   118             $('<img />').load(handler).error(handler).attr('src', url);
       
   119         });
       
   120     };
       
   121 
       
   122     function drawSeries(plot, ctx, series) {
       
   123         var plotOffset = plot.getPlotOffset();
       
   124 
       
   125         if (!series.images || !series.images.show) {
       
   126             return;
       
   127         }
       
   128 
       
   129         var points = series.datapoints.points,
       
   130             ps = series.datapoints.pointsize;
       
   131 
       
   132         for (var i = 0; i < points.length; i += ps) {
       
   133             var img = points[i],
       
   134                 x1 = points[i + 1], y1 = points[i + 2],
       
   135                 x2 = points[i + 3], y2 = points[i + 4],
       
   136                 xaxis = series.xaxis, yaxis = series.yaxis,
       
   137                 tmp;
       
   138 
       
   139             // actually we should check img.complete, but it
       
   140             // appears to be a somewhat unreliable indicator in
       
   141             // IE6 (false even after load event)
       
   142             if (!img || img.width <= 0 || img.height <= 0) {
       
   143                 continue;
       
   144             }
       
   145 
       
   146             if (x1 > x2) {
       
   147                 tmp = x2;
       
   148                 x2 = x1;
       
   149                 x1 = tmp;
       
   150             }
       
   151             if (y1 > y2) {
       
   152                 tmp = y2;
       
   153                 y2 = y1;
       
   154                 y1 = tmp;
       
   155             }
       
   156 
       
   157             // if the anchor is at the center of the pixel, expand the
       
   158             // image by 1/2 pixel in each direction
       
   159             if (series.images.anchor === "center") {
       
   160                 tmp = 0.5 * (x2 - x1) / (img.width - 1);
       
   161                 x1 -= tmp;
       
   162                 x2 += tmp;
       
   163                 tmp = 0.5 * (y2 - y1) / (img.height - 1);
       
   164                 y1 -= tmp;
       
   165                 y2 += tmp;
       
   166             }
       
   167 
       
   168             // clip
       
   169             if (x1 === x2 || y1 === y2 ||
       
   170                 x1 >= xaxis.max || x2 <= xaxis.min ||
       
   171                 y1 >= yaxis.max || y2 <= yaxis.min) {
       
   172                 continue;
       
   173             }
       
   174 
       
   175             var sx1 = 0, sy1 = 0, sx2 = img.width, sy2 = img.height;
       
   176             if (x1 < xaxis.min) {
       
   177                 sx1 += (sx2 - sx1) * (xaxis.min - x1) / (x2 - x1);
       
   178                 x1 = xaxis.min;
       
   179             }
       
   180 
       
   181             if (x2 > xaxis.max) {
       
   182                 sx2 += (sx2 - sx1) * (xaxis.max - x2) / (x2 - x1);
       
   183                 x2 = xaxis.max;
       
   184             }
       
   185 
       
   186             if (y1 < yaxis.min) {
       
   187                 sy2 += (sy1 - sy2) * (yaxis.min - y1) / (y2 - y1);
       
   188                 y1 = yaxis.min;
       
   189             }
       
   190 
       
   191             if (y2 > yaxis.max) {
       
   192                 sy1 += (sy1 - sy2) * (yaxis.max - y2) / (y2 - y1);
       
   193                 y2 = yaxis.max;
       
   194             }
       
   195 
       
   196             x1 = xaxis.p2c(x1);
       
   197             x2 = xaxis.p2c(x2);
       
   198             y1 = yaxis.p2c(y1);
       
   199             y2 = yaxis.p2c(y2);
       
   200 
       
   201             // the transformation may have swapped us
       
   202             if (x1 > x2) {
       
   203                 tmp = x2;
       
   204                 x2 = x1;
       
   205                 x1 = tmp;
       
   206             }
       
   207             if (y1 > y2) {
       
   208                 tmp = y2;
       
   209                 y2 = y1;
       
   210                 y1 = tmp;
       
   211             }
       
   212 
       
   213             tmp = ctx.globalAlpha;
       
   214             ctx.globalAlpha *= series.images.alpha;
       
   215             ctx.drawImage(img,
       
   216                           sx1, sy1, sx2 - sx1, sy2 - sy1,
       
   217                           x1 + plotOffset.left, y1 + plotOffset.top,
       
   218                           x2 - x1, y2 - y1);
       
   219             ctx.globalAlpha = tmp;
       
   220         }
       
   221     }
       
   222 
       
   223     function processRawData(plot, series, data, datapoints) {
       
   224         if (!series.images.show) {
       
   225             return;
       
   226         }
       
   227 
       
   228         // format is Image, x1, y1, x2, y2 (opposite corners)
       
   229         datapoints.format = [
       
   230             { required: true },
       
   231             { x: true, number: true, required: true },
       
   232             { y: true, number: true, required: true },
       
   233             { x: true, number: true, required: true },
       
   234             { y: true, number: true, required: true }
       
   235         ];
       
   236     }
       
   237 
       
   238     function init(plot) {
       
   239         plot.hooks.processRawData.push(processRawData);
       
   240         plot.hooks.drawSeries.push(drawSeries);
       
   241     }
       
   242 
       
   243     $.plot.plugins.push({
       
   244         init: init,
       
   245         options: options,
       
   246         name: 'image',
       
   247         version: '1.1'
       
   248     });
       
   249 })(jQuery);