mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Fix background-clip and background-origin rendering
This commit is contained in:
parent
213f35f61c
commit
52a815a13f
@ -2,6 +2,10 @@
|
||||
'use strict';
|
||||
import Vector from './Vector';
|
||||
|
||||
const lerp = (a: Vector, b: Vector, t: number): Vector => {
|
||||
return new Vector(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t);
|
||||
};
|
||||
|
||||
export default class BezierCurve {
|
||||
start: Vector;
|
||||
startControl: Vector;
|
||||
@ -15,21 +19,16 @@ export default class BezierCurve {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
lerp(a: Vector, b: Vector, t: number): Vector {
|
||||
return new Vector(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t);
|
||||
}
|
||||
|
||||
subdivide(t: number): [BezierCurve, BezierCurve] {
|
||||
const ab = this.lerp(this.start, this.startControl, t);
|
||||
const bc = this.lerp(this.startControl, this.endControl, t);
|
||||
const cd = this.lerp(this.endControl, this.end, t);
|
||||
const abbc = this.lerp(ab, bc, t);
|
||||
const bccd = this.lerp(bc, cd, t);
|
||||
const dest = this.lerp(abbc, bccd, t);
|
||||
return [
|
||||
new BezierCurve(this.start, ab, abbc, dest),
|
||||
new BezierCurve(dest, bccd, cd, this.end)
|
||||
];
|
||||
subdivide(t: number, firstHalf: boolean): BezierCurve {
|
||||
const ab = lerp(this.start, this.startControl, t);
|
||||
const bc = lerp(this.startControl, this.endControl, t);
|
||||
const cd = lerp(this.endControl, this.end, t);
|
||||
const abbc = lerp(ab, bc, t);
|
||||
const bccd = lerp(bc, cd, t);
|
||||
const dest = lerp(abbc, bccd, t);
|
||||
return firstHalf
|
||||
? new BezierCurve(this.start, ab, abbc, dest)
|
||||
: new BezierCurve(dest, bccd, cd, this.end);
|
||||
}
|
||||
|
||||
reverse(): BezierCurve {
|
||||
|
231
src/Bounds.js
231
src/Bounds.js
@ -15,15 +15,18 @@ const RIGHT = 1;
|
||||
const BOTTOM = 2;
|
||||
const LEFT = 3;
|
||||
|
||||
const H = 0;
|
||||
const V = 0;
|
||||
|
||||
export type BoundCurves = {
|
||||
topLeftOuter: [BezierCurve, BezierCurve],
|
||||
topLeftInner: [BezierCurve, BezierCurve],
|
||||
topRightOuter: [BezierCurve, BezierCurve],
|
||||
topRightInner: [BezierCurve, BezierCurve],
|
||||
bottomRightOuter: [BezierCurve, BezierCurve],
|
||||
bottomRightInner: [BezierCurve, BezierCurve],
|
||||
bottomLeftOuter: [BezierCurve, BezierCurve],
|
||||
bottomLeftInner: [BezierCurve, BezierCurve]
|
||||
topLeftOuter: BezierCurve | Vector,
|
||||
topLeftInner: BezierCurve | Vector,
|
||||
topRightOuter: BezierCurve | Vector,
|
||||
topRightInner: BezierCurve | Vector,
|
||||
bottomRightOuter: BezierCurve | Vector,
|
||||
bottomRightInner: BezierCurve | Vector,
|
||||
bottomLeftOuter: BezierCurve | Vector,
|
||||
bottomLeftInner: BezierCurve | Vector
|
||||
};
|
||||
|
||||
export class Bounds {
|
||||
@ -123,6 +126,7 @@ export const parsePathForBorder = (curves: BoundCurves, borderSide: BorderSide):
|
||||
curves.bottomLeftOuter,
|
||||
curves.bottomLeftInner
|
||||
);
|
||||
case LEFT:
|
||||
default:
|
||||
return createPathFromCurves(
|
||||
curves.bottomLeftOuter,
|
||||
@ -134,16 +138,35 @@ export const parsePathForBorder = (curves: BoundCurves, borderSide: BorderSide):
|
||||
};
|
||||
|
||||
const createPathFromCurves = (
|
||||
outer1: [BezierCurve, BezierCurve],
|
||||
inner1: [BezierCurve, BezierCurve],
|
||||
outer2: [BezierCurve, BezierCurve],
|
||||
inner2: [BezierCurve, BezierCurve]
|
||||
outer1: BezierCurve | Vector,
|
||||
inner1: BezierCurve | Vector,
|
||||
outer2: BezierCurve | Vector,
|
||||
inner2: BezierCurve | Vector
|
||||
): Path => {
|
||||
const path = [];
|
||||
path.push(outer1[1]);
|
||||
path.push(outer2[0]);
|
||||
path.push(inner2[0].reverse());
|
||||
path.push(inner1[1].reverse());
|
||||
if (outer1 instanceof BezierCurve) {
|
||||
path.push(outer1.subdivide(0.5, false));
|
||||
} else {
|
||||
path.push(outer1);
|
||||
}
|
||||
|
||||
if (outer2 instanceof BezierCurve) {
|
||||
path.push(outer2.subdivide(0.5, true));
|
||||
} else {
|
||||
path.push(outer2);
|
||||
}
|
||||
|
||||
if (inner2 instanceof BezierCurve) {
|
||||
path.push(inner2.subdivide(0.5, true).reverse());
|
||||
} else {
|
||||
path.push(inner2);
|
||||
}
|
||||
|
||||
if (inner1 instanceof BezierCurve) {
|
||||
path.push(inner1.subdivide(0.5, false).reverse());
|
||||
} else {
|
||||
path.push(inner1);
|
||||
}
|
||||
|
||||
return path;
|
||||
};
|
||||
@ -154,22 +177,40 @@ export const parseBoundCurves = (
|
||||
borderRadius: Array<BorderRadius>
|
||||
): BoundCurves => {
|
||||
// TODO support percentage borderRadius
|
||||
const HALF_WIDTH = bounds.width / 2;
|
||||
const HALF_HEIGHT = bounds.height / 2;
|
||||
const tlh =
|
||||
borderRadius[0][0].value < bounds.width / 2 ? borderRadius[0][0].value : bounds.width / 2;
|
||||
borderRadius[CORNER.TOP_LEFT][H].value < HALF_WIDTH
|
||||
? borderRadius[CORNER.TOP_LEFT][H].value
|
||||
: HALF_WIDTH;
|
||||
const tlv =
|
||||
borderRadius[0][1].value < bounds.height / 2 ? borderRadius[0][1].value : bounds.height / 2;
|
||||
borderRadius[CORNER.TOP_LEFT][V].value < HALF_HEIGHT
|
||||
? borderRadius[CORNER.TOP_LEFT][V].value
|
||||
: HALF_HEIGHT;
|
||||
const trh =
|
||||
borderRadius[1][0].value < bounds.width / 2 ? borderRadius[1][0].value : bounds.width / 2;
|
||||
borderRadius[CORNER.TOP_RIGHT][H].value < HALF_WIDTH
|
||||
? borderRadius[CORNER.TOP_RIGHT][H].value
|
||||
: HALF_WIDTH;
|
||||
const trv =
|
||||
borderRadius[1][1].value < bounds.height / 2 ? borderRadius[1][1].value : bounds.height / 2;
|
||||
borderRadius[CORNER.TOP_RIGHT][V].value < HALF_HEIGHT
|
||||
? borderRadius[CORNER.TOP_RIGHT][V].value
|
||||
: HALF_HEIGHT;
|
||||
const brh =
|
||||
borderRadius[2][0].value < bounds.width / 2 ? borderRadius[2][0].value : bounds.width / 2;
|
||||
borderRadius[CORNER.BOTTOM_RIGHT][H].value < HALF_WIDTH
|
||||
? borderRadius[CORNER.BOTTOM_RIGHT][H].value
|
||||
: HALF_WIDTH;
|
||||
const brv =
|
||||
borderRadius[2][1].value < bounds.height / 2 ? borderRadius[2][1].value : bounds.height / 2;
|
||||
borderRadius[CORNER.BOTTOM_RIGHT][V].value < HALF_HEIGHT
|
||||
? borderRadius[CORNER.BOTTOM_RIGHT][V].value
|
||||
: HALF_HEIGHT;
|
||||
const blh =
|
||||
borderRadius[3][0].value < bounds.width / 2 ? borderRadius[3][0].value : bounds.width / 2;
|
||||
borderRadius[CORNER.BOTTOM_LEFT][H].value < HALF_WIDTH
|
||||
? borderRadius[CORNER.BOTTOM_LEFT][H].value
|
||||
: HALF_WIDTH;
|
||||
const blv =
|
||||
borderRadius[3][1].value < bounds.height / 2 ? borderRadius[3][1].value : bounds.height / 2;
|
||||
borderRadius[CORNER.BOTTOM_LEFT][V].value < HALF_HEIGHT
|
||||
? borderRadius[CORNER.BOTTOM_LEFT][V].value
|
||||
: HALF_HEIGHT;
|
||||
|
||||
const topWidth = bounds.width - trh;
|
||||
const rightHeight = bounds.height - brv;
|
||||
@ -177,58 +218,82 @@ export const parseBoundCurves = (
|
||||
const leftHeight = bounds.height - blv;
|
||||
|
||||
return {
|
||||
topLeftOuter: getCurvePoints(bounds.left, bounds.top, tlh, tlv, CORNER.TOP_LEFT).subdivide(
|
||||
0.5
|
||||
),
|
||||
topLeftInner: getCurvePoints(
|
||||
bounds.left + borders[3].borderWidth,
|
||||
bounds.top + borders[0].borderWidth,
|
||||
Math.max(0, tlh - borders[3].borderWidth),
|
||||
Math.max(0, tlv - borders[0].borderWidth),
|
||||
CORNER.TOP_LEFT
|
||||
).subdivide(0.5),
|
||||
topRightOuter: getCurvePoints(
|
||||
bounds.left + topWidth,
|
||||
bounds.top,
|
||||
trh,
|
||||
trv,
|
||||
CORNER.TOP_RIGHT
|
||||
).subdivide(0.5),
|
||||
topRightInner: getCurvePoints(
|
||||
bounds.left + Math.min(topWidth, bounds.width + borders[3].borderWidth),
|
||||
bounds.top + borders[0].borderWidth,
|
||||
topWidth > bounds.width + borders[3].borderWidth ? 0 : trh - borders[3].borderWidth,
|
||||
trv - borders[0].borderWidth,
|
||||
CORNER.TOP_RIGHT
|
||||
).subdivide(0.5),
|
||||
bottomRightOuter: getCurvePoints(
|
||||
bounds.left + bottomWidth,
|
||||
bounds.top + rightHeight,
|
||||
brh,
|
||||
brv,
|
||||
CORNER.BOTTOM_RIGHT
|
||||
).subdivide(0.5),
|
||||
bottomRightInner: getCurvePoints(
|
||||
bounds.left + Math.min(bottomWidth, bounds.width - borders[3].borderWidth),
|
||||
bounds.top + Math.min(rightHeight, bounds.height + borders[0].borderWidth),
|
||||
Math.max(0, brh - borders[1].borderWidth),
|
||||
brv - borders[2].borderWidth,
|
||||
CORNER.BOTTOM_RIGHT
|
||||
).subdivide(0.5),
|
||||
bottomLeftOuter: getCurvePoints(
|
||||
bounds.left,
|
||||
bounds.top + leftHeight,
|
||||
blh,
|
||||
blv,
|
||||
CORNER.BOTTOM_LEFT
|
||||
).subdivide(0.5),
|
||||
bottomLeftInner: getCurvePoints(
|
||||
bounds.left + borders[3].borderWidth,
|
||||
bounds.top + leftHeight,
|
||||
Math.max(0, blh - borders[3].borderWidth),
|
||||
blv - borders[2].borderWidth,
|
||||
CORNER.BOTTOM_LEFT
|
||||
).subdivide(0.5)
|
||||
topLeftOuter:
|
||||
tlh > 0 || tlv > 0
|
||||
? getCurvePoints(bounds.left, bounds.top, tlh, tlv, CORNER.TOP_LEFT)
|
||||
: new Vector(bounds.left, bounds.top),
|
||||
topLeftInner:
|
||||
tlh > 0 || tlv > 0
|
||||
? getCurvePoints(
|
||||
bounds.left + borders[LEFT].borderWidth,
|
||||
bounds.top + borders[TOP].borderWidth,
|
||||
Math.max(0, tlh - borders[LEFT].borderWidth),
|
||||
Math.max(0, tlv - borders[TOP].borderWidth),
|
||||
CORNER.TOP_LEFT
|
||||
)
|
||||
: new Vector(
|
||||
bounds.left + borders[LEFT].borderWidth,
|
||||
bounds.top + borders[TOP].borderWidth
|
||||
),
|
||||
topRightOuter:
|
||||
trh > 0 || trv > 0
|
||||
? getCurvePoints(bounds.left + topWidth, bounds.top, trh, trv, CORNER.TOP_RIGHT)
|
||||
: new Vector(bounds.left + bounds.width, bounds.top),
|
||||
topRightInner:
|
||||
trh > 0 || trv > 0
|
||||
? getCurvePoints(
|
||||
bounds.left + Math.min(topWidth, bounds.width + borders[LEFT].borderWidth),
|
||||
bounds.top + borders[TOP].borderWidth,
|
||||
topWidth > bounds.width + borders[LEFT].borderWidth
|
||||
? 0
|
||||
: trh - borders[LEFT].borderWidth,
|
||||
trv - borders[TOP].borderWidth,
|
||||
CORNER.TOP_RIGHT
|
||||
)
|
||||
: new Vector(
|
||||
bounds.left + bounds.width - borders[RIGHT].borderWidth,
|
||||
bounds.top + borders[TOP].borderWidth
|
||||
),
|
||||
bottomRightOuter:
|
||||
brh > 0 || brv > 0
|
||||
? getCurvePoints(
|
||||
bounds.left + bottomWidth,
|
||||
bounds.top + rightHeight,
|
||||
brh,
|
||||
brv,
|
||||
CORNER.BOTTOM_RIGHT
|
||||
)
|
||||
: new Vector(bounds.left + bounds.width, bounds.top + bounds.height),
|
||||
bottomRightInner:
|
||||
brh > 0 || brv > 0
|
||||
? getCurvePoints(
|
||||
bounds.left + Math.min(bottomWidth, bounds.width - borders[LEFT].borderWidth),
|
||||
bounds.top + Math.min(rightHeight, bounds.height + borders[TOP].borderWidth),
|
||||
Math.max(0, brh - borders[RIGHT].borderWidth),
|
||||
brv - borders[BOTTOM].borderWidth,
|
||||
CORNER.BOTTOM_RIGHT
|
||||
)
|
||||
: new Vector(
|
||||
bounds.left + bounds.width - borders[RIGHT].borderWidth,
|
||||
bounds.top + bounds.height - borders[BOTTOM].borderWidth
|
||||
),
|
||||
bottomLeftOuter:
|
||||
blh > 0 || blv > 0
|
||||
? getCurvePoints(bounds.left, bounds.top + leftHeight, blh, blv, CORNER.BOTTOM_LEFT)
|
||||
: new Vector(bounds.left, bounds.top + bounds.height),
|
||||
bottomLeftInner:
|
||||
blh > 0 || blv > 0
|
||||
? getCurvePoints(
|
||||
bounds.left + borders[LEFT].borderWidth,
|
||||
bounds.top + leftHeight,
|
||||
Math.max(0, blh - borders[LEFT].borderWidth),
|
||||
blv - borders[BOTTOM].borderWidth,
|
||||
CORNER.BOTTOM_LEFT
|
||||
)
|
||||
: new Vector(
|
||||
bounds.left + borders[LEFT].borderWidth,
|
||||
bounds.top + bounds.height - borders[BOTTOM].borderWidth
|
||||
)
|
||||
};
|
||||
};
|
||||
|
||||
@ -276,11 +341,13 @@ const getCurvePoints = (
|
||||
new Vector(x + ox, ym),
|
||||
new Vector(x, ym)
|
||||
);
|
||||
case CORNER.BOTTOM_LEFT:
|
||||
default:
|
||||
return new BezierCurve(
|
||||
new Vector(xm, ym),
|
||||
new Vector(xm - ox, ym),
|
||||
new Vector(x, y + oy),
|
||||
new Vector(x, y)
|
||||
);
|
||||
}
|
||||
return new BezierCurve(
|
||||
new Vector(xm, ym),
|
||||
new Vector(xm - ox, ym),
|
||||
new Vector(x, y + oy),
|
||||
new Vector(x, y)
|
||||
);
|
||||
};
|
||||
|
@ -16,9 +16,12 @@ import type {ImageStore} from './ImageLoader';
|
||||
import type StackingContext from './StackingContext';
|
||||
|
||||
import {
|
||||
calculateBackgroundSize,
|
||||
BACKGROUND_CLIP,
|
||||
BACKGROUND_ORIGIN,
|
||||
calculateBackgroungPaintingArea,
|
||||
calculateBackgroundPosition,
|
||||
calculateBackgroundRepeatPath
|
||||
calculateBackgroundRepeatPath,
|
||||
calculateBackgroundSize
|
||||
} from './parsing/background';
|
||||
import {BORDER_STYLE} from './parsing/border';
|
||||
import {
|
||||
@ -98,7 +101,20 @@ export default class CanvasRenderer {
|
||||
container.style.borderRadius
|
||||
);
|
||||
|
||||
this.renderBackground(container);
|
||||
const backgroungPaintingArea = calculateBackgroungPaintingArea(
|
||||
curvePoints,
|
||||
container.style.background.backgroundClip
|
||||
);
|
||||
this.path(backgroungPaintingArea);
|
||||
if (!container.style.background.backgroundColor.isTransparent()) {
|
||||
this.ctx.fillStyle = container.style.background.backgroundColor.toString();
|
||||
this.ctx.fill();
|
||||
}
|
||||
|
||||
this.ctx.save();
|
||||
this.ctx.clip();
|
||||
this.renderBackgroundImage(container);
|
||||
this.ctx.restore();
|
||||
container.style.border.forEach((border, side) => {
|
||||
this.renderBorder(border, side, curvePoints);
|
||||
});
|
||||
@ -112,25 +128,6 @@ export default class CanvasRenderer {
|
||||
this.ctx.fillText(text.text, text.bounds.left, text.bounds.top + text.bounds.height);
|
||||
}
|
||||
|
||||
renderBackground(container: NodeContainer) {
|
||||
if (container.bounds.height > 0 && container.bounds.width > 0) {
|
||||
this.renderBackgroundColor(container);
|
||||
this.renderBackgroundImage(container);
|
||||
}
|
||||
}
|
||||
|
||||
renderBackgroundColor(container: NodeContainer) {
|
||||
if (!container.style.background.backgroundColor.isTransparent()) {
|
||||
this.rectangle(
|
||||
container.bounds.left,
|
||||
container.bounds.top,
|
||||
container.bounds.width,
|
||||
container.bounds.height,
|
||||
container.style.background.backgroundColor
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
renderBackgroundImage(container: NodeContainer) {
|
||||
container.style.background.backgroundImage.reverse().forEach(backgroundImage => {
|
||||
if (backgroundImage.source.method === 'url' && backgroundImage.source.args.length) {
|
||||
@ -144,13 +141,33 @@ export default class CanvasRenderer {
|
||||
if (image) {
|
||||
const bounds = container.bounds;
|
||||
const paddingBox = calculatePaddingBox(bounds, container.style.border);
|
||||
const size = calculateBackgroundSize(background, image, bounds);
|
||||
const position = calculateBackgroundPosition(background.position, size, bounds);
|
||||
const path = calculateBackgroundRepeatPath(background, position, size, paddingBox);
|
||||
const backgroundImageSize = calculateBackgroundSize(background, image, bounds);
|
||||
|
||||
// TODO support CONTENT_BOX
|
||||
const backgroundPositioningArea =
|
||||
container.style.background.backgroundOrigin === BACKGROUND_ORIGIN.BORDER_BOX
|
||||
? bounds
|
||||
: paddingBox;
|
||||
|
||||
const position = calculateBackgroundPosition(
|
||||
background.position,
|
||||
backgroundImageSize,
|
||||
backgroundPositioningArea
|
||||
);
|
||||
const path = calculateBackgroundRepeatPath(
|
||||
background,
|
||||
position,
|
||||
backgroundImageSize,
|
||||
backgroundPositioningArea,
|
||||
bounds
|
||||
);
|
||||
this.path(path);
|
||||
const offsetX = Math.round(paddingBox.left + position.x);
|
||||
const offsetY = Math.round(paddingBox.top + position.y);
|
||||
this.ctx.fillStyle = this.ctx.createPattern(this.resizeImage(image, size), 'repeat');
|
||||
this.ctx.fillStyle = this.ctx.createPattern(
|
||||
this.resizeImage(image, backgroundImageSize),
|
||||
'repeat'
|
||||
);
|
||||
this.ctx.translate(offsetX, offsetY);
|
||||
this.ctx.fill();
|
||||
this.ctx.translate(-offsetX, -offsetY);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* @flow */
|
||||
'use strict';
|
||||
|
||||
import type {Bounds} from '../Bounds';
|
||||
import type {Bounds, BoundCurves, Path} from '../Bounds';
|
||||
import type ImageLoader from '../ImageLoader';
|
||||
|
||||
import Color from '../Color';
|
||||
@ -11,9 +11,13 @@ import Vector from '../Vector';
|
||||
|
||||
export type Background = {
|
||||
backgroundImage: Array<BackgroundImage>,
|
||||
backgroundColor: Color
|
||||
backgroundClip: BackgroundClip,
|
||||
backgroundColor: Color,
|
||||
backgroundOrigin: BackgroundOrigin
|
||||
};
|
||||
|
||||
export type BackgroundClip = $Values<typeof BACKGROUND_CLIP>;
|
||||
export type BackgroundOrigin = $Values<typeof BACKGROUND_ORIGIN>;
|
||||
export type BackgroundRepeat = $Values<typeof BACKGROUND_REPEAT>;
|
||||
export type BackgroundSizeTypes = $Values<typeof BACKGROUND_SIZE>;
|
||||
|
||||
@ -44,6 +48,14 @@ export const BACKGROUND_SIZE = {
|
||||
LENGTH: 3
|
||||
};
|
||||
|
||||
export const BACKGROUND_CLIP = {
|
||||
BORDER_BOX: 0,
|
||||
PADDING_BOX: 1,
|
||||
CONTENT_BOX: 2
|
||||
};
|
||||
|
||||
export const BACKGROUND_ORIGIN = BACKGROUND_CLIP;
|
||||
|
||||
const AUTO = 'auto';
|
||||
|
||||
class BackgroundSize {
|
||||
@ -79,8 +91,8 @@ export const calculateBackgroundSize = (
|
||||
const targetRatio = bounds.width / bounds.height;
|
||||
const currentRatio = image.width / image.height;
|
||||
return targetRatio < currentRatio !== (size[0].size === BACKGROUND_SIZE.COVER)
|
||||
? new Size(bounds.height * currentRatio, bounds.height)
|
||||
: new Size(bounds.width, bounds.width / currentRatio);
|
||||
? new Size(bounds.width, bounds.width / currentRatio)
|
||||
: new Size(bounds.height * currentRatio, bounds.height);
|
||||
}
|
||||
|
||||
if (size[0].value) {
|
||||
@ -104,6 +116,30 @@ export const calculateBackgroundSize = (
|
||||
|
||||
const AUTO_SIZE = new BackgroundSize(AUTO);
|
||||
|
||||
export const calculateBackgroungPaintingArea = (
|
||||
curves: BoundCurves,
|
||||
clip: BackgroundClip
|
||||
): Path => {
|
||||
// TODO support CONTENT_BOX
|
||||
switch (clip) {
|
||||
case BACKGROUND_CLIP.BORDER_BOX:
|
||||
return [
|
||||
curves.topLeftOuter,
|
||||
curves.topRightOuter,
|
||||
curves.bottomRightOuter,
|
||||
curves.bottomLeftOuter
|
||||
];
|
||||
case BACKGROUND_CLIP.PADDING_BOX:
|
||||
default:
|
||||
return [
|
||||
curves.topLeftInner,
|
||||
curves.topRightInner,
|
||||
curves.bottomRightInner,
|
||||
curves.bottomLeftInner
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
export const calculateBackgroundPosition = (
|
||||
position: [Length, Length],
|
||||
size: Size,
|
||||
@ -119,59 +155,66 @@ export const calculateBackgroundRepeatPath = (
|
||||
background: BackgroundImage,
|
||||
position: Vector,
|
||||
size: Size,
|
||||
backgroundPositioningArea: Bounds,
|
||||
bounds: Bounds
|
||||
) => {
|
||||
const repeat = background.repeat;
|
||||
switch (repeat) {
|
||||
case BACKGROUND_REPEAT.REPEAT_X:
|
||||
return [
|
||||
new Vector(Math.round(bounds.left), Math.round(bounds.top + position.y)),
|
||||
new Vector(
|
||||
Math.round(bounds.left + bounds.width),
|
||||
Math.round(bounds.top + position.y)
|
||||
Math.round(bounds.left),
|
||||
Math.round(backgroundPositioningArea.top + position.y)
|
||||
),
|
||||
new Vector(
|
||||
Math.round(bounds.left + bounds.width),
|
||||
Math.round(size.height + bounds.top + position.y)
|
||||
Math.round(backgroundPositioningArea.top + position.y)
|
||||
),
|
||||
new Vector(
|
||||
Math.round(bounds.left + bounds.width),
|
||||
Math.round(size.height + backgroundPositioningArea.top + position.y)
|
||||
),
|
||||
new Vector(
|
||||
Math.round(bounds.left),
|
||||
Math.round(size.height + bounds.top + position.y)
|
||||
Math.round(size.height + backgroundPositioningArea.top + position.y)
|
||||
)
|
||||
];
|
||||
case BACKGROUND_REPEAT.REPEAT_Y:
|
||||
return [
|
||||
new Vector(Math.round(bounds.left + position.x), Math.round(bounds.top)),
|
||||
new Vector(
|
||||
Math.round(bounds.left + position.x + size.width),
|
||||
Math.round(backgroundPositioningArea.left + position.x),
|
||||
Math.round(bounds.top)
|
||||
),
|
||||
new Vector(
|
||||
Math.round(bounds.left + position.x + size.width),
|
||||
Math.round(backgroundPositioningArea.left + position.x + size.width),
|
||||
Math.round(bounds.top)
|
||||
),
|
||||
new Vector(
|
||||
Math.round(backgroundPositioningArea.left + position.x + size.width),
|
||||
Math.round(bounds.height + bounds.top)
|
||||
),
|
||||
new Vector(
|
||||
Math.round(bounds.left + position.x),
|
||||
Math.round(backgroundPositioningArea.left + position.x),
|
||||
Math.round(bounds.height + bounds.top)
|
||||
)
|
||||
];
|
||||
case BACKGROUND_REPEAT.NO_REPEAT:
|
||||
return [
|
||||
new Vector(
|
||||
Math.round(bounds.left + position.x),
|
||||
Math.round(bounds.top + position.y)
|
||||
Math.round(backgroundPositioningArea.left + position.x),
|
||||
Math.round(backgroundPositioningArea.top + position.y)
|
||||
),
|
||||
new Vector(
|
||||
Math.round(bounds.left + position.x + size.width),
|
||||
Math.round(bounds.top + position.y)
|
||||
Math.round(backgroundPositioningArea.left + position.x + size.width),
|
||||
Math.round(backgroundPositioningArea.top + position.y)
|
||||
),
|
||||
new Vector(
|
||||
Math.round(bounds.left + position.x + size.width),
|
||||
Math.round(bounds.top + position.y + size.height)
|
||||
Math.round(backgroundPositioningArea.left + position.x + size.width),
|
||||
Math.round(backgroundPositioningArea.top + position.y + size.height)
|
||||
),
|
||||
new Vector(
|
||||
Math.round(bounds.left + position.x),
|
||||
Math.round(bounds.top + position.y + size.height)
|
||||
Math.round(backgroundPositioningArea.left + position.x),
|
||||
Math.round(backgroundPositioningArea.top + position.y + size.height)
|
||||
)
|
||||
];
|
||||
default:
|
||||
@ -192,11 +235,33 @@ export const parseBackground = (
|
||||
imageLoader: ImageLoader
|
||||
): Background => {
|
||||
return {
|
||||
backgroundColor: new Color(style.backgroundColor),
|
||||
backgroundImage: parseBackgroundImages(style, imageLoader),
|
||||
backgroundColor: new Color(style.backgroundColor)
|
||||
backgroundClip: parseBackgroundClip(style.backgroundClip),
|
||||
backgroundOrigin: parseBackgroundOrigin(style.backgroundOrigin)
|
||||
};
|
||||
};
|
||||
|
||||
const parseBackgroundClip = (backgroundClip: string): BackgroundClip => {
|
||||
switch (backgroundClip) {
|
||||
case 'padding-box':
|
||||
return BACKGROUND_CLIP.PADDING_BOX;
|
||||
case 'content-box':
|
||||
return BACKGROUND_CLIP.CONTENT_BOX;
|
||||
}
|
||||
return BACKGROUND_CLIP.BORDER_BOX;
|
||||
};
|
||||
|
||||
const parseBackgroundOrigin = (backgroundOrigin: string): BackgroundOrigin => {
|
||||
switch (backgroundOrigin) {
|
||||
case 'padding-box':
|
||||
return BACKGROUND_ORIGIN.PADDING_BOX;
|
||||
case 'content-box':
|
||||
return BACKGROUND_ORIGIN.CONTENT_BOX;
|
||||
}
|
||||
return BACKGROUND_ORIGIN.BORDER_BOX;
|
||||
};
|
||||
|
||||
const parseBackgroundRepeat = (backgroundRepeat: string): BackgroundRepeat => {
|
||||
switch (backgroundRepeat.trim()) {
|
||||
case 'no-repeat':
|
||||
|
Loading…
x
Reference in New Issue
Block a user