Turn audio into a shareable video. forked from nypublicradio/audiogram

text-wrapper.js 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. var smartquotes = require("smartquotes").string;
  2. module.exports = function(theme) {
  3. // Do some typechecking
  4. var left = ifNumeric(theme.captionLeft, 0),
  5. right = ifNumeric(theme.captionRight, theme.width),
  6. bottom = ifNumeric(theme.captionBottom, null),
  7. top = ifNumeric(theme.captionTop, null),
  8. labelLeft = ifNumeric(theme.labelLeft, 0),
  9. labelRight = ifNumeric(theme.labelRight, theme.width),
  10. labelBottom = ifNumeric(theme.labelBottom, null),
  11. labelTop = ifNumeric(theme.labelTop, null),
  12. renderfunctions ;
  13. if (bottom === null && top === null) {
  14. top = 0;
  15. }
  16. if (labelBottom === null && labelTop === null) {
  17. labelTop = 0;
  18. }
  19. var captionWidth = right - left,
  20. labelWidth = labelRight - labelLeft;
  21. return function(context, caption, type) {
  22. if (!caption) {
  23. return;
  24. }
  25. if (type === 'caption') {
  26. var lines = [[]],
  27. maxWidth = 0,
  28. words = smartquotes(caption + "").trim().replace(/\s\s+/g, " \n").split(/ /g);
  29. context.font = theme.captionFont;
  30. context.textBaseline = "top";
  31. context.textAlign = theme.captionAlign || "center";
  32. // Check whether each word exceeds the width limit
  33. // Wrap onto next line as needed
  34. words.forEach(function(word,i){
  35. var width = context.measureText(lines[lines.length - 1].concat([word]).join(" ")).width;
  36. if (word[0] === "\n" || (lines[lines.length - 1].length && width > captionWidth)) {
  37. word = word.trim();
  38. lines.push([word]);
  39. width = context.measureText(word).width;
  40. } else {
  41. lines[lines.length - 1].push(word);
  42. }
  43. maxWidth = Math.max(maxWidth,width);
  44. });
  45. var totalHeight = lines.length * theme.captionLineHeight + (lines.length - 1) * theme.captionLineSpacing;
  46. // horizontal alignment
  47. var x = theme.captionAlign === "left" ? left : theme.captionAlign === "right" ? right : (left + right) / 2;
  48. // Vertical alignment
  49. var y;
  50. if (top !== null && bottom !== null) {
  51. // Vertical center
  52. y = (bottom + top - totalHeight) / 2;
  53. } else if (bottom !== null) {
  54. // Vertical align bottom
  55. y = bottom - totalHeight;
  56. } else {
  57. // Vertical align top
  58. y = top;
  59. }
  60. // draw caption
  61. context.fillStyle = theme.captionColor;
  62. lines.forEach(function(line, i){
  63. context.fillText(line.join(" "), x, y + i * (theme.captionLineHeight + theme.captionLineSpacing));
  64. });
  65. } // end if caption
  66. if (type === 'label' && caption != 'None') {
  67. var lines = [[]],
  68. maxWidth = 0,
  69. words = smartquotes(caption + "").trim().replace(/\s\s+/g, " \n").split(/ /g);
  70. context.font = theme.labelFont;
  71. context.textBaseline = "top";
  72. context.textAlign = theme.labelAlign || "center";
  73. // Check whether each word exceeds the width limit
  74. // Wrap onto next line as needed
  75. words.forEach(function(word,i){
  76. var width = context.measureText(lines[lines.length - 1].concat([word]).join(" ")).width;
  77. if (word[0] === "\n" || (lines[lines.length - 1].length && width > labelWidth)) {
  78. word = word.trim();
  79. lines.push([word]);
  80. width = context.measureText(word).width;
  81. } else {
  82. lines[lines.length - 1].push(word);
  83. }
  84. maxWidth = Math.max(maxWidth,width);
  85. });
  86. var totalHeight = lines.length * theme.labelLineHeight + (lines.length - 1) * theme.labelLineSpacing;
  87. // horizontal alignment
  88. var x = theme.labelAlign === "left" ? labelLeft : theme.labelAlign === "right" ? labelRight : (labelLeft + labelRight) / 2;
  89. // Vertical alignment
  90. var y;
  91. if (labelTop !== null && labelBottom !== null) {
  92. // Vertical center
  93. y = (labelBottom + labelTop - totalHeight) / 2;
  94. } else if (labelBottom !== null) {
  95. // Vertical align bottom
  96. y = labelBottom - totalHeight;
  97. } else {
  98. // Vertical align top
  99. y = labelTop;
  100. }
  101. // draw label
  102. context.fillStyle = theme.labelColor;
  103. lines.forEach(function(line, i){
  104. context.fillText(line.join(" "), x, y + i * (theme.labelLineHeight + theme.labelLineSpacing));
  105. });
  106. }
  107. };
  108. }
  109. function ifNumeric(val, alt) {
  110. return (typeof val === "number" && !isNaN(val)) ? val : alt;
  111. }