Skip to content
This repository has been archived by the owner on Feb 19, 2022. It is now read-only.

Experiment/brush primitives #335

Merged
merged 17 commits into from
Feb 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ export { default as Portal } from "./victory-portal/portal";
export { default as Arc } from "./victory-primitives/arc";
export { default as Area } from "./victory-primitives/area";
export { default as Bar } from "./victory-primitives/bar";
export { default as Border } from "./victory-primitives/border";
export { default as Border, default as Box } from "./victory-primitives/border";
export { default as Candle } from "./victory-primitives/candle";
export { default as ClipPath } from "./victory-primitives/clip-path";
export { default as Curve } from "./victory-primitives/curve";
export { default as ErrorBar } from "./victory-primitives/error-bar";
export { default as Line } from "./victory-primitives/line";
export { default as Axis, default as Grid } from "./victory-primitives/axis";
export { default as Point } from "./victory-primitives/point";
export { default as Slice } from "./victory-primitives/slice";
export { default as Voronoi } from "./victory-primitives/voronoi";
Expand All @@ -39,3 +39,9 @@ export { default as Style } from "./victory-util/style";
export { default as TextSize } from "./victory-util/textsize";
export { default as Timer } from "./victory-util/timer";
export { default as Transitions } from "./victory-util/transitions";
export { default as Rect } from "./victory-primitives/rect";
export { default as Path } from "./victory-primitives/path";
export { default as Line } from "./victory-primitives/line";
export { default as Circle } from "./victory-primitives/circle";
export { default as TSpan } from "./victory-primitives/tspan";
export { default as Text } from "./victory-primitives/text";
100 changes: 73 additions & 27 deletions src/victory-clip-container/victory-clip-container.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React from "react";
import PropTypes from "prop-types";
import CustomPropTypes from "../victory-util/prop-types";
import Helpers from "../victory-util/helpers";
import { assign, defaults, isFunction, isObject, uniqueId } from "lodash";
import ClipPath from "../victory-primitives/clip-path";
import Circle from "../victory-primitives/circle";
import Rect from "../victory-primitives/rect";

export default class VictoryClipContainer extends React.Component {
static displayName = "VictoryClipContainer";
Expand All @@ -12,6 +15,7 @@ export default class VictoryClipContainer extends React.Component {
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
]),
circleComponent: PropTypes.element,
className: PropTypes.string,
clipHeight: CustomPropTypes.nonNegative,
clipId: PropTypes.number,
Expand All @@ -22,6 +26,7 @@ export default class VictoryClipContainer extends React.Component {
clipPathComponent: PropTypes.element,
clipWidth: CustomPropTypes.nonNegative,
events: PropTypes.object,
groupComponent: PropTypes.element,
origin: PropTypes.shape({ x: CustomPropTypes.nonNegative, y: CustomPropTypes.nonNegative }),
polar: PropTypes.bool,
radius: CustomPropTypes.nonNegative,
Expand All @@ -32,7 +37,10 @@ export default class VictoryClipContainer extends React.Component {
}

static defaultProps = {
clipPathComponent: <ClipPath/>
circleComponent: <Circle/>,
rectComponent: <Rect/>,
clipPathComponent: <ClipPath/>,
groupComponent: <g/>
}

constructor(props) {
Expand All @@ -41,45 +49,83 @@ export default class VictoryClipContainer extends React.Component {
uniqueId("victory-clip-") : props.clipId;
}

calculateAttributes(props) {
const {
polar, origin, clipWidth = 0, clipHeight = 0, translateX = 0, translateY = 0
} = props;
const clipPadding = Helpers.getPadding({ padding: props.clipPadding });
const radius = props.radius || Helpers.getRadius(props);
return {
x: (polar ? origin.x : translateX) - clipPadding.left,
y: (polar ? origin.y : translateY) - clipPadding.top,
width: Math.max((polar ? radius : clipWidth) + clipPadding.left + clipPadding.right, 0),
height: Math.max((polar ? radius : clipHeight) + clipPadding.top + clipPadding.bottom, 0)
};
}

// Overridden in victory-core-native
renderClippedGroup(props, clipId) {
const { style, events, transform, children, className } = props;
const { style, events, transform, children, className, groupComponent } = props;
const clipComponent = this.renderClipComponent(props, clipId);
return (
<g
className={className}
style={style}
{...events}
transform={transform}
>
{clipComponent}
<g clipPath={`url(#${clipId})`}>
{children}
</g>
</g>
const clippedGroup = React.cloneElement(
groupComponent, { key: "clipped-group", clipPath: `url(#${clipId})` }, children
);
return React.cloneElement(
groupComponent,
assign({ className, style, transform }, events),
[clipComponent, clippedGroup]
);
// return (
// <g
// className={className}
// style={style}
// {...events}
// transform={transform}
// >
// {clipComponent}
// <g clipPath={`url(#${clipId})`}>
// {children}
// </g>
// </g>
// );
}

// Overridden in victory-core-native
renderGroup(props) {
const { style, events, transform, children, className } = props;
return (
<g
className={className}
style={style}
{...events}
transform={transform}
>
{children}
</g>
const { style, events, transform, children, className, groupComponent } = props;
return React.cloneElement(
groupComponent, assign({ className, style, transform }, events), children
);
}

// Overridden in victory-core-native
renderClipComponent(props, clipId) {
const {
polar, origin, clipWidth = 0, clipHeight = 0, translateX = 0, translateY = 0,
circleComponent, rectComponent, clipPathComponent
} = props;
const { top, bottom, left, right } = Helpers.getPadding({ padding: props.clipPadding });
let child;
if (polar) {
const radius = props.radius || Helpers.getRadius(props);
const circleProps = {
r: Math.max((radius + left + right), (radius + top + bottom), 0),
cx: origin.x - left,
cy: origin.y - top
};
child = React.cloneElement(circleComponent, circleProps);
} else {
const rectProps = {
x: translateX - left, y: translateY - top,
width: Math.max((clipWidth + left + right), 0),
height: Math.max((clipHeight + top + bottom), 0)
};
child = React.cloneElement(rectComponent, rectProps);
}

return React.cloneElement(
props.clipPathComponent,
assign({}, props, { clipId })
clipPathComponent,
assign({ key: "clip-path" }, props, { clipId }),
child
);
}

Expand Down
142 changes: 45 additions & 97 deletions src/victory-label/victory-label.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import React from "react";
import PropTypes from "prop-types";
import VictoryPortal from "../victory-portal/victory-portal";
import CustomPropTypes from "../victory-util/prop-types";
import Collection from "../victory-util/collection";
import Helpers from "../victory-util/helpers";
import LabelHelpers from "../victory-util/label-helpers";
import Style from "../victory-util/style";
import Log from "../victory-util/log";
import TSpan from "../victory-primitives/tspan";
import Text from "../victory-primitives/text";
import { assign, merge, isEmpty } from "lodash";

const defaultStyles = {
Expand Down Expand Up @@ -77,12 +78,14 @@ export default class VictoryLabel extends React.Component {
]),
PropTypes.func
]),
textComponent: PropTypes.element,
title: PropTypes.string,
transform: PropTypes.oneOfType([
PropTypes.string,
PropTypes.object,
PropTypes.func
]),
tspanComponent: PropTypes.element,
verticalAnchor: PropTypes.oneOfType([
PropTypes.oneOf([
"start",
Expand All @@ -102,68 +105,12 @@ export default class VictoryLabel extends React.Component {
};

static defaultProps = {
textComponent: <Text/>,
tspanComponent: <TSpan/>,
capHeight: 0.71, // Magic number from d3.
lineHeight: 1
};

componentWillMount() {
this.cacheAttributes(this.calculateAttributes(this.props));
}

shouldComponentUpdate(nextProps) {
const attrs = this.calculateAttributes(nextProps);
const { style, dx, dy, x, y, content, lineHeight, textAnchor, transform } = attrs;
const { angle, className, datum, active } = this.props;
if (!Collection.allSetsEqual([
[active, nextProps.active],
[angle, nextProps.angle],
[className, nextProps.className],
[x, this.x],
[y, this.y],
[dx, this.dx],
[dy, this.dy],
[lineHeight, this.lineHeight],
[textAnchor, this.textAnchor],
[transform, this.transform],
[content, this.content],
[style, this.style],
[datum, nextProps.datum]
])) {
this.cacheAttributes(attrs);
return true;
}
return false;
}

cacheAttributes(attrs) {
const { style, dx, dy, x, y, content, textAnchor, transform, lineHeight } = attrs;
this.style = style;
this.dx = dx;
this.dy = dy;
this.x = x;
this.y = y;
this.content = content;
this.textAnchor = textAnchor;
this.lineHeight = lineHeight;
this.transform = transform;
}

calculateAttributes(props) {
const style = this.getStyles(props);
const lineHeight = this.getHeight(props, "lineHeight");
const textAnchor = props.textAnchor ?
Helpers.evaluateProp(props.textAnchor, props.datum) : "start";
const content = this.getContent(props);
const dx = props.dx ? Helpers.evaluateProp(props.dx, props.datum) : 0;
const dy = this.getDy(props, style, content, lineHeight);
const transform = this.getTransform(props, style);
const x = typeof props.x !== "undefined" ? props.x : this.getPosition(props, "x");
const y = typeof props.y !== "undefined" ? props.y : this.getPosition(props, "y");
return {
style, dx, dy, content, lineHeight, textAnchor, transform, x, y
};
}

getPosition(props, dimension) {
if (!props.datum) {
return 0;
Expand Down Expand Up @@ -206,7 +153,7 @@ export default class VictoryLabel extends React.Component {
lineHeight = this.checkLineHeight(lineHeight, lineHeight[0], 1);
const fontSize = style.fontSize;
const datum = props.datum || props.data;
const dy = props.dy ? Helpers.evaluateProp(props.dy, datum) : 0;
const dy = props.dy ? Helpers.evaluateProp(props.dy, datum, props.active) : 0;
const length = content.length;
const capHeight = this.getHeight(props, "capHeight");
const verticalAnchor = style.verticalAnchor || props.verticalAnchor;
Expand All @@ -224,22 +171,17 @@ export default class VictoryLabel extends React.Component {

checkLineHeight(lineHeight, val, fallbackVal) {
if (Array.isArray(lineHeight)) {
if (isEmpty(lineHeight)) {
return fallbackVal;
}

return val;
return isEmpty(lineHeight) ? fallbackVal : val;
}

return lineHeight;
}

getTransform(props, style) {
const { datum, x, y, polar } = props;
const { active, datum, x, y, polar } = props;
const defaultAngle = polar ? LabelHelpers.getPolarAngle(props) : 0;
const angle = style.angle || props.angle || defaultAngle;
const transform = props.transform || style.transform;
const transformPart = transform && Helpers.evaluateProp(transform, datum);
const transformPart = transform && Helpers.evaluateProp(transform, datum, active);
const rotatePart = angle && { rotate: [angle, x, y] };
return transformPart || angle ?
Style.toTransformString(transformPart, rotatePart) : undefined;
Expand All @@ -265,35 +207,41 @@ export default class VictoryLabel extends React.Component {

// Overridden in victory-core-native
renderElements(props) {
const textProps = {
dx: this.dx, dy: this.dy, x: this.x, y: this.y,
transform: this.transform, className: props.className
};
return (
<text {...textProps}
{...props.events}
>
{this.props.title && <title>{this.props.title}</title>}
{this.props.desc && <desc>{this.props.desc}</desc>}
{this.content.map((line, i) => {
const style = this.style[i] || this.style[0];
const lastStyle = this.style[i - 1] || this.style[0];
const fontSize = (style.fontSize + lastStyle.fontSize) / 2;
const lineHeight = this.checkLineHeight(
this.lineHeight,
((this.lineHeight[i] + (this.lineHeight[i - 1] || this.lineHeight[0])) / 2),
1
);
const textAnchor = style.textAnchor || this.textAnchor;
const dy = i && !props.inline ? (lineHeight * fontSize) : undefined;
const x = !props.inline ? props.x : undefined;
return (
<tspan key={i} x={x} dy={dy} dx={this.dx} style={style} textAnchor={textAnchor}>
{line}
</tspan>
);
})}
</text>
const { datum, active, inline, className, title, desc, events } = props;
const style = this.getStyles(props);
const lineHeight = this.getHeight(props, "lineHeight");
const textAnchor = props.textAnchor ?
Helpers.evaluateProp(props.textAnchor, datum, active) : "start";
const content = this.getContent(props);
const dx = props.dx ? Helpers.evaluateProp(props.dx, datum, active) : 0;
const dy = this.getDy(props, style, content, lineHeight);
const transform = this.getTransform(props, style);
const x = typeof props.x !== "undefined" ? props.x : this.getPosition(props, "x");
const y = typeof props.y !== "undefined" ? props.y : this.getPosition(props, "y");

const textChildren = content.map((line, i) => {
const currentStyle = style[i] || style[0];
const lastStyle = style[i - 1] || style[0];
const fontSize = (currentStyle.fontSize + lastStyle.fontSize) / 2;
const currentLineHeight = this.checkLineHeight(
lineHeight, ((lineHeight[i] + (lineHeight[i - 1] || lineHeight[0])) / 2), 1
);

const tspanProps = {
key: i,
x: !inline ? props.x : undefined,
dx,
dy: i && !inline ? (currentLineHeight * fontSize) : undefined,
textAnchor: currentStyle.textAnchor || textAnchor,
style: currentStyle,
content: line
};
return React.cloneElement(props.tspanComponent, tspanProps);
});
return React.cloneElement(
props.textComponent,
{ dx, dy, x, y, events, transform, className, title, desc },
textChildren
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/victory-legend/helper-methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export default {
const { x, y, borderPadding, style } = props;
const height = contentHeight + borderPadding.top + borderPadding.bottom;
const width = contentWidth + borderPadding.left + borderPadding.right;
return { x, y, height, width, style: style.border };
return { x, y, height, width, style: assign({ fill: "none" }, style.border) };
},

getDimensions(props, fallbackProps) {
Expand Down
Loading