UNPKG

3.84 kBJavaScriptView Raw
1var dpr = typeof window !== 'undefined' && window.devicePixelRatio || 1;
2
3export var canvasHeightCache = Object.create(null);
4
5export function canvasHeight(font, fontSize) {
6 if (canvasHeightCache[font]) {
7 return canvasHeightCache[font];
8 }
9 var height = 12;
10 var regex = /(\d+(?:\.\d+)?)(px|%|em|rem)(?:\s*\/\s*(\d+(?:\.\d+)?)(px|%|em|rem)?)?/;
11 var p = font.match(regex);
12 if (p) {
13 var fs = p[1] * 1 || 10;
14 var fsu = p[2];
15 var lh = p[3] * 1 || 1.2;
16 var lhu = p[4];
17 if (fsu === '%') fs *= fontSize.container / 100;
18 if (fsu === 'em') fs *= fontSize.container;
19 if (fsu === 'rem') fs *= fontSize.root;
20 if (lhu === 'px') height = lh;
21 if (lhu === '%') height = fs * lh / 100;
22 if (lhu === 'em') height = fs * lh;
23 if (lhu === 'rem') height = fontSize.root * lh;
24 if (lhu === undefined) height = fs * lh;
25 }
26 canvasHeightCache[font] = height;
27 return height;
28}
29
30export function createCommentCanvas(cmt, fontSize) {
31 if (typeof cmt.render === 'function') {
32 var cvs = cmt.render();
33 if (cvs instanceof HTMLCanvasElement) {
34 cmt.width = cvs.width;
35 cmt.height = cvs.height;
36 return cvs;
37 }
38 }
39 var canvas = document.createElement('canvas');
40 var ctx = canvas.getContext('2d');
41 var style = cmt.style || {};
42 style.font = style.font || '10px sans-serif';
43 style.textBaseline = style.textBaseline || 'bottom';
44 var strokeWidth = style.lineWidth * 1;
45 strokeWidth = (strokeWidth > 0 && strokeWidth !== Infinity)
46 ? Math.ceil(strokeWidth)
47 : !!style.strokeStyle * 1;
48 ctx.font = style.font;
49 cmt.width = cmt.width ||
50 Math.max(1, Math.ceil(ctx.measureText(cmt.text).width) + strokeWidth * 2);
51 cmt.height = cmt.height ||
52 Math.ceil(canvasHeight(style.font, fontSize)) + strokeWidth * 2;
53 canvas.width = cmt.width * dpr;
54 canvas.height = cmt.height * dpr;
55 ctx.scale(dpr, dpr);
56 for (var key in style) {
57 ctx[key] = style[key];
58 }
59 var baseline = 0;
60 switch (style.textBaseline) {
61 case 'top':
62 case 'hanging':
63 baseline = strokeWidth;
64 break;
65 case 'middle':
66 baseline = cmt.height >> 1;
67 break;
68 default:
69 baseline = cmt.height - strokeWidth;
70 }
71 if (style.strokeStyle) {
72 ctx.strokeText(cmt.text, strokeWidth, baseline);
73 }
74 ctx.fillText(cmt.text, strokeWidth, baseline);
75 return canvas;
76}
77
78function computeFontSize(el) {
79 return window
80 .getComputedStyle(el, null)
81 .getPropertyValue('font-size')
82 .match(/(.+)px/)[1] * 1;
83}
84
85export function init(container) {
86 var stage = document.createElement('canvas');
87 stage.context = stage.getContext('2d');
88 stage._fontSize = {
89 root: computeFontSize(document.getElementsByTagName('html')[0]),
90 container: computeFontSize(container)
91 };
92 return stage;
93}
94
95export function clear(stage, comments) {
96 stage.context.clearRect(0, 0, stage.width, stage.height);
97 // avoid caching canvas to reduce memory usage
98 for (var i = 0; i < comments.length; i++) {
99 comments[i].canvas = null;
100 }
101}
102
103export function resize(stage, width, height) {
104 stage.width = width * dpr;
105 stage.height = height * dpr;
106 stage.style.width = width + 'px';
107 stage.style.height = height + 'px';
108}
109
110export function framing(stage) {
111 stage.context.clearRect(0, 0, stage.width, stage.height);
112}
113
114export function setup(stage, comments) {
115 for (var i = 0; i < comments.length; i++) {
116 var cmt = comments[i];
117 cmt.canvas = createCommentCanvas(cmt, stage._fontSize);
118 }
119}
120
121export function render(stage, cmt) {
122 stage.context.drawImage(cmt.canvas, cmt.x * dpr, cmt.y * dpr);
123}
124
125export function remove(stage, cmt) {
126 // avoid caching canvas to reduce memory usage
127 cmt.canvas = null;
128}
129
130export default {
131 name: 'canvas',
132 init: init,
133 clear: clear,
134 resize: resize,
135 framing: framing,
136 setup: setup,
137 render: render,
138 remove: remove,
139};