December 31, 2011

Chemdoodle web components tricks #3: Using mouseover functions to do multiple repaints on a canvas

Another step on the way to integrating ChemDoodle web components into SMARTCyp.

Here I show how you can use mouseover, and mouseout functions to redraw the canvas over and over again, and infinite number of times. The trick is to minimize the mouseover and mouseout functions, and use the drawChildExtras function to do all the drawings. Also, the first four lines and the last line in the drawChildExtras function are required to make this work (thanks to Kevin Theisen for helping me with those).

Here is the canvas, and below is the annotated code.



And here is the code:

 var tutorial3_testmol = new ChemDoodle.ViewerCanvas('tutorial3_testmol', 300, 300);
 tutorial3_testmol.specs.atoms_useJMOLColors = true;
 var caffeineMolFile = 'Molecule Name\n  CHEMDOOD08070920033D 0   0.00000     0.00000     0\n[Insert Comment Here]\n 14 15  0  0  0  0  0  0  0  0  1 V2000\n   -0.3318    2.0000    0.0000   O 0  0  0  1  0  0  0  0  0  0  0  0\n   -0.3318    1.0000    0.0000   C 0  0  0  1  0  0  0  0  0  0  0  0\n   -1.1980    0.5000    0.0000   N 0  0  0  1  0  0  0  0  0  0  0  0\n    0.5342    0.5000    0.0000   C 0  0  0  1  0  0  0  0  0  0  0  0\n   -1.1980   -0.5000    0.0000   C 0  0  0  1  0  0  0  0  0  0  0  0\n   -2.0640    1.0000    0.0000   C 0  0  0  4  0  0  0  0  0  0  0  0\n    1.4804    0.8047    0.0000   N 0  0  0  1  0  0  0  0  0  0  0  0\n    0.5342   -0.5000    0.0000   C 0  0  0  1  0  0  0  0  0  0  0  0\n   -2.0640   -1.0000    0.0000   O 0  0  0  1  0  0  0  0  0  0  0  0\n   -0.3318   -1.0000    0.0000   N 0  0  0  1  0  0  0  0  0  0  0  0\n    2.0640   -0.0000    0.0000   C 0  0  0  2  0  0  0  0  0  0  0  0\n    1.7910    1.7553    0.0000   C 0  0  0  4  0  0  0  0  0  0  0  0\n    1.4804   -0.8047    0.0000   N 0  0  0  1  0  0  0  0  0  0  0  0\n   -0.3318   -2.0000    0.0000   C 0  0  0  4  0  0  0  0  0  0  0  0\n  1  2  2  0  0  0  0\n  3  2  1  0  0  0  0\n  4  2  1  0  0  0  0\n  3  5  1  0  0  0  0\n  3  6  1  0  0  0  0\n  7  4  1  0  0  0  0\n  4  8  2  0  0  0  0\n  9  5  2  0  0  0  0\n 10  5  1  0  0  0  0\n 10  8  1  0  0  0  0\n  7 11  1  0  0  0  0\n  7 12  1  0  0  0  0\n 13  8  1  0  0  0  0\n 13 11  2  0  0  0  0\n 10 14  1  0  0  0  0\nM  END\n> \n07-08-2009\n';
 var caffeine = ChemDoodle.readMOL(caffeineMolFile);
 // get the dimension of the molecule
 var size = caffeine.getDimension();
 // find the scale by taking the minimum of the canvas/size ratios
 var scale = Math.min(tutorial3_testmol.width/size.x, tutorial3_testmol.height/size.y);
 // load the molecule first (this function automatically sets scale, so we need to change specs after)
 tutorial3_testmol.loadMolecule(caffeine);
 // change the specs.scale value to the scale calculated, shrinking it slightly so that text is not cut off
 tutorial3_testmol.specs.scale = scale*.8;
 //we are not showing atom numbers right away
 var showatomnumbers = false;
 
 tutorial3_testmol.mouseover = function(){
  //set atom numbers to be displayed
  showatomnumbers = true;
  this.repaint();
 }
 
 tutorial3_testmol.mouseout = function(){
  //set atom numbers to be hidden
  showatomnumbers = false;
  this.repaint();
 } 
 
 tutorial3_testmol.drawChildExtras = function(ctx){
  //four lines to make sure atom numbering, coordinates and scaling work correctly
  ctx.save();
  ctx.translate(this.width/2, this.height/2);
  ctx.rotate(this.specs.rotateAngle);
  ctx.scale(this.specs.scale, this.specs.scale);
  ctx.translate(-this.width/2, -this.height/2);
  //set the font size relative to the scaling of the molecule
  ctx.font = 'bold ' + 2.5*scale + 'px sans-serif';
  //center the atom numbers over the x,y coordinates of the atoms
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  //iterate through all atoms
  for (var i = 0, ii=caffeine.atoms.length; i<ii; i++) {
   var atom = caffeine.atoms[i];
   if(showatomnumbers){
      //draw a white circle behind the atom number
      ctx.fillStyle = "white";
      ctx.beginPath();
      ctx.arc(atom.x, atom.y, scale*1.8, 0, Math.PI*2, true);
      ctx.fill();
      //draw the atom number in the color
      ctx.fillStyle = ChemDoodle.ELEMENT[atom.label].jmolColor;
      //the "+scale*0.7" is to adjust the text on the y-center of the atoms.
      ctx.fillText(i + 1, atom.x, atom.y);
   }
  } 
  //restore the ctx settings so that application next time will start from scratch
  ctx.restore();
 }
 tutorial3_testmol.repaint();