mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
parent
30a2578f38
commit
6554d4c8c8
@ -6,6 +6,7 @@ import type Size from './drawing/Size';
|
|||||||
|
|
||||||
import type {BackgroundImage} from './parsing/background';
|
import type {BackgroundImage} from './parsing/background';
|
||||||
import type {Border, BorderSide} from './parsing/border';
|
import type {Border, BorderSide} from './parsing/border';
|
||||||
|
import type {TextShadow} from './parsing/textShadow';
|
||||||
|
|
||||||
import type {Path, BoundCurves} from './Bounds';
|
import type {Path, BoundCurves} from './Bounds';
|
||||||
import type {ImageStore, ImageElement} from './ImageLoader';
|
import type {ImageStore, ImageElement} from './ImageLoader';
|
||||||
@ -163,7 +164,23 @@ export default class CanvasRenderer {
|
|||||||
renderText(text: TextBounds, textContainer: TextContainer) {
|
renderText(text: TextBounds, textContainer: TextContainer) {
|
||||||
const container = textContainer.parent;
|
const container = textContainer.parent;
|
||||||
this.ctx.fillStyle = container.style.color.toString();
|
this.ctx.fillStyle = container.style.color.toString();
|
||||||
|
if (container.style.textShadow && text.text.trim().length) {
|
||||||
|
container.style.textShadow.slice(0).reverse().forEach(textShadow => {
|
||||||
|
this.ctx.shadowColor = textShadow.color.toString();
|
||||||
|
this.ctx.shadowOffsetX = textShadow.offsetX * this.options.scale;
|
||||||
|
this.ctx.shadowOffsetY = textShadow.offsetY * this.options.scale;
|
||||||
|
this.ctx.shadowBlur = textShadow.blur;
|
||||||
|
|
||||||
|
this.ctx.fillText(
|
||||||
|
text.text,
|
||||||
|
text.bounds.left,
|
||||||
|
text.bounds.top + text.bounds.height
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
this.ctx.fillText(text.text, text.bounds.left, text.bounds.top + text.bounds.height);
|
this.ctx.fillText(text.text, text.bounds.left, text.bounds.top + text.bounds.height);
|
||||||
|
}
|
||||||
|
|
||||||
const textDecoration = container.style.textDecoration;
|
const textDecoration = container.style.textDecoration;
|
||||||
if (textDecoration) {
|
if (textDecoration) {
|
||||||
textDecoration.textDecorationLine.forEach(textDecorationLine => {
|
textDecoration.textDecorationLine.forEach(textDecorationLine => {
|
||||||
|
@ -10,6 +10,7 @@ import type {Font} from './parsing/font';
|
|||||||
import type {Overflow} from './parsing/overflow';
|
import type {Overflow} from './parsing/overflow';
|
||||||
import type {Padding} from './parsing/padding';
|
import type {Padding} from './parsing/padding';
|
||||||
import type {Position} from './parsing/position';
|
import type {Position} from './parsing/position';
|
||||||
|
import type {TextShadow} from './parsing/textShadow';
|
||||||
import type {TextTransform} from './parsing/textTransform';
|
import type {TextTransform} from './parsing/textTransform';
|
||||||
import type {TextDecoration} from './parsing/textDecoration';
|
import type {TextDecoration} from './parsing/textDecoration';
|
||||||
import type {Transform} from './parsing/transform';
|
import type {Transform} from './parsing/transform';
|
||||||
@ -35,6 +36,7 @@ import {parseOverflow, OVERFLOW} from './parsing/overflow';
|
|||||||
import {parsePadding} from './parsing/padding';
|
import {parsePadding} from './parsing/padding';
|
||||||
import {parsePosition, POSITION} from './parsing/position';
|
import {parsePosition, POSITION} from './parsing/position';
|
||||||
import {parseTextDecoration} from './parsing/textDecoration';
|
import {parseTextDecoration} from './parsing/textDecoration';
|
||||||
|
import {parseTextShadow} from './parsing/textShadow';
|
||||||
import {parseTextTransform} from './parsing/textTransform';
|
import {parseTextTransform} from './parsing/textTransform';
|
||||||
import {parseTransform} from './parsing/transform';
|
import {parseTransform} from './parsing/transform';
|
||||||
import {parseVisibility, VISIBILITY} from './parsing/visibility';
|
import {parseVisibility, VISIBILITY} from './parsing/visibility';
|
||||||
@ -63,6 +65,7 @@ type StyleDeclaration = {
|
|||||||
padding: Padding,
|
padding: Padding,
|
||||||
position: Position,
|
position: Position,
|
||||||
textDecoration: TextDecoration,
|
textDecoration: TextDecoration,
|
||||||
|
textShadow: Array<TextShadow> | null,
|
||||||
textTransform: TextTransform,
|
textTransform: TextTransform,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
visibility: Visibility,
|
visibility: Visibility,
|
||||||
@ -106,6 +109,7 @@ export default class NodeContainer {
|
|||||||
padding: parsePadding(style),
|
padding: parsePadding(style),
|
||||||
position: parsePosition(style.position),
|
position: parsePosition(style.position),
|
||||||
textDecoration: parseTextDecoration(style),
|
textDecoration: parseTextDecoration(style),
|
||||||
|
textShadow: parseTextShadow(style.textShadow),
|
||||||
textTransform: parseTextTransform(style.textTransform),
|
textTransform: parseTextTransform(style.textTransform),
|
||||||
transform: parseTransform(style),
|
transform: parseTransform(style),
|
||||||
visibility: parseVisibility(style.visibility),
|
visibility: parseVisibility(style.visibility),
|
||||||
|
42
src/parsing/textShadow.js
Normal file
42
src/parsing/textShadow.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* @flow */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import Color from '../Color';
|
||||||
|
|
||||||
|
export type TextShadow = {
|
||||||
|
color: Color,
|
||||||
|
offsetX: number,
|
||||||
|
offsetY: number,
|
||||||
|
blur: number
|
||||||
|
};
|
||||||
|
|
||||||
|
const TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){3})/g;
|
||||||
|
const TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
|
||||||
|
|
||||||
|
export const parseTextShadow = (textShadow: string): Array<TextShadow> | null => {
|
||||||
|
if (textShadow === 'none') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shadows = textShadow.match(TEXT_SHADOW_PROPERTY);
|
||||||
|
|
||||||
|
if (!shadows) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shadowList = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < shadows.length; i++) {
|
||||||
|
const shadow = shadows[i].match(TEXT_SHADOW_VALUES);
|
||||||
|
if (shadow) {
|
||||||
|
shadowList.push({
|
||||||
|
color: new Color(shadow[0]),
|
||||||
|
offsetX: shadow[1] ? parseFloat(shadow[1].replace('px', '')) : 0,
|
||||||
|
offsetY: shadow[2] ? parseFloat(shadow[2].replace('px', '')) : 0,
|
||||||
|
blur: shadow[3] ? parseFloat(shadow[3].replace('px', '')) : 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shadowList;
|
||||||
|
};
|
@ -27,6 +27,14 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.white-text-with-blue-shadow {
|
||||||
|
text-shadow: 1px 1px 2px black, 0 0 1em blue, 0 0 0.2em blue;
|
||||||
|
color: white;
|
||||||
|
font: 1.5em Georgia, serif;
|
||||||
|
}
|
||||||
|
.red-text-shadow {
|
||||||
|
text-shadow: 0 -2px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
@ -39,5 +47,11 @@
|
|||||||
<span>testing with transparent</span>
|
<span>testing with transparent</span>
|
||||||
<strong>testing with low opacity</strong>
|
<strong>testing with low opacity</strong>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="white-text-with-blue-shadow">Sed ut perspiciatis unde omnis iste
|
||||||
|
natus error sit voluptatem accusantium doloremque laudantium,
|
||||||
|
totam rem aperiam, eaque ipsa quae ab illo inventore.</p>
|
||||||
|
<p class="red-text-shadow">Sed ut perspiciatis unde omnis iste
|
||||||
|
natus error sit voluptatem accusantium doloremque laudantium,
|
||||||
|
totam rem aperiam, eaque ipsa quae ab illo inventore.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user