mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
added support for gradient background size and fixed linear gradient angle when vendor prefix is used
This commit is contained in:
parent
9bc0fb0bd1
commit
d1e870de88
@ -34,7 +34,7 @@ export const parseGradient = (
|
|||||||
bounds: Bounds
|
bounds: Bounds
|
||||||
): ?Gradient => {
|
): ?Gradient => {
|
||||||
if (method === 'linear-gradient') {
|
if (method === 'linear-gradient') {
|
||||||
return parseLinearGradient(args, bounds);
|
return parseLinearGradient(args, bounds, !!prefix);
|
||||||
} else if (method === 'gradient' && args[0] === 'linear') {
|
} else if (method === 'gradient' && args[0] === 'linear') {
|
||||||
// TODO handle correct angle
|
// TODO handle correct angle
|
||||||
return parseLinearGradient(
|
return parseLinearGradient(
|
||||||
@ -46,18 +46,23 @@ export const parseGradient = (
|
|||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
.map(v => v[2])
|
.map(v => v[2])
|
||||||
),
|
),
|
||||||
bounds
|
bounds,
|
||||||
|
!!prefix
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseLinearGradient = (args: Array<string>, bounds: Bounds): Gradient => {
|
const parseLinearGradient = (args: Array<string>, bounds: Bounds, hasPrefix: boolean): Gradient => {
|
||||||
const angle = parseAngle(args[0]);
|
const angle = parseAngle(args[0]);
|
||||||
const HAS_SIDE_OR_CORNER = SIDE_OR_CORNER.test(args[0]);
|
const HAS_SIDE_OR_CORNER = SIDE_OR_CORNER.test(args[0]);
|
||||||
const HAS_DIRECTION = HAS_SIDE_OR_CORNER || angle !== null || PERCENTAGE_ANGLES.test(args[0]);
|
const HAS_DIRECTION = HAS_SIDE_OR_CORNER || angle !== null || PERCENTAGE_ANGLES.test(args[0]);
|
||||||
const direction = HAS_DIRECTION
|
const direction = HAS_DIRECTION
|
||||||
? angle !== null
|
? angle !== null
|
||||||
? calculateGradientDirection(angle, bounds)
|
? calculateGradientDirection(
|
||||||
|
// if there is a prefix, the 0° angle points due East (instead of North per W3C)
|
||||||
|
hasPrefix ? angle - Math.PI * 0.5 : angle,
|
||||||
|
bounds
|
||||||
|
)
|
||||||
: HAS_SIDE_OR_CORNER
|
: HAS_SIDE_OR_CORNER
|
||||||
? parseSideOrCorner(args[0], bounds)
|
? parseSideOrCorner(args[0], bounds)
|
||||||
: parsePercentageAngle(args[0], bounds)
|
: parsePercentageAngle(args[0], bounds)
|
||||||
|
@ -30,7 +30,8 @@ import {
|
|||||||
calculateBackgroungPaintingArea,
|
calculateBackgroungPaintingArea,
|
||||||
calculateBackgroundPosition,
|
calculateBackgroundPosition,
|
||||||
calculateBackgroundRepeatPath,
|
calculateBackgroundRepeatPath,
|
||||||
calculateBackgroundSize
|
calculateBackgroundSize,
|
||||||
|
calculateGradientBackgroundSize
|
||||||
} from './parsing/background';
|
} from './parsing/background';
|
||||||
import {BORDER_STYLE} from './parsing/border';
|
import {BORDER_STYLE} from './parsing/border';
|
||||||
|
|
||||||
@ -202,12 +203,8 @@ export default class Renderer {
|
|||||||
container.style.background.backgroundImage.slice(0).reverse().forEach(backgroundImage => {
|
container.style.background.backgroundImage.slice(0).reverse().forEach(backgroundImage => {
|
||||||
if (backgroundImage.source.method === 'url' && backgroundImage.source.args.length) {
|
if (backgroundImage.source.method === 'url' && backgroundImage.source.args.length) {
|
||||||
this.renderBackgroundRepeat(container, backgroundImage);
|
this.renderBackgroundRepeat(container, backgroundImage);
|
||||||
} else {
|
} else if (/gradient/i.test(backgroundImage.source.method)) {
|
||||||
const gradient = parseGradient(backgroundImage.source, container.bounds);
|
this.renderBackgroundGradient(container, backgroundImage);
|
||||||
if (gradient) {
|
|
||||||
const bounds = container.bounds;
|
|
||||||
this.target.renderLinearGradient(bounds, gradient);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -245,6 +242,35 @@ export default class Renderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderBackgroundGradient(container: NodeContainer, background: BackgroundImage) {
|
||||||
|
const backgroundPositioningArea = calculateBackgroungPositioningArea(
|
||||||
|
container.style.background.backgroundOrigin,
|
||||||
|
container.bounds,
|
||||||
|
container.style.padding,
|
||||||
|
container.style.border
|
||||||
|
);
|
||||||
|
const backgroundImageSize = calculateGradientBackgroundSize(
|
||||||
|
background,
|
||||||
|
backgroundPositioningArea
|
||||||
|
);
|
||||||
|
const position = calculateBackgroundPosition(
|
||||||
|
background.position,
|
||||||
|
backgroundImageSize,
|
||||||
|
backgroundPositioningArea
|
||||||
|
);
|
||||||
|
const gradientBounds = new Bounds(
|
||||||
|
Math.round(backgroundPositioningArea.left + position.x),
|
||||||
|
Math.round(backgroundPositioningArea.top + position.y),
|
||||||
|
backgroundImageSize.width,
|
||||||
|
backgroundImageSize.height
|
||||||
|
);
|
||||||
|
|
||||||
|
const gradient = parseGradient(background.source, gradientBounds);
|
||||||
|
if (gradient) {
|
||||||
|
this.target.renderLinearGradient(gradientBounds, gradient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderBorder(border: Border, side: BorderSide, curvePoints: BoundCurves) {
|
renderBorder(border: Border, side: BorderSide, curvePoints: BoundCurves) {
|
||||||
this.target.drawShape(parsePathForBorder(curvePoints, side), border.borderColor);
|
this.target.drawShape(parsePathForBorder(curvePoints, side), border.borderColor);
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,19 @@ export const calculateBackgroundSize = (
|
|||||||
return new Size(width, height);
|
return new Size(width, height);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const calculateGradientBackgroundSize = (
|
||||||
|
backgroundImage: BackgroundImage,
|
||||||
|
bounds: Bounds
|
||||||
|
): Size => {
|
||||||
|
const size = backgroundImage.size;
|
||||||
|
const width = size[0].value ? size[0].value.getAbsoluteValue(bounds.width) : bounds.width;
|
||||||
|
const height = size[1].value
|
||||||
|
? size[1].value.getAbsoluteValue(bounds.height)
|
||||||
|
: size[0].value ? width : bounds.height;
|
||||||
|
|
||||||
|
return new Size(width, height);
|
||||||
|
};
|
||||||
|
|
||||||
const AUTO_SIZE = new BackgroundSize(AUTO);
|
const AUTO_SIZE = new BackgroundSize(AUTO);
|
||||||
|
|
||||||
export const calculateBackgroungPaintingArea = (
|
export const calculateBackgroungPaintingArea = (
|
||||||
|
42
tests/reftests/background/linear-gradient2.html
Normal file
42
tests/reftests/background/linear-gradient2.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Background attribute tests</title>
|
||||||
|
<script type="text/javascript" src="../../test.js"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: blanchedalmond;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
padding: 10px;
|
||||||
|
border: 15px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="background: -webkit-linear-gradient(90deg, blue, red);"></div>
|
||||||
|
<div style="background: linear-gradient(90deg, blue, red);"></div>
|
||||||
|
<div style="background: linear-gradient(45deg, blue, red);"></div>
|
||||||
|
<div style="background: linear-gradient(45deg, blue, red); width:200px;"></div>
|
||||||
|
<div style="background-image: linear-gradient(45deg, blue, red); background-position: 20px 30px; background-size: 60px; background-repeat: no-repeat"></div>
|
||||||
|
<div style="background-image: linear-gradient(45deg, blue, red); background-position: 20px 30px; background-size: 60px;"></div>
|
||||||
|
<div style="background-image: linear-gradient(45deg, blue, red);padding:0"></div>
|
||||||
|
<div style="background: linear-gradient(red, red 60%, blue);"></div>
|
||||||
|
<div style="background: linear-gradient(90deg, red 60%, blue);"></div>
|
||||||
|
<div style="background: linear-gradient(135deg, red, red 60%, blue);"></div>
|
||||||
|
<div style="background: linear-gradient(to right, red, red 60%, blue);"></div>
|
||||||
|
<div style="background: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet);"></div>
|
||||||
|
<div style="background: linear-gradient(60deg, yellow 0%, orange 10%, red 50%, blue 90%, cyan 100%);"></div>
|
||||||
|
<div style="background: linear-gradient(45deg, yellow 0%, orange 10%, red 50%, blue 90%, cyan 100%); background-origin: content-box"></div>
|
||||||
|
<div style="background: linear-gradient(90deg, yellow 0%, orange 10%, red 50%, blue 90%, cyan 100%); background-origin: padding-box"></div>
|
||||||
|
<div style="background: linear-gradient(90deg, yellow 0%, orange 10%, red 50%, blue 90%, cyan 100%); background-origin: border-box"></div>
|
||||||
|
<div style="background: linear-gradient(to right, rgba(255,255,255,0) 0%,rgba(255,255,255,1) 100%); "></div>
|
||||||
|
<div style="background: linear-gradient(90deg, yellow 0%, orange 10%, red 50%, blue 90%, cyan 100%) content-box;"></div>
|
||||||
|
<div style="background: linear-gradient(60deg, hsla(120,80%,50%,0.8) 0%, transparent 50%, rgba(255,100,100,0.5) 100%);"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user