diff --git a/src/victory-label/victory-label.js b/src/victory-label/victory-label.js index 3ac298e..4943b65 100644 --- a/src/victory-label/victory-label.js +++ b/src/victory-label/victory-label.js @@ -55,6 +55,7 @@ export default class VictoryLabel extends React.Component { origin: PropTypes.shape({ x: CustomPropTypes.nonNegative, y: CustomPropTypes.nonNegative }), polar: PropTypes.bool, renderInPortal: PropTypes.bool, + scale: PropTypes.shape({ x: CustomPropTypes.scale, y: CustomPropTypes.scale }), style: PropTypes.oneOfType([ PropTypes.object, PropTypes.array @@ -109,14 +110,14 @@ export default class VictoryLabel extends React.Component { shouldComponentUpdate(nextProps) { const attrs = this.calculateAttributes(nextProps); - const { style, dx, dy, content, lineHeight, textAnchor, transform } = attrs; - const { angle, className, datum, x, y, active } = this.props; + 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, nextProps.x], - [y, nextProps.y], + [x, this.x], + [y, this.y], [dx, this.dx], [dy, this.dy], [lineHeight, this.lineHeight], @@ -133,10 +134,12 @@ export default class VictoryLabel extends React.Component { } cacheAttributes(attrs) { - const { style, dx, dy, content, textAnchor, transform, lineHeight } = 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; @@ -149,14 +152,24 @@ export default class VictoryLabel extends React.Component { const textAnchor = props.textAnchor ? Helpers.evaluateProp(props.textAnchor, props.datum) : "start"; const content = this.getContent(props); - const dx = props.dx ? Helpers.evaluateProp(this.props.dx, props.datum) : 0; + 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 + style, dx, dy, content, lineHeight, textAnchor, transform, x, y }; } + getPosition(props, dimension) { + if (!props.datum) { + return 0; + } + const scaledPoint = Helpers.scalePoint(props, props.datum); + return scaledPoint[dimension]; + } + getStyle(props, style) { style = style ? merge({}, defaultStyles, style) : defaultStyles; const datum = props.datum || props.data; @@ -238,7 +251,7 @@ export default class VictoryLabel extends React.Component { // Overridden in victory-core-native renderElements(props) { const textProps = { - dx: this.dx, dy: this.dy, x: props.x, y: props.y, + dx: this.dx, dy: this.dy, x: this.x, y: this.y, transform: this.transform, className: props.className }; return ( diff --git a/src/victory-primitives/path-helpers.js b/src/victory-primitives/path-helpers.js index 5d8921c..7c6599d 100644 --- a/src/victory-primitives/path-helpers.js +++ b/src/victory-primitives/path-helpers.js @@ -3,84 +3,95 @@ import { range } from "lodash"; export default { circle(x, y, size) { - const s = Math.floor(size); - return ` - M ${Math.floor(x)}, ${Math.floor(y)} - m ${-s}, 0 - a ${s}, ${s} 0 1,0 ${s * 2},0 - a ${s}, ${s} 0 1,0 ${-s * 2},0 - `; + x = Math.round(x); + y = Math.round(y); + return `M ${x}, ${y} + m ${-size}, 0 + a ${size}, ${size} 0 1,0 ${size * 2},0 + a ${size}, ${size} 0 1,0 ${-size * 2},0`; }, + square(x, y, size) { + x = Math.round(x); + y = Math.round(y); const baseSize = 0.87 * size; // eslint-disable-line no-magic-numbers - const x0 = Math.floor(x - baseSize); - const y1 = Math.floor(y + baseSize); - const distance = Math.abs(x0 - y1); + const x0 = x - baseSize; + const y1 = y + baseSize; + const distance = Math.floor(x + baseSize - x0); return `M ${x0}, ${y1} - h${distance} - v-${distance} - h-${distance} - z`; + h${distance} + v-${distance} + h-${distance} + z`; }, diamond(x, y, size) { + x = Math.round(x); + y = Math.round(y); const baseSize = 0.87 * size; // eslint-disable-line no-magic-numbers const length = Math.sqrt(2 * (baseSize * baseSize)); - const distance = Math.floor(length); - return `M ${Math.floor(x)}, ${Math.floor(y + length)} - l ${distance}, -${distance} - l -${distance}, -${distance} - l -${distance}, ${distance} - l ${distance}, ${distance} + return `M ${x}, ${y + length} + l ${length}, -${length} + l -${length}, -${length} + l -${length}, ${length} + l ${length}, ${length} z`; }, triangleDown(x, y, size) { + x = Math.round(x); + y = Math.round(y); const height = size / 2 * Math.sqrt(3); - const x0 = Math.floor(x - size); - const x1 = Math.floor(x + size); - const y0 = Math.floor(y - size); - const y1 = Math.floor(y + height); + const x0 = x - size; + const x1 = x + size; + const y0 = y - size; + const y1 = y + height; return `M ${x0}, ${y0} - L ${x1}, ${y0} - L ${Math.floor(x)}, ${y1} - z`; + L ${x1}, ${y0} + L ${x}, ${y1} + z`; }, triangleUp(x, y, size) { + x = Math.round(x); + y = Math.round(y); const height = size / 2 * Math.sqrt(3); - const x0 = Math.floor(x - size); - const x1 = Math.floor(x + size); - const y0 = Math.floor(y - height); - const y1 = Math.floor(y + size); + const x0 = x - size; + const x1 = x + size; + const y0 = y - height; + const y1 = y + size; return `M ${x0}, ${y1} - L ${x1}, ${y1} - L ${Math.floor(x)}, ${y0} - z`; + L ${x1}, ${y1} + L ${x}, ${y0} + z`; }, plus(x, y, size) { + x = Math.round(x); + y = Math.round(y); const baseSize = 1.1 * size; // eslint-disable-line no-magic-numbers - const distance = Math.floor(baseSize / 2.5) * 2 || 1; + const distance = baseSize / 1.5; // eslint-disable-line no-magic-numbers return ` - M ${Math.floor(x - baseSize / 2.5)}, ${Math.floor(y + baseSize)} - v-${distance} - h-${distance} - v-${distance} - h${distance} - v-${distance} - h${distance} - v${distance} - h${distance} - v${distance} - h-${distance} - v${distance} - z`; + M ${x - (distance / 2)}, ${y + baseSize} + v-${distance} + h-${distance} + v-${distance} + h${distance} + v-${distance} + h${distance} + v${distance} + h${distance} + v${distance} + h-${distance} + v${distance} + z`; }, star(x, y, size) { - const baseSize = 1.35 * size; // eslint-disable-line no-magic-numbers + x = Math.round(x); + y = Math.round(y); + const baseSize = Math.round(1.35 * size); // eslint-disable-line no-magic-numbers const angle = Math.PI / 5; // eslint-disable-line no-magic-numbers const starCoords = range(10).map((index) => { // eslint-disable-line no-magic-numbers const length = index % 2 === 0 ? baseSize : baseSize / 2; diff --git a/src/victory-primitives/point.js b/src/victory-primitives/point.js index 62bf725..572e42b 100644 --- a/src/victory-primitives/point.js +++ b/src/victory-primitives/point.js @@ -70,7 +70,9 @@ export default class Point extends React.Component { }; const symbol = Helpers.evaluateProp(props.symbol, datum, active); const size = Helpers.evaluateProp(props.size, datum, active); - return pathFunctions[symbol].call(null, x, y, size); + const symbolFunction = typeof pathFunctions[symbol] === "function" ? + pathFunctions[symbol] : pathFunctions.circle; + return symbolFunction(x, y, size); } // Overridden in victory-core-native diff --git a/src/victory-util/helpers.js b/src/victory-util/helpers.js index bbbfcc6..eafd64c 100644 --- a/src/victory-util/helpers.js +++ b/src/victory-util/helpers.js @@ -5,14 +5,14 @@ import React from "react"; export default { getPoint(datum) { const exists = (val) => val !== undefined; - const { _x, _x1, _x0, _voronoiX, _y, _y1, _y0, _voronoiY } = datum; - const defaultX = exists(_x1) ? _x1 : _x; - const defaultY = exists(_y1) ? _y1 : _y; + const { x, _x, _x1, _x0, _voronoiX, y, _y, _y1, _y0, _voronoiY } = datum; + const defaultX = exists(_x1) ? _x1 : _x || x; + const defaultY = exists(_y1) ? _y1 : _y || y; return { x: exists(_voronoiX) ? _voronoiX : defaultX, - x0: exists(_x0) ? _x0 : _x, + x0: exists(_x0) ? _x0 : _x || x, y: exists(_voronoiY) ? _voronoiY : defaultY, - y0: exists(_y0) ? _y0 : _y + y0: exists(_y0) ? _y0 : _y || y }; }, diff --git a/test/client/spec/victory-primitives/path-helper.spec.js b/test/client/spec/victory-primitives/path-helper.spec.js index 1c8f966..bdc9dd3 100644 --- a/test/client/spec/victory-primitives/path-helper.spec.js +++ b/test/client/spec/victory-primitives/path-helper.spec.js @@ -16,7 +16,7 @@ describe("path-helpers", () => { it("draws a path for a square at the correct location", () => { const pathResult = PathHelpers.square(x, y, size); const baseSize = 0.87 * size; - expect(pathResult).to.contain(`M ${Math.floor(x - baseSize)}, ${Math.floor(y + baseSize)}`); + expect(pathResult).to.contain(`M ${x - baseSize}, ${y + baseSize}`); }); }); @@ -47,8 +47,9 @@ describe("path-helpers", () => { it("draws a path for a plus at the correct location", () => { const pathResult = PathHelpers.plus(0, 0, 1); const baseSize = 1.1 * size; + const distance = baseSize / 1.5; expect(pathResult).to.contain( - `M ${Math.floor(x - baseSize / 2.5)}, ${Math.floor(y + baseSize)}` + `M ${(x - (distance / 2))}, ${(y + baseSize)}` ); }); }); @@ -57,8 +58,9 @@ describe("path-helpers", () => { it("draws a path for a star at the correct location", () => { const pathResult = PathHelpers.star(0, 0, 1); const angle = Math.PI / 5; - expect(pathResult).to.contain(`M ${(1.35 * size) * Math.sin(angle) + x }, - ${(1.35 * size) * Math.cos(angle) + y}`); + const baseSize = Math.round(1.35 * size); + expect(pathResult).to.contain(`M ${(baseSize) * Math.sin(angle) + x }, + ${(baseSize) * Math.cos(angle) + y}`); }); }); });