added support for gradient background size and fixed linear gradient angle when vendor prefix is used

This commit is contained in:
Matthias Christen
2017-12-09 23:07:27 +01:00
parent 9bc0fb0bd1
commit d1e870de88
4 changed files with 97 additions and 11 deletions

View File

@ -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)

View File

@ -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);
}

View File

@ -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 = (