JSXGraph logo
JSXGraph
JSXGraph share

Share

Texts, Images and Transformations II
QR code
<iframe 
    src="http://jsxgraph.org/share/iframe/texts-images-and-transformations-ii" 
    style="border: 1px solid black; overflow: hidden; width: 550px; aspect-ratio: 55 / 65;" 
    name="JSXGraph example: Texts, Images and Transformations II" 
    allowfullscreen
></iframe>
This code has to
<div id="board-0-wrapper" class="jxgbox-wrapper " style="width: 100%; ">
   <div id="board-0" class="jxgbox" style="aspect-ratio: 1 / 1; width: 100%;" data-ar="1 / 1"></div>
</div>
<div id="board-1-wrapper" class="jxgbox-wrapper " style="width: 100%; ">
   <div id="board-1" class="jxgbox" style="aspect-ratio: 1 / 1; width: 100%;" data-ar="1 / 1"></div>
</div>

<script type = "text/javascript"> 
    /*
    This example is licensed under a 
    Creative Commons Attribution ShareAlike 4.0 International License.
    https://creativecommons.org/licenses/by-sa/4.0/
    
    Please note you have to mention 
    The Center of Mobile Learning with Digital Technology
    in the credits.
    */
    
    const BOARDID0 = 'board-0';
    const BOARDID1 = 'board-1';
    const BOARDID = BOARDID0;

    var board, txt, im, p0, p1;
    
    board = JXG.JSXGraph.initBoard(BOARDID0, { boundingbox: [-5, 20, 5, -20], axis: true, showNavigation: true, showCopyright: true,
    });
    
    p0 = board.create('point', [0, 0], { style: 5, name: 'offset' });
    p1 = board.create('point', [3, 0], { style: 5, name: 'rotate' });
    
    txt = board.create('text', [0, 0, 'Hello'], { fontSize: 64 });
    im = board.create('image', ["/distrib/images/uccellino.jpg", [0, 0], [3, 12]], { opacity: 0.5 });
    
    // Translate text and image based on point "offset"
    var tOff = board.create('transform', [
        function() { return p0.X(); },
        function() { return p0.Y(); }
    ], { type: 'translate' });
    
    tOff.bindTo(txt);
    tOff.bindTo(im);
    
    // Rotate text and image around point "offset" by dragging point "rotate"
    var tRot = board.create('transform', [
        function() { return Math.atan2(p1.Y() - p0.Y(), p1.X() - p0.X()); },
        p0
    ], { type: 'rotate' });
    
    tRot.bindTo(txt);
    tRot.bindTo(im);
    
    
    var board1, txt, p0, p1, p2, im;
    
    board1 = JXG.JSXGraph.initBoard(BOARDID1, { boundingbox: [-5, 20, 5, -20], axis: true, showNavigation: true, showCopyright: true,
    });
    
    p0 = board1.create('point', [0, 0], { style: 5, name: 'offset' });
    p1 = board1.create('point', [3, 0], { style: 5, name: 'rotate here' });
    p2 = board1.create('point', [0, 4], { color: 'blue', trace: true });
    txt = board1.create('text', [0, 0, JXG.JSXGraph.rendererType], { fontSize: 64 });
    im = board1.create('image', ["/distrib/images/uccellino.jpg", [0, 0], [3, 12]], { opacity: 0.5 });
    
    // Transformations
    var tOffInv = board1.create('transform', [
        function() { return -p0.X(); },
        function() { return -p0.Y(); }
    ], { type: 'translate' });
    
    var tOff = board1.create('transform', [
        function() { return p0.X(); },
        function() { return p0.Y(); }
    ], { type: 'translate' });
    
    // Bind translation to points and objects
    tOff.bindTo(p1);
    tOff.bindTo(txt);
    tOff.bindTo(im);
    
    // Rotation and scaling
    var ratio = 4; // ratio between board dimensions in user coordinates
    var ts1 = board1.create('transform', [function() { return ratio; }, function() { return 1; }], { type: 'scale' });
    var ts2 = board1.create('transform', [function() { return 1 / ratio; }, function() { return 1; }], { type: 'scale' });
    
    var tRot = board1.create('transform', [
        function() { return Math.atan2((p1.Y() - p0.Y()) / ratio, p1.X() - p0.X()); }
    ], { type: 'rotate' });
    
    // Apply transformations to text and image
    tOffInv.bindTo(txt);
    ts1.bindTo(txt);
    tRot.bindTo(txt);
    ts2.bindTo(txt);
    tOff.bindTo(txt);
    
    tOffInv.bindTo(im);
    ts1.bindTo(im);
    tRot.bindTo(im);
    ts2.bindTo(im);
    tOff.bindTo(im);
    
    // Rotate p2 in user coordinates for comparison
    tRot.bindTo(p2);
    
    board1.update();
 </script> 
/*
This example is licensed under a 
Creative Commons Attribution ShareAlike 4.0 International License.
https://creativecommons.org/licenses/by-sa/4.0/

Please note you have to mention 
The Center of Mobile Learning with Digital Technology
in the credits.
*/

const BOARDID0 = 'your_div_id_0'; // Insert your 1st board id here!
const BOARDID1 = 'your_div_id_1'; // Insert your 2nd board id here!

var board, txt, im, p0, p1;

board = JXG.JSXGraph.initBoard(BOARDID0, { boundingbox: [-5, 20, 5, -20], axis: true, showNavigation: true, showCopyright: true,
});

p0 = board.create('point', [0, 0], { style: 5, name: 'offset' });
p1 = board.create('point', [3, 0], { style: 5, name: 'rotate' });

txt = board.create('text', [0, 0, 'Hello'], { fontSize: 64 });
im = board.create('image', ["/distrib/images/uccellino.jpg", [0, 0], [3, 12]], { opacity: 0.5 });

// Translate text and image based on point "offset"
var tOff = board.create('transform', [
    function() { return p0.X(); },
    function() { return p0.Y(); }
], { type: 'translate' });

tOff.bindTo(txt);
tOff.bindTo(im);

// Rotate text and image around point "offset" by dragging point "rotate"
var tRot = board.create('transform', [
    function() { return Math.atan2(p1.Y() - p0.Y(), p1.X() - p0.X()); },
    p0
], { type: 'rotate' });

tRot.bindTo(txt);
tRot.bindTo(im);


var board1, txt, p0, p1, p2, im;

board1 = JXG.JSXGraph.initBoard(BOARDID1, { boundingbox: [-5, 20, 5, -20], axis: true, showNavigation: true, showCopyright: true,
});

p0 = board1.create('point', [0, 0], { style: 5, name: 'offset' });
p1 = board1.create('point', [3, 0], { style: 5, name: 'rotate here' });
p2 = board1.create('point', [0, 4], { color: 'blue', trace: true });
txt = board1.create('text', [0, 0, JXG.JSXGraph.rendererType], { fontSize: 64 });
im = board1.create('image', ["/distrib/images/uccellino.jpg", [0, 0], [3, 12]], { opacity: 0.5 });

// Transformations
var tOffInv = board1.create('transform', [
    function() { return -p0.X(); },
    function() { return -p0.Y(); }
], { type: 'translate' });

var tOff = board1.create('transform', [
    function() { return p0.X(); },
    function() { return p0.Y(); }
], { type: 'translate' });

// Bind translation to points and objects
tOff.bindTo(p1);
tOff.bindTo(txt);
tOff.bindTo(im);

// Rotation and scaling
var ratio = 4; // ratio between board dimensions in user coordinates
var ts1 = board1.create('transform', [function() { return ratio; }, function() { return 1; }], { type: 'scale' });
var ts2 = board1.create('transform', [function() { return 1 / ratio; }, function() { return 1; }], { type: 'scale' });

var tRot = board1.create('transform', [
    function() { return Math.atan2((p1.Y() - p0.Y()) / ratio, p1.X() - p0.X()); }
], { type: 'rotate' });

// Apply transformations to text and image
tOffInv.bindTo(txt);
ts1.bindTo(txt);
tRot.bindTo(txt);
ts2.bindTo(txt);
tOff.bindTo(txt);

tOffInv.bindTo(im);
ts1.bindTo(im);
tRot.bindTo(im);
ts2.bindTo(im);
tOff.bindTo(im);

// Rotate p2 in user coordinates for comparison
tRot.bindTo(p2);

board1.update();
<jsxgraph width="100%, 100%" aspect-ratio="1 / 1, 1 / 1" numberOfBoards="2" title="Texts, Images and Transformations II" description="This construction was copied from JSXGraph examples database: BTW HERE SHOULD BE A GENERATED LINKuseGlobalJS="false">
   /*
   This example is licensed under a 
   Creative Commons Attribution ShareAlike 4.0 International License.
   https://creativecommons.org/licenses/by-sa/4.0/
   
   Please note you have to mention 
   The Center of Mobile Learning with Digital Technology
   in the credits.
   */
   
   var board, txt, im, p0, p1;
   
   board = JXG.JSXGraph.initBoard(BOARDID0, { boundingbox: [-5, 20, 5, -20], axis: true, showNavigation: true, showCopyright: true,
   });
   
   p0 = board.create('point', [0, 0], { style: 5, name: 'offset' });
   p1 = board.create('point', [3, 0], { style: 5, name: 'rotate' });
   
   txt = board.create('text', [0, 0, 'Hello'], { fontSize: 64 });
   im = board.create('image', ["/distrib/images/uccellino.jpg", [0, 0], [3, 12]], { opacity: 0.5 });
   
   // Translate text and image based on point "offset"
   var tOff = board.create('transform', [
       function() { return p0.X(); },
       function() { return p0.Y(); }
   ], { type: 'translate' });
   
   tOff.bindTo(txt);
   tOff.bindTo(im);
   
   // Rotate text and image around point "offset" by dragging point "rotate"
   var tRot = board.create('transform', [
       function() { return Math.atan2(p1.Y() - p0.Y(), p1.X() - p0.X()); },
       p0
   ], { type: 'rotate' });
   
   tRot.bindTo(txt);
   tRot.bindTo(im);
   
   
   var board1, txt, p0, p1, p2, im;
   
   board1 = JXG.JSXGraph.initBoard(BOARDID1, { boundingbox: [-5, 20, 5, -20], axis: true, showNavigation: true, showCopyright: true,
   });
   
   p0 = board1.create('point', [0, 0], { style: 5, name: 'offset' });
   p1 = board1.create('point', [3, 0], { style: 5, name: 'rotate here' });
   p2 = board1.create('point', [0, 4], { color: 'blue', trace: true });
   txt = board1.create('text', [0, 0, JXG.JSXGraph.rendererType], { fontSize: 64 });
   im = board1.create('image', ["/distrib/images/uccellino.jpg", [0, 0], [3, 12]], { opacity: 0.5 });
   
   // Transformations
   var tOffInv = board1.create('transform', [
       function() { return -p0.X(); },
       function() { return -p0.Y(); }
   ], { type: 'translate' });
   
   var tOff = board1.create('transform', [
       function() { return p0.X(); },
       function() { return p0.Y(); }
   ], { type: 'translate' });
   
   // Bind translation to points and objects
   tOff.bindTo(p1);
   tOff.bindTo(txt);
   tOff.bindTo(im);
   
   // Rotation and scaling
   var ratio = 4; // ratio between board dimensions in user coordinates
   var ts1 = board1.create('transform', [function() { return ratio; }, function() { return 1; }], { type: 'scale' });
   var ts2 = board1.create('transform', [function() { return 1 / ratio; }, function() { return 1; }], { type: 'scale' });
   
   var tRot = board1.create('transform', [
       function() { return Math.atan2((p1.Y() - p0.Y()) / ratio, p1.X() - p0.X()); }
   ], { type: 'rotate' });
   
   // Apply transformations to text and image
   tOffInv.bindTo(txt);
   ts1.bindTo(txt);
   tRot.bindTo(txt);
   ts2.bindTo(txt);
   tOff.bindTo(txt);
   
   tOffInv.bindTo(im);
   ts1.bindTo(im);
   tRot.bindTo(im);
   ts2.bindTo(im);
   tOff.bindTo(im);
   
   // Rotate p2 in user coordinates for comparison
   tRot.bindTo(p2);
   
   board1.update();
</jsxgraph>

Texts, Images and Transformations II

### The Problem This example is similar to the one [[Texts and Transformations]], beside that the x-axis and the y-axis have different scalings. To be precise, the ratio of the two scalings is equal to 4. The result is that rotating the text and the image will also stretch these objects. See first example. ### The Solution In order to avoid this effect, we have to do the following steps: - Move the rotation center to the origin ```javascript var tOffInv = brd.create('transform', [function(){return -p0.X()}, function(){return -p0.Y()}], {type:'translate'}); ``` - Scale the objects by the ratio between the axis scalings (i.e., 4) ```javascript var ts1 = brd.create('transform', [function(){return ratio;}, function(){return 1;}], {type:'scale'}); ``` - Rotate around the origin (angle also scaled) ```javascript var tRot = brd.create('transform', [function(){return Math.atan2((p1.Y()-p0.Y())/ratio, p1.X()-p0.X());}], {type:'rotate'}); ``` - Undo the scaling ```javascript var ts2 = brd.create('transform', [function(){return 1/ratio;}, function(){return 1;}], {type:'scale'}); ``` - Move the rotation center back ```javascript var tOff = brd.create('transform', [function(){return p0.X()}, function(){return p0.Y()}], {type:'translate'}); ``` - Apply all transformations to both the text and the image ```javascript tOffInv.bindTo(txt); ts1.bindTo(txt); tRot.bindTo(txt); ts2.bindTo(txt); tOff.bindTo(txt); tOffInv.bindTo(im); ts1.bindTo(im); tRot.bindTo(im); ts2.bindTo(im); tOff.bindTo(im); ```
// Define the ids of your boards in BOARDID0, BOARDID1,...

var board, txt, im, p0, p1;

board = JXG.JSXGraph.initBoard(BOARDID0, { boundingbox: [-5, 20, 5, -20], axis: true, showNavigation: true, showCopyright: true,
});

p0 = board.create('point', [0, 0], { style: 5, name: 'offset' });
p1 = board.create('point', [3, 0], { style: 5, name: 'rotate' });

txt = board.create('text', [0, 0, 'Hello'], { fontSize: 64 });
im = board.create('image', ["/distrib/images/uccellino.jpg", [0, 0], [3, 12]], { opacity: 0.5 });

// Translate text and image based on point "offset"
var tOff = board.create('transform', [
    function() { return p0.X(); },
    function() { return p0.Y(); }
], { type: 'translate' });

tOff.bindTo(txt);
tOff.bindTo(im);

// Rotate text and image around point "offset" by dragging point "rotate"
var tRot = board.create('transform', [
    function() { return Math.atan2(p1.Y() - p0.Y(), p1.X() - p0.X()); },
    p0
], { type: 'rotate' });

tRot.bindTo(txt);
tRot.bindTo(im);


var board1, txt, p0, p1, p2, im;

board1 = JXG.JSXGraph.initBoard(BOARDID1, { boundingbox: [-5, 20, 5, -20], axis: true, showNavigation: true, showCopyright: true,
});

p0 = board1.create('point', [0, 0], { style: 5, name: 'offset' });
p1 = board1.create('point', [3, 0], { style: 5, name: 'rotate here' });
p2 = board1.create('point', [0, 4], { color: 'blue', trace: true });
txt = board1.create('text', [0, 0, JXG.JSXGraph.rendererType], { fontSize: 64 });
im = board1.create('image', ["/distrib/images/uccellino.jpg", [0, 0], [3, 12]], { opacity: 0.5 });

// Transformations
var tOffInv = board1.create('transform', [
    function() { return -p0.X(); },
    function() { return -p0.Y(); }
], { type: 'translate' });

var tOff = board1.create('transform', [
    function() { return p0.X(); },
    function() { return p0.Y(); }
], { type: 'translate' });

// Bind translation to points and objects
tOff.bindTo(p1);
tOff.bindTo(txt);
tOff.bindTo(im);

// Rotation and scaling
var ratio = 4; // ratio between board dimensions in user coordinates
var ts1 = board1.create('transform', [function() { return ratio; }, function() { return 1; }], { type: 'scale' });
var ts2 = board1.create('transform', [function() { return 1 / ratio; }, function() { return 1; }], { type: 'scale' });

var tRot = board1.create('transform', [
    function() { return Math.atan2((p1.Y() - p0.Y()) / ratio, p1.X() - p0.X()); }
], { type: 'rotate' });

// Apply transformations to text and image
tOffInv.bindTo(txt);
ts1.bindTo(txt);
tRot.bindTo(txt);
ts2.bindTo(txt);
tOff.bindTo(txt);

tOffInv.bindTo(im);
ts1.bindTo(im);
tRot.bindTo(im);
ts2.bindTo(im);
tOff.bindTo(im);

// Rotate p2 in user coordinates for comparison
tRot.bindTo(p2);

board1.update();

license

This example is licensed under a Creative Commons Attribution ShareAlike 4.0 International License.
Please note you have to mention The Center of Mobile Learning with Digital Technology in the credits.