Skip to content

Commit 893ce74

Browse files
committed
Implement checkbox and radio input element rendering
1 parent e4329c4 commit 893ce74

5 files changed

Lines changed: 222 additions & 73 deletions

File tree

dist/html2canvas.js

Lines changed: 99 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,6 +1874,16 @@ NodeParser.prototype.paintNode = function(container) {
18741874
}
18751875
}
18761876

1877+
if (container.node.nodeName === "INPUT" && container.node.type === "checkbox") {
1878+
this.paintCheckbox(container);
1879+
} else if (container.node.nodeName === "INPUT" && container.node.type === "radio") {
1880+
this.paintRadio(container);
1881+
} else {
1882+
this.paintElement(container);
1883+
}
1884+
};
1885+
1886+
NodeParser.prototype.paintElement = function(container) {
18771887
var bounds = container.parseBounds();
18781888
this.renderer.clip(container.backgroundClip, function() {
18791889
this.renderer.renderBackground(container, bounds, container.borders.borders.map(getWidth));
@@ -1914,6 +1924,42 @@ NodeParser.prototype.paintNode = function(container) {
19141924
}, this);
19151925
};
19161926

1927+
NodeParser.prototype.paintCheckbox = function(container) {
1928+
var b = container.parseBounds();
1929+
1930+
var size = Math.min(b.width, b.height);
1931+
var bounds = {width: size - 1, height: size - 1, top: b.top, left: b.left};
1932+
var r = [3, 3];
1933+
var radius = [r, r, r, r];
1934+
var borders = [1,1,1,1].map(function(w) {
1935+
return {color: '#A5A5A5', width: w};
1936+
});
1937+
1938+
var borderPoints = calculateCurvePoints(bounds, radius, borders);
1939+
1940+
this.renderer.clip(container.backgroundClip, function() {
1941+
this.renderer.rectangle(bounds.left + 1, bounds.top + 1, bounds.width - 2, bounds.height - 2, "#DEDEDE");
1942+
this.renderer.renderBorders(calculateBorders(borders, bounds, borderPoints, radius));
1943+
if (container.node.checked) {
1944+
this.renderer.font('#424242', 'normal', 'normal', 'bold', (size - 3) + "px", 'arial');
1945+
this.renderer.text("\u2714", bounds.left + size / 6, bounds.top + size - 1);
1946+
}
1947+
}, this);
1948+
};
1949+
1950+
NodeParser.prototype.paintRadio = function(container) {
1951+
var bounds = container.parseBounds();
1952+
1953+
var size = Math.min(bounds.width, bounds.height) - 2;
1954+
1955+
this.renderer.clip(container.backgroundClip, function() {
1956+
this.renderer.circleStroke(bounds.left + 1, bounds.top + 1, size, '#DEDEDE', 1, '#A5A5A5');
1957+
if (container.node.checked) {
1958+
this.renderer.circle(Math.ceil(bounds.left + size / 4) + 1, Math.ceil(bounds.top + size / 4) + 1, Math.floor(size / 2), '#424242');
1959+
}
1960+
}, this);
1961+
};
1962+
19171963
NodeParser.prototype.paintFormValue = function(container) {
19181964
if (container.getValue().length > 0) {
19191965
var document = container.node.ownerDocument;
@@ -2003,67 +2049,71 @@ NodeParser.prototype.parseBorders = function(container) {
20032049

20042050
return {
20052051
clip: this.parseBackgroundClip(container, borderPoints, borders, radius, nodeBounds),
2006-
borders: borders.map(function(border, borderSide) {
2007-
if (border.width > 0) {
2008-
var bx = nodeBounds.left;
2009-
var by = nodeBounds.top;
2010-
var bw = nodeBounds.width;
2011-
var bh = nodeBounds.height - (borders[2].width);
2012-
2013-
switch(borderSide) {
2014-
case 0:
2015-
// top border
2016-
bh = borders[0].width;
2017-
border.args = drawSide({
2052+
borders: calculateBorders(borders, nodeBounds, borderPoints, radius)
2053+
};
2054+
};
2055+
2056+
function calculateBorders(borders, nodeBounds, borderPoints, radius) {
2057+
return borders.map(function(border, borderSide) {
2058+
if (border.width > 0) {
2059+
var bx = nodeBounds.left;
2060+
var by = nodeBounds.top;
2061+
var bw = nodeBounds.width;
2062+
var bh = nodeBounds.height - (borders[2].width);
2063+
2064+
switch(borderSide) {
2065+
case 0:
2066+
// top border
2067+
bh = borders[0].width;
2068+
border.args = drawSide({
20182069
c1: [bx, by],
20192070
c2: [bx + bw, by],
20202071
c3: [bx + bw - borders[1].width, by + bh],
20212072
c4: [bx + borders[3].width, by + bh]
20222073
}, radius[0], radius[1],
20232074
borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);
2024-
break;
2025-
case 1:
2026-
// right border
2027-
bx = nodeBounds.left + nodeBounds.width - (borders[1].width);
2028-
bw = borders[1].width;
2075+
break;
2076+
case 1:
2077+
// right border
2078+
bx = nodeBounds.left + nodeBounds.width - (borders[1].width);
2079+
bw = borders[1].width;
20292080

2030-
border.args = drawSide({
2081+
border.args = drawSide({
20312082
c1: [bx + bw, by],
20322083
c2: [bx + bw, by + bh + borders[2].width],
20332084
c3: [bx, by + bh],
20342085
c4: [bx, by + borders[0].width]
20352086
}, radius[1], radius[2],
20362087
borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);
2037-
break;
2038-
case 2:
2039-
// bottom border
2040-
by = (by + nodeBounds.height) - (borders[2].width);
2041-
bh = borders[2].width;
2042-
border.args = drawSide({
2088+
break;
2089+
case 2:
2090+
// bottom border
2091+
by = (by + nodeBounds.height) - (borders[2].width);
2092+
bh = borders[2].width;
2093+
border.args = drawSide({
20432094
c1: [bx + bw, by + bh],
20442095
c2: [bx, by + bh],
20452096
c3: [bx + borders[3].width, by],
20462097
c4: [bx + bw - borders[3].width, by]
20472098
}, radius[2], radius[3],
20482099
borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);
2049-
break;
2050-
case 3:
2051-
// left border
2052-
bw = borders[3].width;
2053-
border.args = drawSide({
2100+
break;
2101+
case 3:
2102+
// left border
2103+
bw = borders[3].width;
2104+
border.args = drawSide({
20542105
c1: [bx, by + bh + borders[2].width],
20552106
c2: [bx, by],
20562107
c3: [bx + bw, by + borders[0].width],
20572108
c4: [bx + bw, by + bh]
20582109
}, radius[3], radius[0],
20592110
borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);
2060-
break;
2061-
}
2111+
break;
20622112
}
2063-
return border;
2064-
})
2065-
};
2066-
};
2113+
}
2114+
return border;
2115+
});
2116+
}
20672117

20682118
NodeParser.prototype.parseBackgroundClip = function(container, borderPoints, borders, radius, bounds) {
20692119
var backgroundClip = container.css('backgroundClip'),
@@ -2833,6 +2883,20 @@ CanvasRenderer.prototype.rectangle = function(left, top, width, height, color) {
28332883
this.setFillStyle(color).fillRect(left, top, width, height);
28342884
};
28352885

2886+
CanvasRenderer.prototype.circle = function(left, top, size, color) {
2887+
this.setFillStyle(color);
2888+
this.ctx.beginPath();
2889+
this.ctx.arc(left + size / 2, top + size / 2, size / 2, 0, Math.PI*2, true);
2890+
this.ctx.closePath();
2891+
this.ctx.fill();
2892+
};
2893+
2894+
CanvasRenderer.prototype.circleStroke = function(left, top, size, color, stroke, strokeColor) {
2895+
this.circle(left, top, size, color);
2896+
this.ctx.strokeStyle = strokeColor;
2897+
this.ctx.stroke();
2898+
};
2899+
28362900
CanvasRenderer.prototype.drawShape = function(shape, color) {
28372901
this.shape(shape);
28382902
this.setFillStyle(color).fill();

dist/html2canvas.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/nodeparser.js

Lines changed: 85 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,16 @@ NodeParser.prototype.paintNode = function(container) {
295295
}
296296
}
297297

298+
if (container.node.nodeName === "INPUT" && container.node.type === "checkbox") {
299+
this.paintCheckbox(container);
300+
} else if (container.node.nodeName === "INPUT" && container.node.type === "radio") {
301+
this.paintRadio(container);
302+
} else {
303+
this.paintElement(container);
304+
}
305+
};
306+
307+
NodeParser.prototype.paintElement = function(container) {
298308
var bounds = container.parseBounds();
299309
this.renderer.clip(container.backgroundClip, function() {
300310
this.renderer.renderBackground(container, bounds, container.borders.borders.map(getWidth));
@@ -335,6 +345,42 @@ NodeParser.prototype.paintNode = function(container) {
335345
}, this);
336346
};
337347

348+
NodeParser.prototype.paintCheckbox = function(container) {
349+
var b = container.parseBounds();
350+
351+
var size = Math.min(b.width, b.height);
352+
var bounds = {width: size - 1, height: size - 1, top: b.top, left: b.left};
353+
var r = [3, 3];
354+
var radius = [r, r, r, r];
355+
var borders = [1,1,1,1].map(function(w) {
356+
return {color: '#A5A5A5', width: w};
357+
});
358+
359+
var borderPoints = calculateCurvePoints(bounds, radius, borders);
360+
361+
this.renderer.clip(container.backgroundClip, function() {
362+
this.renderer.rectangle(bounds.left + 1, bounds.top + 1, bounds.width - 2, bounds.height - 2, "#DEDEDE");
363+
this.renderer.renderBorders(calculateBorders(borders, bounds, borderPoints, radius));
364+
if (container.node.checked) {
365+
this.renderer.font('#424242', 'normal', 'normal', 'bold', (size - 3) + "px", 'arial');
366+
this.renderer.text("\u2714", bounds.left + size / 6, bounds.top + size - 1);
367+
}
368+
}, this);
369+
};
370+
371+
NodeParser.prototype.paintRadio = function(container) {
372+
var bounds = container.parseBounds();
373+
374+
var size = Math.min(bounds.width, bounds.height) - 2;
375+
376+
this.renderer.clip(container.backgroundClip, function() {
377+
this.renderer.circleStroke(bounds.left + 1, bounds.top + 1, size, '#DEDEDE', 1, '#A5A5A5');
378+
if (container.node.checked) {
379+
this.renderer.circle(Math.ceil(bounds.left + size / 4) + 1, Math.ceil(bounds.top + size / 4) + 1, Math.floor(size / 2), '#424242');
380+
}
381+
}, this);
382+
};
383+
338384
NodeParser.prototype.paintFormValue = function(container) {
339385
if (container.getValue().length > 0) {
340386
var document = container.node.ownerDocument;
@@ -424,67 +470,71 @@ NodeParser.prototype.parseBorders = function(container) {
424470

425471
return {
426472
clip: this.parseBackgroundClip(container, borderPoints, borders, radius, nodeBounds),
427-
borders: borders.map(function(border, borderSide) {
428-
if (border.width > 0) {
429-
var bx = nodeBounds.left;
430-
var by = nodeBounds.top;
431-
var bw = nodeBounds.width;
432-
var bh = nodeBounds.height - (borders[2].width);
433-
434-
switch(borderSide) {
435-
case 0:
436-
// top border
437-
bh = borders[0].width;
438-
border.args = drawSide({
473+
borders: calculateBorders(borders, nodeBounds, borderPoints, radius)
474+
};
475+
};
476+
477+
function calculateBorders(borders, nodeBounds, borderPoints, radius) {
478+
return borders.map(function(border, borderSide) {
479+
if (border.width > 0) {
480+
var bx = nodeBounds.left;
481+
var by = nodeBounds.top;
482+
var bw = nodeBounds.width;
483+
var bh = nodeBounds.height - (borders[2].width);
484+
485+
switch(borderSide) {
486+
case 0:
487+
// top border
488+
bh = borders[0].width;
489+
border.args = drawSide({
439490
c1: [bx, by],
440491
c2: [bx + bw, by],
441492
c3: [bx + bw - borders[1].width, by + bh],
442493
c4: [bx + borders[3].width, by + bh]
443494
}, radius[0], radius[1],
444495
borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);
445-
break;
446-
case 1:
447-
// right border
448-
bx = nodeBounds.left + nodeBounds.width - (borders[1].width);
449-
bw = borders[1].width;
496+
break;
497+
case 1:
498+
// right border
499+
bx = nodeBounds.left + nodeBounds.width - (borders[1].width);
500+
bw = borders[1].width;
450501

451-
border.args = drawSide({
502+
border.args = drawSide({
452503
c1: [bx + bw, by],
453504
c2: [bx + bw, by + bh + borders[2].width],
454505
c3: [bx, by + bh],
455506
c4: [bx, by + borders[0].width]
456507
}, radius[1], radius[2],
457508
borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);
458-
break;
459-
case 2:
460-
// bottom border
461-
by = (by + nodeBounds.height) - (borders[2].width);
462-
bh = borders[2].width;
463-
border.args = drawSide({
509+
break;
510+
case 2:
511+
// bottom border
512+
by = (by + nodeBounds.height) - (borders[2].width);
513+
bh = borders[2].width;
514+
border.args = drawSide({
464515
c1: [bx + bw, by + bh],
465516
c2: [bx, by + bh],
466517
c3: [bx + borders[3].width, by],
467518
c4: [bx + bw - borders[3].width, by]
468519
}, radius[2], radius[3],
469520
borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);
470-
break;
471-
case 3:
472-
// left border
473-
bw = borders[3].width;
474-
border.args = drawSide({
521+
break;
522+
case 3:
523+
// left border
524+
bw = borders[3].width;
525+
border.args = drawSide({
475526
c1: [bx, by + bh + borders[2].width],
476527
c2: [bx, by],
477528
c3: [bx + bw, by + borders[0].width],
478529
c4: [bx + bw, by + bh]
479530
}, radius[3], radius[0],
480531
borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);
481-
break;
482-
}
532+
break;
483533
}
484-
return border;
485-
})
486-
};
487-
};
534+
}
535+
return border;
536+
});
537+
}
488538

489539
NodeParser.prototype.parseBackgroundClip = function(container, borderPoints, borders, radius, bounds) {
490540
var backgroundClip = container.css('backgroundClip'),

src/renderers/canvas.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@ CanvasRenderer.prototype.rectangle = function(left, top, width, height, color) {
2626
this.setFillStyle(color).fillRect(left, top, width, height);
2727
};
2828

29+
CanvasRenderer.prototype.circle = function(left, top, size, color) {
30+
this.setFillStyle(color);
31+
this.ctx.beginPath();
32+
this.ctx.arc(left + size / 2, top + size / 2, size / 2, 0, Math.PI*2, true);
33+
this.ctx.closePath();
34+
this.ctx.fill();
35+
};
36+
37+
CanvasRenderer.prototype.circleStroke = function(left, top, size, color, stroke, strokeColor) {
38+
this.circle(left, top, size, color);
39+
this.ctx.strokeStyle = strokeColor;
40+
this.ctx.stroke();
41+
};
42+
2943
CanvasRenderer.prototype.drawShape = function(shape, color) {
3044
this.shape(shape);
3145
this.setFillStyle(color).fill();

0 commit comments

Comments
 (0)