/***************************************************** * canvas.js.php * * Contains functions for drawing instructions * onto the HTML5 Canvas for easier localization. * * Author: Jonathan Taratuta-Titus * Last Modified: 7 June 2013 * * © Copyright 2014 LabintheWild.org. * For questions about this file and permission to use * the code, contact us at info@labinthewild.org *****************************************************/ // main function for drawing all instructions function drawInst(current) { // draw first box of instructions drawFirst(); // draw second box of instructions drawSecond(current); } // draws instruction frame of the specified height function drawFrame(num,height, ctx) { var width = 550; var radius = 25; var lwidth = 2; ctx.beginPath(); ctx.lineWidth = lwidth; ctx.moveTo(radius,1); ctx.lineTo(width-radius,1); ctx.arcTo(width-1,1,width-1,radius,radius-1); ctx.lineTo(width-1,height-25); ctx.arcTo(width-1,height-1,width-radius,height-1,radius-1); ctx.lineTo(radius,height-1); ctx.arcTo(1,height-1,1,height-radius,radius-1); ctx.lineTo(1,radius); ctx.arcTo(1,1,radius,1,radius-1); ctx.arcTo(2*radius-1,1,2*radius-1,radius,radius-1); ctx.arcTo(2*radius-1,2*radius-1,radius,2*radius-1,radius-1); ctx.arcTo(1,2*radius-1,1,radius,radius-1); ctx.stroke(); ctx.font = 'bold 24pt Arial'; ctx.textBaseline = 'middle'; ctx.fillText(num,15,25); } // draws a sample box with top middle starting at (x,y) and side length s function drawSample(x,y,s,ctx) { ctx.beginPath(); ctx.lineWidth = 1; ctx.moveTo(pixadjust(x),pixadjust(y)); ctx.lineTo(pixadjust(x+(s/2)),pixadjust(y)); ctx.lineTo(pixadjust(x+(s/2)),pixadjust(y+s)); ctx.lineTo(pixadjust(x-(s/2)),pixadjust(y+s)); ctx.lineTo(pixadjust(x-(s/2)),pixadjust(y)); ctx.lineTo(pixadjust(x),pixadjust(y)); ctx.stroke(); } // draws a line (for boxes) starting at (x,y) and of length l function drawLine(x,y,l,ctx) { ctx.beginPath(); ctx.lineWidth = 2; ctx.moveTo(x,y); ctx.lineTo(x,y+l); ctx.stroke(); } // draw the first instruction box function drawFirst() { var firstText = "You will briefly see a square with a line. Pay close attention to the length of the line."; var firstExample = 'In this example, the line is 1/3 of the height of the square.'; var c = document.getElementById('instructionscanvas'); var ctx = c.getContext("2d"); drawFrame('1',212,ctx); paint_centered_wrap(c,115,5,320,60,firstText,16,2,'normal 16px Arial', 'black'); paint_centered_wrap(c,0,180,550,20,firstExample,16,2, 'normal 16px Arial', 'red'); ctx.strokeStyle = 'black'; // draw sample square drawSample(275,80,60,ctx); drawLine(275,80,20,ctx); } function drawSecond(current) { var secondText = 'You will now see a square of a different size, and in a different place on the screen.'; var secondRelText = 'Redraw a line with the same proportion to the frame as the one you saw before.'; var secondAbsText = 'Redraw a line of the same length as the one you saw before, independent of the size of the frame.'; var correctRelText = 'Correct! The line is again 1/3 of the height of the square.'; var wrongRelText = 'This line is not 1/3 of the height of the square, but has a different proportional length.'; var correctAbsText = 'Correct! The line has the same length as the one above.'; var wrongAbsText = 'This line does not have the same absolute length of the line seen before.'; c = document.getElementById('secondcanvas'); ctx = c.getContext("2d"); drawFrame('2',280,ctx); paint_centered_wrap(c,55,5,440,60,secondText,16,2,'normal 16px Arial','black'); ctx.strokeStyle = 'black'; // draw two squares for examples drawSample(183,100,81,ctx); drawSample(366,100,81,ctx); if (current=="instructions/relative.png") // the first task { drawExample(c,ctx,secondRelText,correctRelText,wrongRelText,27,20); } else // the second task { drawExample(c,ctx,secondAbsText,correctAbsText,wrongAbsText,20,27); } } function drawExample(c,ctx,second,correct,wrong,cnum,wnum) { paint_centered_wrap(c,55,50,440,40,second,16,2,'bold 16px Arial','black'); paint_centered_wrap(c,122,171,121,90,correct,12,2,'normal 12px Arial','#00C618'); paint_centered_wrap(c,305,171,121,90,wrong,12,2,'normal 12px Arial','red'); ctx.strokeStyle = 'black'; drawLine(183,100,cnum,ctx); drawLine(366,100,wnum,ctx); } /*** CODE BELOW ADAPTED FROM ***/ /*** http://andreinc.net/2012/11/14/painting-and-wrapping-a-text-inside-a-rectangular-area-html5-canvas/ ***/ /*** used for wrapping and centering canvas text into a given rectangle ***/ /** * @param canvas : The canvas object where to draw . * This object is usually obtained by doing: * canvas = document.getElementById('canvasId'); * @param x : The x position of the rectangle. * @param y : The y position of the rectangle. * @param w : The width of the rectangle. * @param h : The height of the rectangle. * @param text : The text we are going to centralize. * @param fh : The font height (in pixels). * @param spl : Vertical space between lines. * @param format: Font formatting (e.g., 'bold 16px Arial'). (added by JTT) * @param color : Color of text (e.g., 'black'). (added by JTT) */ paint_centered_wrap = function(canvas, x, y, w, h, text, fh, spl, format, color) { // The painting properties // Normally I would write this as an input parameter var Paint = { RECTANGLE_STROKE_STYLE : 'white', RECTANGLE_LINE_WIDTH : 1, VALUE_FONT : format, VALUE_FILL_STYLE : 'black' } /* * @param ctx : The 2d context * @param mw : The max width of the text accepted * @param font : The font used to draw the text * @param text : The text to be splitted into */ var split_lines = function(ctx, mw, font, text) { // We give a little "padding" // This should probably be an input param // but for the sake of simplicity we will keep it // this way mw = mw - 10; // We setup the text font to the context (if not already) ctx2d.font = font; ctx2d.fillStyle = color; // We split the text by words var delimit = ' '; var words = text.split(delimit); var new_line = words[0]; var lines = []; for(var i = 1; i < words.length; ++i) { if (ctx.measureText(new_line + delimit + words[i]).width < mw) { new_line += delimit + words[i]; } else { lines.push(new_line); new_line = words[i]; } } lines.push(new_line); // DEBUG // for(var j = 0; j < lines.length; ++j) { // console.log("line[" + j + "]=" + lines[j]); // } return lines; } // Obtains the context 2d of the canvas // It may return null var ctx2d = canvas.getContext('2d'); if (ctx2d) { // draw rectangular ctx2d.strokeStyle=Paint.RECTANGLE_STROKE_STYLE; ctx2d.lineWidth = Paint.RECTANGLE_LINE_WIDTH; ctx2d.strokeRect(x, y, w, h); // Paint text var lines = split_lines(ctx2d, w, Paint.VALUE_FONT, text); // Block of text height var both = lines.length * (fh + spl); if (both >= h) { // We won't be able to wrap the text inside the area // the area is too small. We should inform the user // about this in a meaningful way } else { // We determine the y of the first line var ly = (h - both)/2 + y + spl*lines.length; var lx = 0; for (var j = 0, ly; j < lines.length; ++j, ly+=fh+spl) { // We continue to centralize the lines lx = x+w/2-ctx2d.measureText(lines[j]).width/2; // DEBUG // console.log("ctx2d.fillText('"+ lines[j] +"', "+ lx +", " + ly + ")"); ctx2d.fillText(lines[j], lx, ly); } } } else { // Do something meaningful } }