threex.dynamictexture.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. var THREEx = THREEx || {}
  2. //////////////////////////////////////////////////////////////////////////////////
  3. // Constructor //
  4. //////////////////////////////////////////////////////////////////////////////////
  5. /**
  6. * create a dynamic texture with a underlying canvas
  7. *
  8. * @param {Number} width width of the canvas
  9. * @param {Number} height height of the canvas
  10. */
  11. THREEx.DynamicTexture = function(width, height){
  12. var canvas = document.createElement( 'canvas' )
  13. canvas.width = width
  14. canvas.height = height
  15. this.canvas = canvas
  16. var context = canvas.getContext( '2d' )
  17. this.context = context
  18. var texture = new THREE.Texture(canvas)
  19. this.texture = texture
  20. }
  21. //////////////////////////////////////////////////////////////////////////////////
  22. // methods //
  23. //////////////////////////////////////////////////////////////////////////////////
  24. /**
  25. * clear the canvas
  26. *
  27. * @param {String*} fillStyle the fillStyle to clear with, if not provided, fallback on .clearRect
  28. * @return {THREEx.DynamicTexture} the object itself, for chained texture
  29. */
  30. THREEx.DynamicTexture.prototype.clear = function(fillStyle){
  31. // depends on fillStyle
  32. if( fillStyle !== undefined ){
  33. this.context.fillStyle = fillStyle
  34. this.context.fillRect(0,0,this.canvas.width, this.canvas.height)
  35. }else{
  36. this.context.clearRect(0,0,this.canvas.width, this.canvas.height)
  37. }
  38. // make the texture as .needsUpdate
  39. this.texture.needsUpdate = true;
  40. // for chained API
  41. return this;
  42. }
  43. /**
  44. * draw text
  45. *
  46. * @param {String} text - the text to display
  47. * @param {Number|undefined} x - if provided, it is the x where to draw, if not, the text is centered
  48. * @param {Number} y - the y where to draw the text
  49. * @param {String*} fillStyle - the fillStyle to clear with, if not provided, fallback on .clearRect
  50. * @param {String*} contextFont - the font to use
  51. * @return {THREEx.DynamicTexture} - the object itself, for chained texture
  52. */
  53. THREEx.DynamicTexture.prototype.drawText = function(text, x, y, fillStyle, contextFont){
  54. // set font if needed
  55. if( contextFont !== undefined ) this.context.font = contextFont;
  56. // if x isnt provided
  57. if( x === undefined || x === null ){
  58. var textSize = this.context.measureText(text);
  59. x = (this.canvas.width - textSize.width) / 2;
  60. }
  61. // actually draw the text
  62. this.context.fillStyle = fillStyle;
  63. this.context.fillText(text, x, y);
  64. // make the texture as .needsUpdate
  65. this.texture.needsUpdate = true;
  66. // for chained API
  67. return this;
  68. };
  69. THREEx.DynamicTexture.prototype.drawTextCooked = function(options){
  70. var context = this.context
  71. var canvas = this.canvas
  72. options = options || {}
  73. var text = options.text
  74. var params = {
  75. margin : options.margin !== undefined ? options.margin : 0.1,
  76. lineHeight : options.lineHeight !== undefined ? options.lineHeight : 0.1,
  77. align : options.align !== undefined ? options.align : 'left',
  78. fillStyle : options.fillStyle !== undefined ? options.fillStyle : 'black',
  79. font : options.font !== undefined ? options.font : "bold "+(0.2*512)+"px Arial",
  80. }
  81. // sanity check
  82. console.assert(typeof(text) === 'string')
  83. context.save()
  84. context.fillStyle = params.fillStyle;
  85. context.font = params.font;
  86. var y = (params.lineHeight + params.margin)*canvas.height
  87. while(text.length > 0 ){
  88. // compute the text for specifically this line
  89. var maxText = computeMaxTextLength(text)
  90. // update the remaining text
  91. text = text.substr(maxText.length)
  92. // compute x based on params.align
  93. var textSize = context.measureText(maxText);
  94. if( params.align === 'left' ){
  95. var x = params.margin*canvas.width
  96. }else if( params.align === 'right' ){
  97. var x = (1-params.margin)*canvas.width - textSize.width
  98. }else if( params.align === 'center' ){
  99. var x = (canvas.width - textSize.width) / 2;
  100. }else console.assert( false )
  101. // actually draw the text at the proper position
  102. this.context.fillText(maxText, x, y);
  103. // goto the next line
  104. y += params.lineHeight*canvas.height
  105. }
  106. context.restore()
  107. // make the texture as .needsUpdate
  108. this.texture.needsUpdate = true;
  109. // for chained API
  110. return this;
  111. function computeMaxTextLength(text){
  112. var maxText = ''
  113. var maxWidth = (1-params.margin*2)*canvas.width
  114. while( maxText.length !== text.length ){
  115. var textSize = context.measureText(maxText);
  116. if( textSize.width > maxWidth ) break;
  117. maxText += text.substr(maxText.length, 1)
  118. }
  119. return maxText
  120. }
  121. }
  122. /**
  123. * execute the drawImage on the internal context
  124. * the arguments are the same the official context2d.drawImage
  125. */
  126. THREEx.DynamicTexture.prototype.drawImage = function(/* same params as context2d.drawImage */){
  127. // call the drawImage
  128. this.context.drawImage.apply(this.context, arguments)
  129. // make the texture as .needsUpdate
  130. this.texture.needsUpdate = true;
  131. // for chained API
  132. return this;
  133. }