1 | var dpr = typeof window !== 'undefined' && window.devicePixelRatio || 1;
|
2 |
|
3 | export var canvasHeightCache = Object.create(null);
|
4 |
|
5 | export 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 |
|
30 | export 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 |
|
78 | function computeFontSize(el) {
|
79 | return window
|
80 | .getComputedStyle(el, null)
|
81 | .getPropertyValue('font-size')
|
82 | .match(/(.+)px/)[1] * 1;
|
83 | }
|
84 |
|
85 | export 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 |
|
95 | export function clear(stage, comments) {
|
96 | stage.context.clearRect(0, 0, stage.width, stage.height);
|
97 |
|
98 | for (var i = 0; i < comments.length; i++) {
|
99 | comments[i].canvas = null;
|
100 | }
|
101 | }
|
102 |
|
103 | export 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 |
|
110 | export function framing(stage) {
|
111 | stage.context.clearRect(0, 0, stage.width, stage.height);
|
112 | }
|
113 |
|
114 | export 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 |
|
121 | export function render(stage, cmt) {
|
122 | stage.context.drawImage(cmt.canvas, cmt.x * dpr, cmt.y * dpr);
|
123 | }
|
124 |
|
125 | export function remove(stage, cmt) {
|
126 |
|
127 | cmt.canvas = null;
|
128 | }
|
129 |
|
130 | export 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 | };
|