      1 /*
      2     Copyright 2008,2009
      3         Matthias Ehmann,
      4         Michael Gerhaeuser,
      5         Carsten Miller,
      6         Bianca Valentin,
      7         Alfred Wassermann,
      8         Peter Wilfahrt
      9
     10     This file is part of JSXGraph.
     11
     12     JSXGraph is free software: you can redistribute it and/or modify
     13     it under the terms of the GNU Lesser General Public License as published by
     14     the Free Software Foundation, either version 3 of the License, or
     15     (at your option) any later version.
     16
     17     JSXGraph is distributed in the hope that it will be useful,
     18     but WITHOUT ANY WARRANTY; without even the implied warranty of
     19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     20     GNU Lesser General Public License for more details.
     21
     22     You should have received a copy of the GNU Lesser General Public License
     23     along with JSXGraph.  If not, see <http://www.gnu.org/licenses/>.
     24
     25 */
     26
     27 /**
     28  * @fileoverview In this file the geometry element Image is defined.
     29  */
     30
     31 /**
     32  * Construct and handle images
     33  * @class Image:
     34  * It inherits from @see GeometryElement.
     35  * @constructor
     36  */
     37 JXG.Image = function (board, url, coords, size, attributes) {
     38     this.constructor(board, attributes, JXG.OBJECT_TYPE_IMAGE, JXG.OBJECT_CLASS_OTHER);
     39
     40     this.initialCoords = new JXG.Coords(JXG.COORDS_BY_USER, coords, this.board);  // Still needed?
     41
     42     if (!JXG.isFunction(coords[0]) && !JXG.isFunction(coords[1])) {
     43         this.isDraggable = true;
     44     }
     45     this.X = JXG.createFunction(coords[0],this.board,'');
     46     this.Y = JXG.createFunction(coords[1],this.board,'');
     47     this.W = JXG.createFunction(size[0],this.board,'');
     48     this.H = JXG.createFunction(size[1],this.board,'');
     49     this.coords = new JXG.Coords(JXG.COORDS_BY_USER, [this.X(),this.Y()], this.board);
     50     this.updateCoords = new Function('','this.coords.setCoordinates(JXG.COORDS_BY_USER,[this.X(),this.Y()]);');
     51     this.updateSize = new Function('','this.coords.setCoordinates(JXG.COORDS_BY_USER,[this.W(),this.H()]);');
     52     this.usrSize = [this.W(), this.H()];
     53     this.size = [this.usrSize[0]*board.unitX,this.usrSize[1]*board.unitY];
     54     this.url = url;
     55
     56     this.parent = JXG.getRef(attributes.anchor);
     57
     58     this.id = this.board.setId(this, 'Im');
     59
     60     this.board.renderer.drawImage(this);
     61     if(!this.visProp.visible) {
     62        this.board.renderer.hide(this);
     63     }
     64 };
     65
     66 JXG.Image.prototype = new JXG.GeometryElement;
     67
     68 JXG.extend(JXG.Image.prototype, /** @lends JXG.Image.prototype */ {
     69
     70     /**
     71      * Checks whether (x,y) is over or near the image;
     72      * @param {int} x Coordinate in x direction, screen coordinates.
     73      * @param {int} y Coordinate in y direction, screen coordinates.
     74      * @return Always returns false
     75      */
     76     hasPoint: function (x,y) {
     77         var dx = x-this.coords.scrCoords[1],
     78             dy = this.coords.scrCoords[2]-y,
     79             r = this.board.options.precision.hasPoint;
     80
     81         if (dx>=-r && dx/*-this.size[0]*/<=2*r &&
     82             dy>=-r && dy/*-this.size[1]*/<=r) {
     83             return true;
     84         } else {
     85             return false;
     86         }
     87     },
     88
     89     /**
     90      * Recalculate the coordinates of lower left corner and the width amd the height.
     91      * @private
     92      */
     93     update: function () {
     94         if (this.needsUpdate) {
     95             this.updateCoords();
     96             this.usrSize = [this.W(), this.H()];
     97             this.size = [this.usrSize[0]*this.board.unitX,this.usrSize[1]*this.board.unitY];
     98             this.updateTransform();
     99         }
    100         return this;
    101     },
    102
    103     /**
    104      * Send an update request to the renderer.
    105      */
    106     updateRenderer: function () {
    107         if (this.needsUpdate) {
    108             this.board.renderer.updateImage(this);
    109             this.needsUpdate = false;
    110         }
    111         return this;
    112     },
    113
    114     updateTransform: function () {
    115         if (this.transformations.length==0) {
    116             return;
    117         }
    118         for (var i=0;i<this.transformations.length;i++) {
    119             this.transformations[i].update();
    120         }
    121     },
    122
    123     addTransform: function (transform) {
    124         if (JXG.isArray(transform)) {
    125             for (var i=0;i<transform.length;i++) {
    126                 this.transformations.push(transform[i]);
    127             }
    128         } else {
    129             this.transformations.push(transform);
    130         }
    131     },
    132
    133     /**
    134      * Sets x and y coordinate of the image.
    135      * @param {number} method The type of coordinates used here. Possible values are {@link JXG.COORDS_BY_USER} and {@link JXG.COORDS_BY_SCREEN}.
    136      * @param {number} x x coordinate in screen/user units
    137      * @param {number} y y coordinate in screen/user units
    138      * @param {number} x optional: previous x coordinate in screen/user units (ignored)
    139      * @param {number} y optional: previous y coordinate in screen/user units (ignored)
    140      */
    141     setPositionDirectly: function (method, x, y, oldx, oldy) {
    142         var newCoords, dx, dy;
    143
    144         if (method == JXG.COORDS_BY_SCREEN) {
    145             newCoords = new JXG.Coords(JXG.COORDS_BY_SCREEN, [x,y], this.board);
    146             x = newCoords.usrCoords[1];
    147             y = newCoords.usrCoords[2];
    148         }
    149         //dx = x-this.coords.usrCoords[1];
    150         //dy = x-this.coords.usrCoords[2];
    151
    152         this.X = JXG.createFunction(x,this.board,'');
    153         this.Y = JXG.createFunction(y,this.board,'');
    154         //this.coords = new JXG.Coords(JXG.COORDS_BY_USER, [this.X(),this.Y()], this.board);
    155         //this.prepareUpdate().update();
    156
    157         return this;
    158     }
    159
    160 });
    161
    162 /**
    163  * @class Displays an image.
    164  * @pseudo
    165  * @description Shows an image. The image can be supplied as an URL or an base64 encoded inline image
    166  * like "data:image/png;base64, /9j/4AAQSkZJRgA..." or a function returning an URL: function(){ return 'xxx.png; }.
    167  * @constructor
    168  * @name Image
    169  * @type JXG.Image
    170  * @throws {Exception} If the element cannot be constructed with the given parent objects an exception is thrown.
    171  * @param {String_Array_Array} url, [position of the top left vertice], [width,height]
    172  * @example
    173  * var im = board.create('image', ['http://geonext.uni-bayreuth.de/fileadmin/geonext/design/images/logo.gif', [-3,1],[5,5]]);
    174  *
    175  * </pre><div id="9850cda0-7ea0-4750-981c-68bacf9cca57" style="width: 400px; height: 400px;"></div>
    176  * <script type="text/javascript">
    177  *   var image_board = JXG.JSXGraph.initBoard('9850cda0-7ea0-4750-981c-68bacf9cca57', {boundingbox: [-4, 4, 4, -4], axis: false, showcopyright: false, shownavigation: false});
    178  *   var image_im = image_board.create('image', ['http://jsxgraph.uni-bayreuth.de/distrib/images/uccellino.jpg', [-3,1],[5,5]]);
    179  * </script><pre>
    180  */
    181 JXG.createImage = function(board, parents, attributes) {
    182     var url, attr;
    183     attr = JXG.copyAttributes(attributes, board.options, 'image');
    184     return new JXG.Image(board, parents[0], parents[1], parents[2], attr);
    185 };
    186
    187 JXG.JSXGraph.registerElement('image', JXG.createImage);
    188