diff --git a/docs/.vuepress/components/Cartesian.vue b/docs/.vuepress/components/Cartesian.vue
new file mode 100644
index 00000000..69e26a4a
--- /dev/null
+++ b/docs/.vuepress/components/Cartesian.vue
@@ -0,0 +1,145 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/.vuepress/components/SymbolMarkDemo.vue b/docs/.vuepress/components/SymbolMarkDemo.vue
index 4bbfbfa9..e897210a 100644
--- a/docs/.vuepress/components/SymbolMarkDemo.vue
+++ b/docs/.vuepress/components/SymbolMarkDemo.vue
@@ -21,11 +21,23 @@
:size="16"
:shape="shape"
:stroke="stroke"
- :fill="fill"
+ :fill="fill(row.explanatory)"
:stroke-width="1"
/>
+
+
+
+
+
-
-
-
-
@@ -100,14 +96,6 @@ export default {
},
computed : {
- fill () {
- if (this.color === 'both' || this.color === 'fill') {
- return { scale: { scale: 'viridis', variable: 'explanatory' } }
- } else {
- return 'none'
- }
- },
-
stroke () {
if (this.color === 'both' || this.color === 'stroke') {
return 'black'
@@ -133,7 +121,15 @@ export default {
return newData
- }
+ },
+
+ fill (value) {
+ if (this.color === 'both' || this.color === 'fill') {
+ return { val: value, scale: { type: 'viridis', domain: 'explanatory' } }
+ } else {
+ return 'none'
+ }
+ },
}
}
diff --git a/docs/axes/cartesian.md b/docs/axes/cartesian.md
index 245505f8..cdf45089 100644
--- a/docs/axes/cartesian.md
+++ b/docs/axes/cartesian.md
@@ -2,27 +2,116 @@
title: Cartesian Axes
---
-# Cartesian Axes
+# Component tag
-
-
-
+``
-The standard axis takes the following props:
+``
-Prop | Required | Default | Description
-----------|----------|-----------|----------------------------
- | | |
-
+# Description
-
+Axes are used as reference scales for values in the graph. Each axis is typically mapped to a single dimension or variable.
-### Axis Domain
+# Props
-### Multi-axis
+| Prop | Required | Regular types | Default | Description |
+| ------ | -------- | ----------------------- | --------- | --------------------------------------------------------- |
+| scale | true | [Array, String, Object] | undefined | range of values covered by the axis, can be variable name |
+| flip | false | [Boolean] | false | direction of tick and axis labels |
-### Gridlines
+### X Axis Positioning
-### Format Tick Values
+There are three options for positioning the x axis on the graph. The default position of the x-axis is at `vjust = 'b'` (bottom of parent section).
-### Custom Ticks
\ No newline at end of file
+When using `vjust`, the x axis defaults to a height of 100px in screen coordinates.
+
+| Prop | Required | Regular types | Default | Description | Unit(s) |
+| ---- | -------- | ---------------- | --------- | --------------------------------------- | ---------------------- |
+| vjust| false | [Number, String] | 'b' | position of x axis | Number between 0 and 1 |
+| y | false | [Number] | undefined | position of x axis | Local Coordinates |
+| h | false | [Number] | undefined | height of x axis | Local Coordinates |
+| y1 | false | [Number] | undefined | starting y coordinate of x axis | Local Coordinates |
+| y2 | false | [Number] | undefined | ending y coordinate of x axis | Local Coordinates |
+
+By default the x axis spans the entire width of the section. To customize the width of the x axis, it is possible to provide `x1` and `x2` as start and end coordinates.
+
+| Prop | Required | Regular types | Default | Description | Unit(s) |
+| ---- | -------- | ---------------- | --------- | --------------------------------------- | --------------------- |
+| x1 | false | [Number] | undefined | starting x coordinate of x axis | Local Coordinates |
+| x2 | false | [Number] | undefined | ending x coordinate of x axis | Local Coordinates |
+
+
+
+### Y Axis Positioning
+
+Similar to the x axis, there are three options for positioning the y axis on the graph. The default position of the y-axis is at `hjust = 'l'` (left of parent section).
+
+When using `hjust`, the y axis defaults to a width of 100px in screen coordinates.
+
+| Prop | Required | Regular types | Default | Description | Unit(s) |
+| ---- | -------- | ---------------- | --------- | --------------------------------------- | ---------------------- |
+| hjust| false | [Number, String] | 'l' | position of y axis | Number between 0 and 1 |
+| x | false | [Number] | undefined | position of y axis | Local Coordinates |
+| w | false | [Number] | undefined | width of y axis | Local Coordinates |
+| x1 | false | [Number] | undefined | starting x coordinate of y axis | Local Coordinates |
+| x2 | false | [Number] | undefined | ending x coordinate of y axis | Local Coordinates |
+
+By default the y axis spans the entire height of the section. To customize the height of the y axis, it is possible to provide `y1` and `y2` as start and end coordinates.
+
+| Prop | Required | Regular types | Default | Description | Unit(s) |
+| ---- | -------- | ---------------- | --------- | --------------------------------------- | --------------------- |
+| y1 | false | [Number] | undefined | starting y coordinate of y axis | Local Coordinates |
+| y2 | false | [Number] | undefined | ending y coordinate of y axis | Local Coordinates |
+
+
+
+### Main Line
+
+| Prop | Required | Regular types | Default | Description | Unit(s) |
+| -------------- | -------- | ---------------- | --------- | --------------------------------------- | -------------------------- |
+| domain | false | [Boolean] | true | if true render axis main line | |
+| domainColor | false | [String] | 'black' | color of main line | Named color, hex, rgb, hsl |
+| domainOpacity | false | [Number] | 1 | opacity of main line | Number between 0 and 1 |
+| domainWidth | false | [Number] | 1 | stroke width of main line | Screen pixels |
+
+### Labels
+
+Note that if a `Function` is passed to the `format` prop to format labels before rendering, the function output must be of type `String`
+
+| Prop | Required | Regular types | Default | Description | Unit(s) |
+| -------------- | -------- | ------------------ | ----------- | --------------------------------------- | -------------------------- |
+| labels | false | [Boolean] | true | if true render labels | |
+| format | false | [String, Function] | undefined | formatting of axis labels | |
+| labelColor | false | [String] | 'black' | color of labels | Named color, hex, rgb, hsl |
+| labelFont | false | [String] | 'Helvetica' | font used for axis labels | Named font |
+| labelFontSize | false | [Number] | 10 | size of font used for axis labels | Screen pixels |
+| labelFontWeight| false | [String, Number] | 'normal' | weight of font used for axis labels | Any valid css font weight |
+| labelOpacity | false | [Number] | 1 | opacity of labels | Number between 0 and 1 |
+| labelRotate | false | [Boolean] | false | if true rotate labels | Degrees |
+
+### Ticks
+
+| Prop | Required | Regular types | Default | Description | Unit(s) |
+| -------------- | -------- | ---------------- | ----------- | ---------------------------------------------- | -------------------------- |
+| ticks | false | [Boolean] | true | if true render ticks | |
+| tickColor | false | [String] | 'black' | color of ticks | Named color, hex, rgb, hsl |
+| tickValues | false | [Array] | undefined | custom tick positions | |
+| tickCount | false | [Number] | 10 | number of ticks on the axis, equal intervals | |
+| tickExtra | false | [Boolean] | true | if true, render extra tick at axis origin | |
+| tickOpacity | false | [Number] | 1 | opacity of ticks | Number between 0 and 1 |
+| tickSize | false | [Number] | 7 | length of ticks | Screen pixels |
+| tickWidth | false | [Number] | 0.5 | stroke width of ticks | Screen pixels |
+
+### Title
+
+| Prop | Required | Regular types | Default | Description | Unit(s) |
+| --------------- | -------- | ---------------- | ----------- | --------------------------------------- | -------------------------- |
+| titleHjust | false | [String, Number] | depends | position of axis title relative to axis; default -0.08 for x-axis; default 'center' for y-axis | Number between 0 and 1 |
+| titleVjust | false | [String, Number] | depends | position of axis title relative to axis; default 'center' for x-axis; default 1.05 for y-axis | Number between 0 and 1 |
+| title | false | [String] | '' | text to render as axis title | |
+| titleAnchorPoint| false | [String] | 'center' | baseline and alignment of title text | |
+| titleColor | false | [String] | 'black' | color of title | Named color, hex, rgb, hsl |
+| titleFont | false | [String] | 'Helvetica' | font used for axis title | Named font |
+| titleFontSize | false | [Number] | 12 | size of font used for axis title | Screen pixels |
+| titleFontWeight | false | [String, Number] | 'normal' | weight of font used for axis title | Any valid css font weight |
+| titleOpacity | false | [Number] | 1 | opacity of title | Number between 0 and 1 |
\ No newline at end of file
diff --git a/docs/marks/symbol.md b/docs/marks/symbol.md
index b56196f0..87d3292b 100644
--- a/docs/marks/symbol.md
+++ b/docs/marks/symbol.md
@@ -4,6 +4,8 @@ title: Symbol Mark
# Component tag
+``
+
``
# Description
diff --git a/src/classes/CoordinateTree/CoordinateTransformation.js b/src/classes/CoordinateTree/CoordinateTransformation.js
index a56129fa..1dc369a8 100644
--- a/src/classes/CoordinateTree/CoordinateTransformation.js
+++ b/src/classes/CoordinateTree/CoordinateTransformation.js
@@ -72,13 +72,17 @@ export default class CoordinateTransformation {
// before we actually use $$transform. This is necessary in a few cases.
if (['categorical', 'temporal'].includes(this.domainTypes.x)) {
this.getX = x => x.constructor === Number ? x : this.scaleX(x)
+ this.invertX = x => x.constructor === Number ? x : this.scaleX.invert(x)
} else {
this.getX = this.scaleX
+ this.invertX = this.scaleX.invert
}
if (['categorical', 'temporal'].includes(this.domainTypes.y)) {
this.getY = y => y.constructor === Number ? y : this.scaleY(y)
+ this.invertY = y => y.constructor === Number ? y : this.scaleY.invert(y)
} else {
this.getY = this.scaleY
+ this.invertY = this.scaleY.invert
}
if (options.type === 'scale') {
@@ -128,6 +132,9 @@ export default class CoordinateTransformation {
this.getX = this.scaleX
this.getY = this.scaleY
+ this.invertX = this.scaleX.invert
+ this.invertY = this.scaleY.invert
+
this.transform = ([x, y]) => {
return [this.getX(x), this.getY(y)]
}
diff --git a/src/classes/CoordinateTree/CoordinateTree.js b/src/classes/CoordinateTree/CoordinateTree.js
index d98af56a..1d39d97f 100644
--- a/src/classes/CoordinateTree/CoordinateTree.js
+++ b/src/classes/CoordinateTree/CoordinateTree.js
@@ -73,6 +73,42 @@ export default class CoordinateTree {
return transformation.bind(this)
}
+
+ getLocalX (id) {
+ let transformation = function (x) {
+ let branchParents = this._branchPaths[id]
+ let result = x
+
+ if (branchParents == undefined) {return result}
+
+ for (let i = 0; i < branchParents.length; i++) {
+ let currentLocation = this.getBranch(branchParents[i])
+ result = currentLocation.invertX(result)
+ }
+
+ return result
+ }
+
+ return transformation.bind(this)
+ }
+
+ getLocalY (id) {
+ let transformation = function (y) {
+ let branchParents = this._branchPaths[id]
+ let result = y
+
+ if (branchParents == undefined) {return result}
+
+ for (let i = 0; i < branchParents.length; i++) {
+ let currentLocation = this.getBranch(branchParents[i])
+ result = currentLocation.invertY(result)
+ }
+
+ return result
+ }
+
+ return transformation.bind(this)
+ }
}
class Branch {
diff --git a/src/components/Core/Section.vue b/src/components/Core/Section.vue
index 30b2e902..fa05f15c 100644
--- a/src/components/Core/Section.vue
+++ b/src/components/Core/Section.vue
@@ -147,11 +147,11 @@ export default {
id = '_' + randomID()
}
return id
- }
+ },
},
watch: {
- transformation: 'updateCoordinateTreeBranch'
+ transformation: 'updateCoordinateTreeBranch',
},
beforeDestroy () {
@@ -194,8 +194,9 @@ export default {
provide () {
let $$transform = this.$$coordinateTree.getTotalTransformation(this.coordinateTreeBranchID)
let $$coordinateTreeParent = this.coordinateTreeBranchID
-
- return { $$transform, $$coordinateTreeParent }
+ let $$getLocalX = this.$$coordinateTree.getLocalX(this.coordinateTreeBranchID)
+ let $$getLocalY = this.$$coordinateTree.getLocalY(this.coordinateTreeBranchID)
+ return { $$transform, $$coordinateTreeParent, $$getLocalX, $$getLocalY }
},
render (createElement) {
diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue
index 98cf5b2d..7ff72ef1 100644
--- a/src/components/Guides/XAxis.vue
+++ b/src/components/Guides/XAxis.vue
@@ -11,16 +11,35 @@
+
+
+
@@ -78,6 +108,103 @@
import BaseAxis from '../../mixins/Guides/BaseAxis.js'
export default {
- mixins: [BaseAxis]
+ mixins: [BaseAxis],
+
+ props: {
+ titleHjust: {
+ default: -0.08
+ },
+
+ titleVjust: {
+ default: 'center'
+ }
+ },
+
+ computed: {
+ titlePosX () {
+ if (this.titleHjust === 'center') {
+ return 0.5
+ } else if (this.titleHjust === 'l') {
+ return 0
+ } else if (this.titleHjust === 'r') {
+ return 1
+ } else {
+ return this.titleHjust
+ }
+ },
+
+ titlePosY () {
+ if (this.titleVjust === 'center') {
+ return 0.5
+ } else if (this.titleVjust === 't') {
+ return 1
+ } else if (this.titleVjust === 'b') {
+ return 0
+ } else {
+ return this.titleVjust
+ }
+ },
+
+ tickMin () {
+ let localTickSize = this.getLocalY(this.tickSize) - this.getLocalY(0)
+ let scaledSize = localTickSize / (this.ranges.y2 - this.ranges.y1)
+ return 0.5 - scaledSize
+ },
+
+ tickMax () {
+ let localTickSize = this.getLocalY(this.tickSize) - this.getLocalY(0)
+ let scaledSize = localTickSize / (this.ranges.y2 - this.ranges.y1)
+ return 0.5 + scaledSize
+ },
+
+ posY () {
+ if (this.validY) {
+ return [this.coords.y1, this.coords.y2]
+ }
+
+ let yDomain = this.yDomain
+
+ let yDomainMin = Math.min(yDomain[0], yDomain[1])
+ let yDomainMax = Math.max(yDomain[0], yDomain[1])
+
+ let yHeight = this.getLocalY(50) - this.getLocalY(0)
+
+ if (this.vjust.constructor === Number) {
+ let scaledVal = (yDomainMax - yDomainMin) * this.vjust + yDomainMin
+ return [scaledVal - yHeight, scaledVal + yHeight]
+ } else if (this.vjust === 'center') {
+ let centerVal = (yDomainMax - yDomainMin) / 2 + yDomainMin
+ return [centerVal - yHeight, centerVal + yHeight]
+ } else if (this.vjust === 't') {
+ return [yDomainMax - yHeight, yDomainMax + yHeight]
+ } else {
+ return [yDomainMin - yHeight, yDomainMin + yHeight]
+ }
+ },
+
+ ranges () {
+ let newRange = {}
+
+ newRange.y1 = this.posY[0]
+ newRange.y2 = this.posY[1]
+
+ if (this.validX) {
+ newRange.x1 = this.coords.x1
+ newRange.x2 = this.coords.x2
+
+ return newRange
+ }
+
+ if (this._domainType === 'temporal') {
+ newRange.x1 = this._domain[0]
+ newRange.x2 = this._domain[1]
+ } else {
+ newRange.x1 = this.xDomain[0]
+ newRange.x2 = this.xDomain[1]
+ }
+
+ return newRange
+ },
+ }
}
diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue
index 94dbe5fd..be95ffec 100644
--- a/src/components/Guides/YAxis.vue
+++ b/src/components/Guides/YAxis.vue
@@ -11,12 +11,30 @@
+
+
+
@@ -39,31 +57,42 @@
@@ -79,6 +108,103 @@
import BaseAxis from '../../mixins/Guides/BaseAxis.js'
export default {
- mixins: [BaseAxis]
+ mixins: [BaseAxis],
+
+ props: {
+ titleHjust: {
+ default: 'center'
+ },
+
+ titleVjust: {
+ default: 1.08
+ }
+ },
+
+ computed: {
+ titlePosX () {
+ if (this.titleHjust === 'center') {
+ return 0.5
+ } else if (this.titleHjust === 'l') {
+ return 0
+ } else if (this.titleHjust === 'r') {
+ return 1
+ } else {
+ return this.titleHjust
+ }
+ },
+
+ titlePosY () {
+ if (this.titleVjust === 'center') {
+ return 0.5
+ } else if (this.titleVjust === 't') {
+ return 1
+ } else if (this.titleVjust === 'b') {
+ return 0
+ } else {
+ return this.titleVjust
+ }
+ },
+
+ tickMin () {
+ let localTickSize = this.getLocalX(this.tickSize) - this.getLocalX(0)
+ let scaledSize = localTickSize / (this.ranges.x2 - this.ranges.x1)
+ return 0.5 - scaledSize
+ },
+
+ tickMax () {
+ let localTickSize = this.getLocalX(this.tickSize) - this.getLocalX(0)
+ let scaledSize = localTickSize / (this.ranges.x2 - this.ranges.x1)
+ return 0.5 + scaledSize
+ },
+
+ posX () {
+ if (this.validX) {
+ return [this.coords.x1, this.coords.x2]
+ }
+
+ let xDomain = this.xDomain
+
+ let xDomainMin = Math.min(xDomain[0], xDomain[1])
+ let xDomainMax = Math.max(xDomain[0], xDomain[1])
+
+ let xWidth = this.getLocalX(50) - this.getLocalX(0)
+
+ if (this.hjust.constructor === Number) {
+ let scaledVal = (xDomainMax - xDomainMin) * this.hjust + xDomainMin
+ return [scaledVal - xWidth, scaledVal + xWidth]
+ } else if (this.hjust === 'center') {
+ let centerVal = (xDomainMax - xDomainMin) / 2 + xDomainMin
+ return [centerVal - xWidth, centerVal + xWidth]
+ } else if (this.hjust === 'l') {
+ return [xDomainMin - xWidth, xDomainMin + xWidth]
+ } else {
+ return [xDomainMax - xWidth, xDomainMax + xWidth]
+ }
+ },
+
+ ranges () {
+ let newRange = {}
+
+ newRange.x1 = this.posX[0]
+ newRange.x2 = this.posX[1]
+
+ if (this.validY) {
+ newRange.y1 = this.coords.y1
+ newRange.y2 = this.coords.y2
+
+ return newRange
+ }
+
+ if (this._domainType === 'temporal') {
+ newRange.y1 = this._domain[0]
+ newRange.y2 = this._domain[1]
+ } else {
+ newRange.y1 = this.yDomain[0]
+ newRange.y2 = this.yDomain[1]
+ }
+
+ return newRange
+ },
+ }
}
diff --git a/src/components/Marks/Label.vue b/src/components/Marks/Label.vue
index 6d258cb0..30138cf2 100644
--- a/src/components/Marks/Label.vue
+++ b/src/components/Marks/Label.vue
@@ -51,11 +51,21 @@ export default {
default: undefined
},
+ fontFamily: {
+ type: String,
+ default: 'Helvetica'
+ },
+
fontSize: {
type: Number,
default: 16
},
+ fontWeight: {
+ type: [String, Number],
+ default: 'normal'
+ },
+
rotation: {
type: Number,
default: 0
@@ -91,6 +101,8 @@ export default {
let styles = this.createSVGStyle(aesthetics)
styles['fontSize'] = aesthetics.fontSize + 'px'
+ styles['font-family'] = this.fontFamily
+ styles['font-weight'] = this.fontWeight
let el = createElement('text', {
attrs: {
@@ -110,9 +122,3 @@ export default {
}
}
-
-
diff --git a/src/mixins/CoordinateSystem.js b/src/mixins/CoordinateSystem.js
index e867bfdd..6004a218 100644
--- a/src/mixins/CoordinateSystem.js
+++ b/src/mixins/CoordinateSystem.js
@@ -61,7 +61,9 @@ export default {
let $$coordinateTree = this.coordinateTree
let $$transform = this.coordinateTree.getTotalTransformation('root')
let $$coordinateTreeParent = 'root'
+ let $$getLocalX = this.coordinateTree.getLocalX(this.coordinateTreeBranchID)
+ let $$getLocalY = this.coordinateTree.getLocalY(this.coordinateTreeBranchID)
- return { $$coordinateTree, $$transform, $$coordinateTreeParent }
+ return { $$coordinateTree, $$transform, $$coordinateTreeParent, $$getLocalX, $$getLocalY }
}
}
diff --git a/src/mixins/CoordinateTreeUser.js b/src/mixins/CoordinateTreeUser.js
index b173eb9b..893b9d32 100644
--- a/src/mixins/CoordinateTreeUser.js
+++ b/src/mixins/CoordinateTreeUser.js
@@ -2,14 +2,24 @@ export default {
inject: ['$$coordinateTree', '$$coordinateTreeParent'],
data () {
- return {
- parentBranch: this.$$coordinateTree.getBranch(this.$$coordinateTreeParent)
- }
+ return {
+ parentBranch: this.$$coordinateTree.getBranch(this.$$coordinateTreeParent)
+ }
},
computed: {
parentRangeTypes () {
return this.parentBranch.domainTypes
- }
+ },
+ },
+
+ watch: {
+ $$transform: 'getParent'
+ },
+
+ methods: {
+ getParent () {
+ this.parentBranch = this.$$coordinateTree.getBranch(this.$$coordinateTreeParent)
+ }
}
}
diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js
index 5ae5e801..a5d0f8b7 100644
--- a/src/mixins/Guides/BaseAxis.js
+++ b/src/mixins/Guides/BaseAxis.js
@@ -15,9 +15,116 @@ export default {
props: {
scale: {
type: [Array, String, Object, undefined],
+ default: undefined,
+ required: true
+ },
+
+ format: {
+ type: [String, Function, undefined],
default: undefined
},
+ flip: {
+ type: Boolean,
+ default: false
+ },
+
+ hjust: {
+ type: [Number, String],
+ default: 'l',
+ validator: function (p) {
+ return (p.constructor === Number) || (['center', 'l', 'r'].includes(p))
+ }
+ },
+
+ vjust: {
+ type: [Number, String],
+ default: 'b',
+ validator: function (p) {
+ return (p.constructor === Number) || (['center', 't', 'b'].includes(p))
+ }
+ },
+
+ // STYLING OPTIONS //
+
+ // If true render axis main line
+ domain: {
+ type: Boolean,
+ default: true
+ },
+
+ domainColor: {
+ type: String,
+ default: 'black'
+ },
+
+ domainOpacity: {
+ type: Number,
+ default: 1
+ },
+
+ domainWidth: {
+ type: Number,
+ default: 1
+ },
+
+ labels: {
+ type: Boolean,
+ default: true
+ },
+
+ // hide labels that exceed axis range
+ // labelBound: {
+ // type: Boolean,
+ // default: false
+ // },
+
+ labelColor: {
+ type: String,
+ default: 'black'
+ },
+
+ labelFont: {
+ type: String,
+ default: 'Helvetica'
+ },
+
+ labelFontSize: {
+ type: Number,
+ default: 10
+ },
+
+ labelFontWeight: {
+ type: [String, Number],
+ default: 'normal'
+ },
+
+ labelOpacity: {
+ type: Number,
+ default: 1
+ },
+
+ // Distance between tick and label **
+ // labelPadding: {
+ // type: Number,
+ // default: 0
+ // },
+
+ labelRotate: {
+ type: Boolean,
+ default: false
+ },
+
+ ticks: {
+ type: Boolean,
+ default: true
+ },
+
+ tickColor: {
+ type: String,
+ default: 'black'
+ },
+
tickValues: {
type: [Array, undefined],
default: undefined
@@ -28,20 +135,86 @@ export default {
default: 10
},
- rotateLabel: {
+ tickExtra: {
+ type: Boolean,
+ default: true
+ },
+
+ tickExtraLabel: {
type: Boolean,
default: false
},
- format: {
- type: [String, Function, undefined],
- default: undefined
+ tickOpacity: {
+ type: Number,
+ default: 1
+ },
+
+ tickSize: {
+ type: Number,
+ default: 7
},
- flip: {
- type: Boolean,
- default: false
+ tickWidth: {
+ type: Number,
+ default: 0.5
+ },
+
+ title: {
+ type: String,
+ default: ''
+ },
+
+ titleAnchorPoint: {
+ type: String,
+ default: 'center',
+ validator: p => ['center', 'lb', 'lt', 'rt', 'rb', 'l', 'r', 't', 'b'].includes(p)
+ },
+
+ titleAngle: {
+ type: Number,
+ default: 0
+ },
+
+ titleColor: {
+ type: String,
+ default: 'black'
+ },
+
+ titleFont: {
+ type: String,
+ default: 'Helvetica'
+ },
+
+ titleFontSize: {
+ type: Number,
+ default: 12
+ },
+
+ titleFontWeight: {
+ type: Number,
+ default: 500
+ },
+
+ titleOpacity: {
+ type: Number,
+ default: 1
+ },
+
+ titleHjust: {
+ type: [Number, String],
+ validator: function (p) {
+ return (p.constructor === Number) || (['center', 'l', 'r'].includes(p))
+ }
+ },
+
+ titleVjust: {
+ type: [Number, String],
+ validator: function (p) {
+ return (p.constructor === Number) || (['center', 't', 'b'].includes(p))
+ }
}
+
},
computed: {
@@ -56,14 +229,46 @@ export default {
_domainType () {
return this._parsedScalingOptions[1]
},
+ _scalingOptions () {
+ return this._parsedScalingOptions[2]
+ },
+
+ _parentNodes () {
+ return this.getParents(this.parentBranch, [this.parentBranch])
+ },
+
+ validX () {
+ return (this.x1 !== undefined && this.x2 !== undefined) || (this.x !== undefined && this.w !== undefined)
+ },
+
+ validY () {
+ return (this.y1 !== undefined && this.y2 !== undefined) || (this.y !== undefined && this.h !== undefined)
+ },
- ranges () {
- return this.coordinateSpecification
+ coords () {
+ if (this.validX || this.validY) {return this.coordinateSpecification}
+ },
+
+ xDomain () {
+ return this.parentBranch.domains.x
+ },
+
+ yDomain () {
+ return this.parentBranch.domains.y
},
tickData () {
+ let firstValue = this._domain[0]
+ let newTickValues
+
if (this.tickValues) {
- return this.tickValues.map(value => {
+ newTickValues = this.tickValues
+
+ if (this.tickExtra && this.tickValues[0] !== firstValue) {
+ newTickValues.unshift(firstValue)
+ }
+
+ return newTickValues.map(value => {
return { value }
})
} else {
@@ -71,8 +276,18 @@ export default {
let format = this.format && this.format.constructor === Function ? this.format : defaultFormat
if (this._domainType === 'quantitative') {
- ticks = arrayTicks(...this._domain, this.tickCount).map(value => {
- return { value, label: format(value) }
+ newTickValues = arrayTicks(...this._domain, this.tickCount)
+
+ if (this.tickExtra && newTickValues[0] !== firstValue) {
+ newTickValues.unshift(firstValue)
+ }
+
+ ticks = newTickValues.map((value, i) => {
+ if (i === 0 && this.tickExtra && !this.tickExtraLabel) {
+ return { value, label: '' }
+ } else {
+ return { value, label: format(value) }
+ }
})
}
@@ -91,9 +306,20 @@ export default {
let scale = scaleTime().domain(this._domain)
- ticks = scale.ticks(this.tickCount).map(value => {
+ newTickValues = scale.ticks(this.tickCount)
+
+ if (this.tickExtra && newTickValues[0] !== firstValue) {
+ newTickValues.unshift(firstValue)
+ }
+
+ ticks = newTickValues.map((value, i) => {
let date = new Date(value)
- return { value: date, label: format(date) }
+
+ if (i === 0 && this.tickExtra && !this.tickExtraLabel) {
+ return { value: date, label: '' }
+ } else {
+ return { value: date, label: format(date) }
+ }
})
}
@@ -131,6 +357,10 @@ export default {
ticks.add(interval[1])
}
return Array.from(ticks)
- }
+ },
+
+ getLocalX (n) { return this.$$getLocalX(n) },
+
+ getLocalY (n) { return this.$$getLocalY(n) }
}
}
diff --git a/src/mixins/Guides/defaultFormat.js b/src/mixins/Guides/defaultFormat.js
index b2c1ca07..28ed9880 100644
--- a/src/mixins/Guides/defaultFormat.js
+++ b/src/mixins/Guides/defaultFormat.js
@@ -2,7 +2,7 @@ export default function (value) {
if (value.constructor === Number) {
let stringValue = value.toString()
let length = stringValue.length
- if (length < 6) { return value }
+ if (length < 6) { return value.toString() }
let nIntegers = stringValue.split('.')[0].length
@@ -24,5 +24,5 @@ export default function (value) {
function round (value, decimals) {
let z = 10 ** decimals
- return Math.floor(value * z) / z
+ return (Math.floor(value * z) / z).toString()
}
diff --git a/src/mixins/Marks/Mark.js b/src/mixins/Marks/Mark.js
index b8807109..7ca71e0b 100644
--- a/src/mixins/Marks/Mark.js
+++ b/src/mixins/Marks/Mark.js
@@ -4,7 +4,7 @@ import createSVGStyle from './utils/createSVGStyle.js'
export default {
mixins: [CoordinateTreeUser],
- inject: ['$$transform'],
+ inject: ['$$transform', '$$getLocalX', '$$getLocalY'],
props: {
interpolate: {
diff --git a/stories/charts/Scatterplot.vue b/stories/charts/Scatterplot.vue
index f35f2e1e..eca345b8 100644
--- a/stories/charts/Scatterplot.vue
+++ b/stories/charts/Scatterplot.vue
@@ -24,6 +24,18 @@
+
+
+
+
-
-
-
-
diff --git a/stories/sandbox/Areas.vue b/stories/sandbox/Areas.vue
index a4ae1182..9e0bcfdf 100644
--- a/stories/sandbox/Areas.vue
+++ b/stories/sandbox/Areas.vue
@@ -4,24 +4,6 @@
:height="600"
:data="dummyData">
-
-
-
-
-
+
+
+
+
+
diff --git a/stories/sandbox/BarChart.vue b/stories/sandbox/BarChart.vue
index a530e3ba..8a35e9bb 100644
--- a/stories/sandbox/BarChart.vue
+++ b/stories/sandbox/BarChart.vue
@@ -66,24 +66,20 @@
-
+
-
-
-
+
+
+
diff --git a/stories/sandbox/BinningTest.vue b/stories/sandbox/BinningTest.vue
index b15e0957..ff5883ec 100644
--- a/stories/sandbox/BinningTest.vue
+++ b/stories/sandbox/BinningTest.vue
@@ -47,6 +47,19 @@
+
+
+
+
+
+
diff --git a/stories/sandbox/NestedCoordinateSystem.vue b/stories/sandbox/NestedCoordinateSystem.vue
index ce6cff2b..9a38ecdd 100644
--- a/stories/sandbox/NestedCoordinateSystem.vue
+++ b/stories/sandbox/NestedCoordinateSystem.vue
@@ -33,7 +33,7 @@
:x="p.x"
:y="p.y"
:fill="cs.color"
- :size="8"
+ :radius="4"
/>
-
-
-
-
-
+
+
+
+
+
diff --git a/stories/sandbox/Scatterplot.vue b/stories/sandbox/Scatterplot.vue
index 3ed00ccc..53c468b9 100644
--- a/stories/sandbox/Scatterplot.vue
+++ b/stories/sandbox/Scatterplot.vue
@@ -26,6 +26,34 @@
+
+
+
+
+
+
+
+
-
-
-
-
diff --git a/stories/sandbox/TestCategoricalDomain.vue b/stories/sandbox/TestCategoricalDomain.vue
index 2ad9fbd8..74a29b92 100644
--- a/stories/sandbox/TestCategoricalDomain.vue
+++ b/stories/sandbox/TestCategoricalDomain.vue
@@ -36,16 +36,21 @@
]"
/>
+
+
-
+ /> -->
diff --git a/stories/sandbox/TestSymbol.vue b/stories/sandbox/TestSymbol.vue
index 9a0ac845..1950392e 100644
--- a/stories/sandbox/TestSymbol.vue
+++ b/stories/sandbox/TestSymbol.vue
@@ -26,8 +26,21 @@
shape="triangle-left"
fill="none"
/>
+
+
+
+
+
-
-
-
-