Implement checkbox and radio input element rendering

This commit is contained in:
Niklas von Hertzen 2014-12-06 18:17:04 +02:00
parent e4329c4d37
commit 893ce74a33
5 changed files with 220 additions and 71 deletions

132
dist/html2canvas.js vendored
View File

@ -1874,6 +1874,16 @@ NodeParser.prototype.paintNode = function(container) {
}
}
if (container.node.nodeName === "INPUT" && container.node.type === "checkbox") {
this.paintCheckbox(container);
} else if (container.node.nodeName === "INPUT" && container.node.type === "radio") {
this.paintRadio(container);
} else {
this.paintElement(container);
}
};
NodeParser.prototype.paintElement = function(container) {
var bounds = container.parseBounds();
this.renderer.clip(container.backgroundClip, function() {
this.renderer.renderBackground(container, bounds, container.borders.borders.map(getWidth));
@ -1914,6 +1924,42 @@ NodeParser.prototype.paintNode = function(container) {
}, this);
};
NodeParser.prototype.paintCheckbox = function(container) {
var b = container.parseBounds();
var size = Math.min(b.width, b.height);
var bounds = {width: size - 1, height: size - 1, top: b.top, left: b.left};
var r = [3, 3];
var radius = [r, r, r, r];
var borders = [1,1,1,1].map(function(w) {
return {color: '#A5A5A5', width: w};
});
var borderPoints = calculateCurvePoints(bounds, radius, borders);
this.renderer.clip(container.backgroundClip, function() {
this.renderer.rectangle(bounds.left + 1, bounds.top + 1, bounds.width - 2, bounds.height - 2, "#DEDEDE");
this.renderer.renderBorders(calculateBorders(borders, bounds, borderPoints, radius));
if (container.node.checked) {
this.renderer.font('#424242', 'normal', 'normal', 'bold', (size - 3) + "px", 'arial');
this.renderer.text("\u2714", bounds.left + size / 6, bounds.top + size - 1);
}
}, this);
};
NodeParser.prototype.paintRadio = function(container) {
var bounds = container.parseBounds();
var size = Math.min(bounds.width, bounds.height) - 2;
this.renderer.clip(container.backgroundClip, function() {
this.renderer.circleStroke(bounds.left + 1, bounds.top + 1, size, '#DEDEDE', 1, '#A5A5A5');
if (container.node.checked) {
this.renderer.circle(Math.ceil(bounds.left + size / 4) + 1, Math.ceil(bounds.top + size / 4) + 1, Math.floor(size / 2), '#424242');
}
}, this);
};
NodeParser.prototype.paintFormValue = function(container) {
if (container.getValue().length > 0) {
var document = container.node.ownerDocument;
@ -2003,67 +2049,71 @@ NodeParser.prototype.parseBorders = function(container) {
return {
clip: this.parseBackgroundClip(container, borderPoints, borders, radius, nodeBounds),
borders: borders.map(function(border, borderSide) {
if (border.width > 0) {
var bx = nodeBounds.left;
var by = nodeBounds.top;
var bw = nodeBounds.width;
var bh = nodeBounds.height - (borders[2].width);
borders: calculateBorders(borders, nodeBounds, borderPoints, radius)
};
};
switch(borderSide) {
case 0:
// top border
bh = borders[0].width;
border.args = drawSide({
function calculateBorders(borders, nodeBounds, borderPoints, radius) {
return borders.map(function(border, borderSide) {
if (border.width > 0) {
var bx = nodeBounds.left;
var by = nodeBounds.top;
var bw = nodeBounds.width;
var bh = nodeBounds.height - (borders[2].width);
switch(borderSide) {
case 0:
// top border
bh = borders[0].width;
border.args = drawSide({
c1: [bx, by],
c2: [bx + bw, by],
c3: [bx + bw - borders[1].width, by + bh],
c4: [bx + borders[3].width, by + bh]
}, radius[0], radius[1],
borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);
break;
case 1:
// right border
bx = nodeBounds.left + nodeBounds.width - (borders[1].width);
bw = borders[1].width;
break;
case 1:
// right border
bx = nodeBounds.left + nodeBounds.width - (borders[1].width);
bw = borders[1].width;
border.args = drawSide({
border.args = drawSide({
c1: [bx + bw, by],
c2: [bx + bw, by + bh + borders[2].width],
c3: [bx, by + bh],
c4: [bx, by + borders[0].width]
}, radius[1], radius[2],
borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);
break;
case 2:
// bottom border
by = (by + nodeBounds.height) - (borders[2].width);
bh = borders[2].width;
border.args = drawSide({
break;
case 2:
// bottom border
by = (by + nodeBounds.height) - (borders[2].width);
bh = borders[2].width;
border.args = drawSide({
c1: [bx + bw, by + bh],
c2: [bx, by + bh],
c3: [bx + borders[3].width, by],
c4: [bx + bw - borders[3].width, by]
}, radius[2], radius[3],
borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);
break;
case 3:
// left border
bw = borders[3].width;
border.args = drawSide({
break;
case 3:
// left border
bw = borders[3].width;
border.args = drawSide({
c1: [bx, by + bh + borders[2].width],
c2: [bx, by],
c3: [bx + bw, by + borders[0].width],
c4: [bx + bw, by + bh]
}, radius[3], radius[0],
borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);
break;
}
break;
}
return border;
})
};
};
}
return border;
});
}
NodeParser.prototype.parseBackgroundClip = function(container, borderPoints, borders, radius, bounds) {
var backgroundClip = container.css('backgroundClip'),
@ -2833,6 +2883,20 @@ CanvasRenderer.prototype.rectangle = function(left, top, width, height, color) {
this.setFillStyle(color).fillRect(left, top, width, height);
};
CanvasRenderer.prototype.circle = function(left, top, size, color) {
this.setFillStyle(color);
this.ctx.beginPath();
this.ctx.arc(left + size / 2, top + size / 2, size / 2, 0, Math.PI*2, true);
this.ctx.closePath();
this.ctx.fill();
};
CanvasRenderer.prototype.circleStroke = function(left, top, size, color, stroke, strokeColor) {
this.circle(left, top, size, color);
this.ctx.strokeStyle = strokeColor;
this.ctx.stroke();
};
CanvasRenderer.prototype.drawShape = function(shape, color) {
this.shape(shape);
this.setFillStyle(color).fill();

File diff suppressed because one or more lines are too long

View File

@ -295,6 +295,16 @@ NodeParser.prototype.paintNode = function(container) {
}
}
if (container.node.nodeName === "INPUT" && container.node.type === "checkbox") {
this.paintCheckbox(container);
} else if (container.node.nodeName === "INPUT" && container.node.type === "radio") {
this.paintRadio(container);
} else {
this.paintElement(container);
}
};
NodeParser.prototype.paintElement = function(container) {
var bounds = container.parseBounds();
this.renderer.clip(container.backgroundClip, function() {
this.renderer.renderBackground(container, bounds, container.borders.borders.map(getWidth));
@ -335,6 +345,42 @@ NodeParser.prototype.paintNode = function(container) {
}, this);
};
NodeParser.prototype.paintCheckbox = function(container) {
var b = container.parseBounds();
var size = Math.min(b.width, b.height);
var bounds = {width: size - 1, height: size - 1, top: b.top, left: b.left};
var r = [3, 3];
var radius = [r, r, r, r];
var borders = [1,1,1,1].map(function(w) {
return {color: '#A5A5A5', width: w};
});
var borderPoints = calculateCurvePoints(bounds, radius, borders);
this.renderer.clip(container.backgroundClip, function() {
this.renderer.rectangle(bounds.left + 1, bounds.top + 1, bounds.width - 2, bounds.height - 2, "#DEDEDE");
this.renderer.renderBorders(calculateBorders(borders, bounds, borderPoints, radius));
if (container.node.checked) {
this.renderer.font('#424242', 'normal', 'normal', 'bold', (size - 3) + "px", 'arial');
this.renderer.text("\u2714", bounds.left + size / 6, bounds.top + size - 1);
}
}, this);
};
NodeParser.prototype.paintRadio = function(container) {
var bounds = container.parseBounds();
var size = Math.min(bounds.width, bounds.height) - 2;
this.renderer.clip(container.backgroundClip, function() {
this.renderer.circleStroke(bounds.left + 1, bounds.top + 1, size, '#DEDEDE', 1, '#A5A5A5');
if (container.node.checked) {
this.renderer.circle(Math.ceil(bounds.left + size / 4) + 1, Math.ceil(bounds.top + size / 4) + 1, Math.floor(size / 2), '#424242');
}
}, this);
};
NodeParser.prototype.paintFormValue = function(container) {
if (container.getValue().length > 0) {
var document = container.node.ownerDocument;
@ -424,67 +470,71 @@ NodeParser.prototype.parseBorders = function(container) {
return {
clip: this.parseBackgroundClip(container, borderPoints, borders, radius, nodeBounds),
borders: borders.map(function(border, borderSide) {
if (border.width > 0) {
var bx = nodeBounds.left;
var by = nodeBounds.top;
var bw = nodeBounds.width;
var bh = nodeBounds.height - (borders[2].width);
borders: calculateBorders(borders, nodeBounds, borderPoints, radius)
};
};
switch(borderSide) {
case 0:
// top border
bh = borders[0].width;
border.args = drawSide({
function calculateBorders(borders, nodeBounds, borderPoints, radius) {
return borders.map(function(border, borderSide) {
if (border.width > 0) {
var bx = nodeBounds.left;
var by = nodeBounds.top;
var bw = nodeBounds.width;
var bh = nodeBounds.height - (borders[2].width);
switch(borderSide) {
case 0:
// top border
bh = borders[0].width;
border.args = drawSide({
c1: [bx, by],
c2: [bx + bw, by],
c3: [bx + bw - borders[1].width, by + bh],
c4: [bx + borders[3].width, by + bh]
}, radius[0], radius[1],
borderPoints.topLeftOuter, borderPoints.topLeftInner, borderPoints.topRightOuter, borderPoints.topRightInner);
break;
case 1:
// right border
bx = nodeBounds.left + nodeBounds.width - (borders[1].width);
bw = borders[1].width;
break;
case 1:
// right border
bx = nodeBounds.left + nodeBounds.width - (borders[1].width);
bw = borders[1].width;
border.args = drawSide({
border.args = drawSide({
c1: [bx + bw, by],
c2: [bx + bw, by + bh + borders[2].width],
c3: [bx, by + bh],
c4: [bx, by + borders[0].width]
}, radius[1], radius[2],
borderPoints.topRightOuter, borderPoints.topRightInner, borderPoints.bottomRightOuter, borderPoints.bottomRightInner);
break;
case 2:
// bottom border
by = (by + nodeBounds.height) - (borders[2].width);
bh = borders[2].width;
border.args = drawSide({
break;
case 2:
// bottom border
by = (by + nodeBounds.height) - (borders[2].width);
bh = borders[2].width;
border.args = drawSide({
c1: [bx + bw, by + bh],
c2: [bx, by + bh],
c3: [bx + borders[3].width, by],
c4: [bx + bw - borders[3].width, by]
}, radius[2], radius[3],
borderPoints.bottomRightOuter, borderPoints.bottomRightInner, borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner);
break;
case 3:
// left border
bw = borders[3].width;
border.args = drawSide({
break;
case 3:
// left border
bw = borders[3].width;
border.args = drawSide({
c1: [bx, by + bh + borders[2].width],
c2: [bx, by],
c3: [bx + bw, by + borders[0].width],
c4: [bx + bw, by + bh]
}, radius[3], radius[0],
borderPoints.bottomLeftOuter, borderPoints.bottomLeftInner, borderPoints.topLeftOuter, borderPoints.topLeftInner);
break;
}
break;
}
return border;
})
};
};
}
return border;
});
}
NodeParser.prototype.parseBackgroundClip = function(container, borderPoints, borders, radius, bounds) {
var backgroundClip = container.css('backgroundClip'),

View File

@ -26,6 +26,20 @@ CanvasRenderer.prototype.rectangle = function(left, top, width, height, color) {
this.setFillStyle(color).fillRect(left, top, width, height);
};
CanvasRenderer.prototype.circle = function(left, top, size, color) {
this.setFillStyle(color);
this.ctx.beginPath();
this.ctx.arc(left + size / 2, top + size / 2, size / 2, 0, Math.PI*2, true);
this.ctx.closePath();
this.ctx.fill();
};
CanvasRenderer.prototype.circleStroke = function(left, top, size, color, stroke, strokeColor) {
this.circle(left, top, size, color);
this.ctx.strokeStyle = strokeColor;
this.ctx.stroke();
};
CanvasRenderer.prototype.drawShape = function(shape, color) {
this.shape(shape);
this.setFillStyle(color).fill();

View File

@ -5,7 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../test.js"></script>
<style>
input[type="radio"], input[type="checkbox"] {
margin: 10px;
display: inline-block;
}
</style>
</head>
@ -55,5 +58,23 @@
<textarea> text </textarea>
<textarea style="border-width:10px;">text</textarea>
<hr />
<input type="radio" value="radio1" />
<input type="radio" value="radio2" style="transform:scale(3)" />
<input type="RADIO" value="radio3" checked />
<input type="radio" value="radio4" style="transform:scale(3)" checked />
<input type="radio" value="radio5" style="transform:scale(3); background: red;" />
<input type="radio" value="radio6" style="width: 200px;" />
<input type="radio" value="radio6" style="width: 200px; height: 200px;" />
<input type="radio" value="radio6" style="width: 200px; height: 200px;" checked />
<input type="checkbox" value="checkbox1" />
<input type="chECKbox" value="checkbox2" style="transform:scale(3)" />
<input type="checkbox" value="checkbox3" checked />
<input type="checkbox" value="checkbox4" style="transform:scale(3)" checked />
<input type="checkbox" value="checkbox5" style="transform:scale(3); background: red;" />
<input type="checkbox" value="checkbox6" style="width: 200px;" />
<input type="checkbox" value="checkbox6" style="width: 200px; height: 200px;" />
<input type="checkbox" value="checkbox6" style="width: 200px; height: 200px;" checked />
<div style="position: absolute; width: 10px; height: 10px; border:1px solid rgb(165,165,165); border-radius: 3px; background: rgb(222,222,222)"></div>
</body>
</html>