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
|
||||
): ?Gradient => {
|
||||
if (method === 'linear-gradient') {
|
||||
return parseLinearGradient(args, bounds);
|
||||
return parseLinearGradient(args, bounds, !!prefix);
|
||||
} else if (method === 'gradient' && args[0] === 'linear') {
|
||||
// TODO handle correct angle
|
||||
return parseLinearGradient(
|
||||
@ -46,18 +46,23 @@ export const parseGradient = (
|
||||
// $FlowFixMe
|
||||
.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 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 direction = HAS_DIRECTION
|
||||
? 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
|
||||
? parseSideOrCorner(args[0], bounds)
|
||||
: parsePercentageAngle(args[0], bounds)
|
||||
|
@ -30,7 +30,8 @@ import {
|
||||
calculateBackgroungPaintingArea,
|
||||
calculateBackgroundPosition,
|
||||
calculateBackgroundRepeatPath,
|
||||
calculateBackgroundSize
|
||||
calculateBackgroundSize,
|
||||
calculateGradientBackgroundSize
|
||||
} from './parsing/background';
|
||||
import {BORDER_STYLE} from './parsing/border';
|
||||
|
||||
@ -202,12 +203,8 @@ export default class Renderer {
|
||||
container.style.background.backgroundImage.slice(0).reverse().forEach(backgroundImage => {
|
||||
if (backgroundImage.source.method === 'url' && backgroundImage.source.args.length) {
|
||||
this.renderBackgroundRepeat(container, backgroundImage);
|
||||
} else {
|
||||
const gradient = parseGradient(backgroundImage.source, container.bounds);
|
||||
if (gradient) {
|
||||
const bounds = container.bounds;
|
||||
this.target.renderLinearGradient(bounds, gradient);
|
||||
}
|
||||
} else if (/gradient/i.test(backgroundImage.source.method)) {
|
||||
this.renderBackgroundGradient(container, backgroundImage);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -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) {
|
||||
this.target.drawShape(parsePathForBorder(curvePoints, side), border.borderColor);
|
||||
}
|
||||
|
@ -123,6 +123,19 @@ export const calculateBackgroundSize = (
|
||||
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);
|
||||
|
||||
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