From 70572ff971d562423ac4d622a5fbc94033cfdfde Mon Sep 17 00:00:00 2001 From: gracegsy Date: Wed, 16 Jan 2019 14:07:14 +0800 Subject: [PATCH 01/37] feat: more classification methods --- .../transformations/binning.js | 156 +++++++++++------- stories/sandbox/BinningTest.vue | 138 +++++++++------- 2 files changed, 178 insertions(+), 116 deletions(-) diff --git a/src/transformations/transformations/binning.js b/src/transformations/transformations/binning.js index 378164fe..7a326947 100644 --- a/src/transformations/transformations/binning.js +++ b/src/transformations/transformations/binning.js @@ -1,49 +1,60 @@ +import * as Geostats from 'geostats' +import dataLength from '../utils/dataLength.js' + export default function (data, binningObj) { if (binningObj.constructor !== Object) { - throw new Error('Binning only accepts an object') + throw new Error('Binning only accepts an Object') } - if (this.$$dataContainer) { console.log(this.$$dataContainer) } - - for (let key in binningObj) { - if (data.hasOwnProperty(key)) { - let binCount = binningObj[key].binCount - let binSize = binningObj[key].binSize - let binInterval = binningObj[key].binInterval - - let variableData = data[key] - - if (!(binCount ^ binSize ^ binInterval)) { - throw new Error('Please provide only one of the following: bin count, bin size, custom bin ranges') - } else if (binCount) { - let domain = variableDomain(variableData) - let interval = (domain[1] - domain[0]) / binCount - - let ranges = rangeFromInterval(domain, interval, binCount) + let key = binningObj.groupBy + if (key.constructor !== String) { + throw new Error('groupBy only accepts a String variable name') + } - let newData = bin(variableData, ranges) - console.log(newData) + let method = binningObj.method + if (method.constructor !== String) { + throw new Error('Please provide the classification method you will like to use') + } - return newData - } else if (binSize) { - let domain = variableDomain(variableData) - let binCount = Math.round((domain[1] - domain[0]) / binSize) + let numClasses = binningObj.numClasses + + let variableData = data[key] + let geoStat = new Geostats(variableData) + + let ranges + + // Calculate ranges to obtain bins of a specified size + if (method === 'IntervalSize') { + let binSize = binningObj.binSize + let domain = variableDomain(variableData) + let binCount = Math.round((domain[1] - domain[0]) / binSize) + + ranges = rangeFromInterval(domain, binSize, binCount) + } else if (method === 'EqualInterval') { + ranges = geoStat.getClassEqInterval(numClasses) + } else if (method === 'StandardDeviation') { + ranges = geoStat.getClassStdDeviation(numClasses) + } else if (method === 'ArithmeticProgression') { + ranges = geoStat.getClassArithmeticProgression(numClasses) + } else if (method === 'GeometricProgression') { + ranges = geoStat.getClassGeometricProgression(numClasses) + } else if (method === 'Quantile') { + ranges = geoStat.getClassQuantile(numClasses) + } else if (method === 'Jenks') { + ranges = geoStat.getClassJenks(numClasses) + } else if (method === 'UniqueValues') { + ranges = geoStat.getClassUniqueValues() + } else if (method === 'Manual') { + ranges = binningObj.manualClasses + } - let ranges = rangeFromInterval(domain, binSize, binCount) + ranges = pairRange(ranges) - let newData = bin(variableData, ranges) - return newData - } else { - let newData = bin(variableData, binInterval) - - return newData - } - } else { - console.warn(`Column '${key}' not found`) - } - } + let newData = bin(data, key, ranges) + return newData } +// Extract domain of variable of interest function variableDomain (column) { let asc = column.sort((a, b) => a - b) @@ -56,6 +67,8 @@ function variableDomain (column) { function rangeFromInterval (domain, interval, binCount) { let ranges = [] + + // Ranges should start at the minimum value of variable of interest let lowerBound = domain[0] for (let i = 0; i < binCount; i++) { @@ -69,38 +82,67 @@ function rangeFromInterval (domain, interval, binCount) { return ranges } -function binIndexFromValue (value, lowerBound, binInterval, upperBound) { - if (value >= upperBound) { - value -= 1 +function pairRange(ranges) { + let l = ranges.length + + let newRange = [] + + for (let i = 0; i < l - 1; i ++) { + newRange.push([ranges[i], ranges[i+1]]) } - return Math.floor((value - lowerBound) / binInterval) + + return newRange } -function bin (data, ranges) { +function bin (data, variable, ranges) { let newData = {} - newData.min = [] - newData.max = [] - newData.n = Array(ranges.length).fill(0) - newData.sum = Array(ranges.length).fill(0) - newData.average = [] + newData.lowerBound = [] + newData.upperBound = [] - for (let ix = 0; ix < data.length; ix++) { - let instance = data[ix] - let binIndex = ranges.findIndex(el => instance >= el[0] && instance <= el[1]) - console.log(binIndex) - newData.n[binIndex]++ - newData.sum[binIndex] = newData.sum[binIndex] + instance + // Create lowerBound and upperBound columns to track bin ranges + for (let i = 0; i < ranges.length; i++) { + newData.lowerBound.push(ranges[i][0]) + newData.upperBound.push(ranges[i][1]) } - for (let i = 0; i < ranges.length; i++) { - newData.min.push(ranges[i][0]) - newData.max.push(ranges[i][1]) + let ix = 0 + + // Create an empty array to store new dataFrames divided by range + let bins = Array(ranges.length) + + let length = dataLength(data) + + // Loop through data + while (ix < length) { + let instance = data[variable][ix] + + // Find index of bin in which the instance belongs + let binIndex = ranges.findIndex(el => instance >= el[0] && instance <= el[1]) - let a = newData.sum[i] / newData.n[i] + let newRow = bins[binIndex] - newData.average.push(a) + // If dataFrame does not exist, create it + if (!newRow) {newRow = {}} + + for (let col in data) { + // If data key does not exist, create it + if (!newRow[col]) { + newRow[col] = [data[col][ix]] + } else { + newRow[col].push(data[col][ix]) + } + } + + // Update the bins column with new dataFrame + bins[binIndex] = newRow + + ix++ } + // Add new dataFrame column to newData + newData.grouped = bins + return newData } + diff --git a/stories/sandbox/BinningTest.vue b/stories/sandbox/BinningTest.vue index 0e8cdafa..9967fb1c 100644 --- a/stories/sandbox/BinningTest.vue +++ b/stories/sandbox/BinningTest.vue @@ -1,74 +1,78 @@ diff --git a/src/components/index.js b/src/components/index.js index 0f178cbc..d17d1502 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -25,6 +25,7 @@ import Point from './Marks/Point.vue' import Polygon from './Marks/Polygon.vue' import Rectangle from './Marks/Rectangle.vue' import Label from './Marks/Label.vue' +import Symbol from './Marks/Symbol.vue' export default { Glyph, @@ -49,5 +50,6 @@ export default { Point, Polygon, Rectangle, - Label + Label, + Symbol } diff --git a/stories/index.js b/stories/index.js index 306374bd..7f920830 100644 --- a/stories/index.js +++ b/stories/index.js @@ -14,6 +14,7 @@ import GeoShape from './sandbox/GeoShape.vue' import MissingInvalidData from './sandbox/MissingInvalidData.vue' import MultiLines from './sandbox/MultiLines.vue' import Areas from './sandbox/Areas.vue' +import TestSymbol from './sandbox/TestSymbol.vue' storiesOf('Charts', module) .add('Scatterplot', () => (Scatterplot)) @@ -31,3 +32,4 @@ storiesOf('Sandbox', module) .add('Test: missing', () => (MissingInvalidData)) .add('Test: Area Mark', () => (Areas)) .add('MultiLines', () => (MultiLines)) + .add('TestSymbol', () => (TestSymbol)) diff --git a/stories/sandbox/TestSymbol.vue b/stories/sandbox/TestSymbol.vue new file mode 100644 index 00000000..bdd2ec6e --- /dev/null +++ b/stories/sandbox/TestSymbol.vue @@ -0,0 +1,93 @@ + + + From 4ec45446e67554798d161c42114ad96eb1e695b7 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Thu, 17 Jan 2019 15:04:23 +0800 Subject: [PATCH 10/37] docs: symbol mark demo component added to docs --- docs/.vuepress/components/SymbolMarkDemo.vue | 139 +++++++++++++++++++ docs/.vuepress/config.js | 1 + docs/marks/symbol.md | 11 ++ 3 files changed, 151 insertions(+) create mode 100644 docs/.vuepress/components/SymbolMarkDemo.vue create mode 100644 docs/marks/symbol.md diff --git a/docs/.vuepress/components/SymbolMarkDemo.vue b/docs/.vuepress/components/SymbolMarkDemo.vue new file mode 100644 index 00000000..a20a63e0 --- /dev/null +++ b/docs/.vuepress/components/SymbolMarkDemo.vue @@ -0,0 +1,139 @@ + + + diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 657b5838..21e9258e 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -67,6 +67,7 @@ module.exports = { 'marks/polygon', 'marks/area', 'marks/rectangle', + 'marks/symbol' ] }, { diff --git a/docs/marks/symbol.md b/docs/marks/symbol.md new file mode 100644 index 00000000..16b78cad --- /dev/null +++ b/docs/marks/symbol.md @@ -0,0 +1,11 @@ +--- +title: Symbol Mark +--- + +# Component tag + +`` + +# Symbol Mark Demo + + \ No newline at end of file From 6428b396ec999ac8b4f1b539dac7ee6ea6cde563 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Thu, 17 Jan 2019 18:57:19 +0800 Subject: [PATCH 11/37] docs: filling in explanatory write-up for symbol mark --- docs/.vuepress/components/SymbolMarkDemo.vue | 22 ++++----- docs/marks/symbol.md | 52 +++++++++++++++++++- src/components/Marks/Symbol.vue | 2 +- 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/docs/.vuepress/components/SymbolMarkDemo.vue b/docs/.vuepress/components/SymbolMarkDemo.vue index a20a63e0..8b24b4f5 100644 --- a/docs/.vuepress/components/SymbolMarkDemo.vue +++ b/docs/.vuepress/components/SymbolMarkDemo.vue @@ -3,14 +3,14 @@ @@ -31,32 +31,32 @@ diff --git a/docs/marks/symbol.md b/docs/marks/symbol.md index 16b78cad..7047acd9 100644 --- a/docs/marks/symbol.md +++ b/docs/marks/symbol.md @@ -6,6 +6,56 @@ title: Symbol Mark `` -# Symbol Mark Demo +# Description + +The Symbol mark is used for plotting point data, with each data instance being represented as a symbol (or shape). The most common use for the Symbol mark is in a scatterplot with the shape set to `circle`. + +# Props + +### Positioning + +| Prop | Required | Regular types | Types when mapping | Default | Description | Unit(s) | +| ---- | -------- | --------------- | ---------------------------------------- | --------- | ---------------------------------------- | ----------------- | +| x | true | [Number, String]| [Number, String, Date, Object, Function] | undefined | x-coordinates of center of each symbol | Local coordinates | +| y | true | [Number, String]| [Number, String, Date, Object, Function] | undefined | y-coordinates of center of each symbol | Local coordinates | + +### Other aesthetics + +| Prop | Required | Regular types | Types when mapping | Default | Description | Unit(s) | +|----------------|----------|---------------|----------------------------|-----------|----------------|----------------------------| +| stroke | false | String | [String, Object, Function] | undefined | Stroke color | Named color, hex, rgb, hsl | +| stroke-width | false | Number | [Number, Object, Function] | undefined | Stroke width | Screen pixel | +| stroke-opacity | false | Number | [Number, Object, Function] | undefined | Stroke opacity | Number between 0 to 1 | +| fill | false | String | [String, Object, Function] | 'black' | Fill color | Named color, hex, rgb, hsl | +| fill-opacity | false | Number | [Number, Object, Function] | undefined | Fill opacity | Number between 0 and 1 | +| opacity | false | Number | [Number, Object, Function] | undefined | Mark opacity | Number between 0 and 1 | + +These are analogous to the CSS properties of the same names. + +### Other props + +| Prop | Required | Types | Default | Description | +| ----------- | -------- | ------- | ------- | ------------------------------------------------------------------------ | +| shape | false | String | 'circle'| Shape of the symbol | +| size | false | Number | 10 | Length and width of the symbol | +| transition | false | Number | 0 | Time taken to animate changes to each symbol when data changes | + +# Usage + +### Positioning + +To render the Symbol mark, you will need the `x` and `y` props. These represent the coordinates of the center point of each shape. + +All above props can be passed as an Array of `Numbers` or `Strings` (for categorical variables). They can also be passed as an entire column within the data scope. However, the length of the two variable sets must be the same. + +### Other props + +The `shape` prop sets the shape of the symbol mark. The value defaults to `circle` but can be set to any of the available options: `square`, `cross`, `diamond`, `triangle-up`, `triangle-down`, `triangle-left`, `triangle-right` and `star`. Additionally, it is also possible to provide a custom shape, specified as a SVG path string with coordinates scaled to [-1, 1] both horizontally and vertically. + +`size` defaults to 10px. This same value refers to both the height and width of the shape. In order to improve the accuracy when reading off the (x, y) values of the center point of each symbol instance, we do not allow height and width of the symbol mark to take on different values. + +`transition` is disabled by default. It can be set to take any arbitrary length of time in seconds. + +# Example \ No newline at end of file diff --git a/src/components/Marks/Symbol.vue b/src/components/Marks/Symbol.vue index f481afb2..7d41b6bb 100644 --- a/src/components/Marks/Symbol.vue +++ b/src/components/Marks/Symbol.vue @@ -18,7 +18,7 @@ export default { fill: { type: [String, Object, Function, undefined], - default: undefined + default: 'black' }, stroke: { From 59bc392471fdf4d7b1f5834acb5d8e4fdd85b324 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Fri, 18 Jan 2019 12:05:21 +0800 Subject: [PATCH 12/37] docs: minor change in example symbol graph --- docs/.vuepress/components/SymbolMarkDemo.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/.vuepress/components/SymbolMarkDemo.vue b/docs/.vuepress/components/SymbolMarkDemo.vue index 8b24b4f5..380b6aca 100644 --- a/docs/.vuepress/components/SymbolMarkDemo.vue +++ b/docs/.vuepress/components/SymbolMarkDemo.vue @@ -119,8 +119,8 @@ export default { methods: { generateNewData () { - let xValues = [78,41,36,54,70,31,88,99,76,60,100,66,100,34,11,1,49,54,32,38] - let yValues = [44,43,-37,-17,29,0,-50,15,-34,-47,-24,-2,4,-10,50,-11,-48,-40,49,39] + let xValues = [78,41, 36, 54,70,31,88,97,76, 60, 100,66,65,34, 11,1, 49, 54,30,39] + let yValues = [44,43,-37,-17,29,0,-50,15,-34,-47,-24, -2,4, -10,50,-11,-49,-40,49,39] // xValues.sort() yValues.sort() From 4110c7082031f9ce0daa0eecf30f4d2dfc2c0f4e Mon Sep 17 00:00:00 2001 From: gracegsy Date: Fri, 18 Jan 2019 15:23:38 +0800 Subject: [PATCH 13/37] feat: tooltip + links for symbol marks --- src/components/Marks/Symbol.vue | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/Marks/Symbol.vue b/src/components/Marks/Symbol.vue index 7d41b6bb..2ee79e3a 100644 --- a/src/components/Marks/Symbol.vue +++ b/src/components/Marks/Symbol.vue @@ -120,13 +120,13 @@ export default { return createElement('path', { attrs: { - d: d + d: d, }, style: s }) }, - renderSVG (createElement, aesthetics) { + getElement (createElement, aesthetics) { let path if (this.shape === 'circle') { return this.createCircle(createElement, aesthetics) @@ -152,6 +152,18 @@ export default { return this.createPath(createElement, aesthetics, path) + }, + + renderSVG (createElement, aesthetics) { + let element = this.getElement(createElement, aesthetics) + + let tooltip = createElement('title', 'color scale') + + return createElement('a', { + attrs: { + href: '../scales/color.html', + }, + }, [element, tooltip]) } } } From 173a8bb439f03cc65874ec13a4c13a375860e23f Mon Sep 17 00:00:00 2001 From: gracegsy Date: Thu, 24 Jan 2019 12:33:54 +0800 Subject: [PATCH 14/37] refactor: scaled symbol size, deprecate vgg-point --- docs/.vuepress/config.js | 1 - src/components/Marks/Symbol.vue | 9 +++++---- src/components/index.js | 4 ++-- src/scales/createScale.js | 2 +- stories/charts/Scatterplot.vue | 4 ++-- stories/sandbox/BarChart.vue | 4 ++-- stories/sandbox/MissingInvalidData.vue | 2 +- stories/sandbox/MultiLines.vue | 2 +- stories/sandbox/NestedCoordinateSystem.vue | 3 ++- stories/sandbox/Scatterplot.vue | 4 ++-- stories/sandbox/TestAbsolute.vue | 4 ++-- stories/sandbox/TestCategoricalDomain.vue | 4 ++-- stories/sandbox/TestSymbol.vue | 2 +- stories/sandbox/TransformTest.vue | 2 +- 14 files changed, 24 insertions(+), 23 deletions(-) diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js index 21e9258e..0a1913ba 100644 --- a/docs/.vuepress/config.js +++ b/docs/.vuepress/config.js @@ -63,7 +63,6 @@ module.exports = { 'marks/label', 'marks/line', 'marks/path', - 'marks/point', 'marks/polygon', 'marks/area', 'marks/rectangle', diff --git a/src/components/Marks/Symbol.vue b/src/components/Marks/Symbol.vue index 2ee79e3a..b9c748df 100644 --- a/src/components/Marks/Symbol.vue +++ b/src/components/Marks/Symbol.vue @@ -37,7 +37,7 @@ export default { }, size: { - type: Number, + type: [Number, Object, Function, undefined], default: 10 }, @@ -73,6 +73,7 @@ export default { opacity: this.parseAesthetic(this.opacity), fillOpacity: this.parseAesthetic(this.fillOpacity), strokeOpacity: this.parseAesthetic(this.strokeOpacity), + size: this.parseAesthetic(this.size), transition: this.transition + 's' } } @@ -81,7 +82,7 @@ export default { methods: { createCircle (createElement, aesthetics) { let [cx, cy] = this.$$transform([aesthetics.x, aesthetics.y]) - let r = this.size / 2 + let r = aesthetics.size / 2 return createElement('circle', { attrs: { @@ -96,7 +97,7 @@ export default { createSquare (createElement, aesthetics) { let [cx, cy] = this.$$transform([aesthetics.x, aesthetics.y]) - let l = this.size + let l = aesthetics.size let x = cx - (l / 2) let y = cy - (l / 2) @@ -114,7 +115,7 @@ export default { createPath (createElement, aesthetics, d) { let [cx, cy] = this.$$transform([aesthetics.x, aesthetics.y]) let s = createSVGStyle(aesthetics) - let scale = this.size / 2 + let scale = aesthetics.size / 2 s.strokeWidth = s.strokeWidth / scale s.transform = 'translateX(' + cx + 'px) translateY(' + cy + 'px) scale(' + scale + ', ' + scale + ') ' diff --git a/src/components/index.js b/src/components/index.js index 35ddde49..7014488a 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -21,7 +21,7 @@ import Line from './Marks/Line.vue' import MultiLine from './Marks/MultiLine.vue' import Area from './Marks/Area.vue' import Path from './Marks/Path.vue' -import Point from './Marks/Point.vue' +// import Point from './Marks/Point.vue' import Polygon from './Marks/Polygon.vue' import Rectangle from './Marks/Rectangle.vue' import Label from './Marks/Label.vue' @@ -47,7 +47,7 @@ export default { MultiLine, Area, Path, - Point, + // Point, Polygon, Rectangle, Label, diff --git a/src/scales/createScale.js b/src/scales/createScale.js index 77c2afc6..c207ecf3 100644 --- a/src/scales/createScale.js +++ b/src/scales/createScale.js @@ -29,7 +29,7 @@ export default function (prop, context, scalingOptions) { } // Pixel-value props - if (['width', 'height', 'fontSize', 'strokeWidth'].includes(prop)) { + if (['width', 'height', 'fontSize', 'strokeWidth', 'size'].includes(prop)) { let range if (!scalingOptions.range) { console.warn(`No range specified for prop ${prop}. Defaulting to [0, 10]`) diff --git a/stories/charts/Scatterplot.vue b/stories/charts/Scatterplot.vue index 0a95d520..de0e4f92 100644 --- a/stories/charts/Scatterplot.vue +++ b/stories/charts/Scatterplot.vue @@ -17,10 +17,10 @@ - diff --git a/stories/sandbox/BarChart.vue b/stories/sandbox/BarChart.vue index f1d3208d..87953629 100644 --- a/stories/sandbox/BarChart.vue +++ b/stories/sandbox/BarChart.vue @@ -50,10 +50,10 @@ - diff --git a/stories/sandbox/MissingInvalidData.vue b/stories/sandbox/MissingInvalidData.vue index 115c276c..3022ed1b 100644 --- a/stories/sandbox/MissingInvalidData.vue +++ b/stories/sandbox/MissingInvalidData.vue @@ -12,7 +12,7 @@ - diff --git a/stories/sandbox/MultiLines.vue b/stories/sandbox/MultiLines.vue index eee3c49d..ad5ea674 100644 --- a/stories/sandbox/MultiLines.vue +++ b/stories/sandbox/MultiLines.vue @@ -64,7 +64,7 @@ - - - diff --git a/stories/sandbox/TestAbsolute.vue b/stories/sandbox/TestAbsolute.vue index 33bb6cae..9a3b9ec3 100644 --- a/stories/sandbox/TestAbsolute.vue +++ b/stories/sandbox/TestAbsolute.vue @@ -12,10 +12,10 @@ :text="row => row.name" /> - diff --git a/stories/sandbox/TestCategoricalDomain.vue b/stories/sandbox/TestCategoricalDomain.vue index 3757211e..664aa1b2 100644 --- a/stories/sandbox/TestCategoricalDomain.vue +++ b/stories/sandbox/TestCategoricalDomain.vue @@ -22,10 +22,10 @@ - diff --git a/stories/sandbox/TestSymbol.vue b/stories/sandbox/TestSymbol.vue index bdd2ec6e..6288def9 100644 --- a/stories/sandbox/TestSymbol.vue +++ b/stories/sandbox/TestSymbol.vue @@ -20,7 +20,7 @@ - From a1b362399b61151b34e8ae5fad792a068180ae35 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Thu, 24 Jan 2019 16:29:39 +0800 Subject: [PATCH 15/37] refactor: remove tooltip and html linking from symbol --- src/components/Marks/Symbol.vue | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/components/Marks/Symbol.vue b/src/components/Marks/Symbol.vue index b9c748df..60d66da4 100644 --- a/src/components/Marks/Symbol.vue +++ b/src/components/Marks/Symbol.vue @@ -127,7 +127,7 @@ export default { }) }, - getElement (createElement, aesthetics) { + renderSVG (createElement, aesthetics) { let path if (this.shape === 'circle') { return this.createCircle(createElement, aesthetics) @@ -154,18 +154,6 @@ export default { return this.createPath(createElement, aesthetics, path) }, - - renderSVG (createElement, aesthetics) { - let element = this.getElement(createElement, aesthetics) - - let tooltip = createElement('title', 'color scale') - - return createElement('a', { - attrs: { - href: '../scales/color.html', - }, - }, [element, tooltip]) - } } } From 7b85413f254ac05c69b83fa7edb24cc690919e87 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Fri, 25 Jan 2019 14:50:46 +0800 Subject: [PATCH 16/37] feat: additional axis style options --- src/components/Guides/XAxis.vue | 26 +++- src/components/Guides/YAxis.vue | 26 +++- src/components/Marks/Label.vue | 18 ++- src/mixins/Guides/BaseAxis.js | 202 ++++++++++++++++++++++++++++++-- 4 files changed, 244 insertions(+), 28 deletions(-) diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index e3fa46b1..e2ab2277 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -14,11 +14,14 @@ @@ -39,31 +42,42 @@ diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue index 4447a7b2..cf6fbb66 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -14,11 +14,14 @@ @@ -40,31 +43,42 @@ diff --git a/src/components/Marks/Label.vue b/src/components/Marks/Label.vue index 4c8fbdf7..d60eb85d 100644 --- a/src/components/Marks/Label.vue +++ b/src/components/Marks/Label.vue @@ -59,11 +59,21 @@ export default { default: undefined }, + fontFamily: { + type: String, + default: 'Helvetica' + }, + fontSize: { type: [Number, Object, Function, undefined], default: undefined }, + fontWeight: { + type: String, + default: 'normal' + }, + rotation: { type: [Number, Object, Function, undefined], default: undefined @@ -110,6 +120,8 @@ export default { let styles = createSVGStyle(aesthetics) styles['fontSize'] = aesthetics.fontSize + 'px' + styles['font-family'] = this.fontFamily + styles['font-weight'] = this.fontWeight let el = createElement('text', { attrs: { @@ -129,9 +141,3 @@ export default { } } - - diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index 3af760ae..049159ea 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -14,30 +14,212 @@ export default { default: undefined }, - tickValues: { - type: [Array, undefined], + format: { + type: [String, Function, undefined], default: undefined }, - tickCount: { + flip: { + type: Boolean, + default: false + }, + + // 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 + }, + + // text-anchor ** + labelAlign: { + type: String, + default: 'middle' + }, + + // alignment-baseline ** + labelBaseline: { + type: String, + default: 'middle' + }, + + // hide labels that exceed axis range + // labelBound: { + // type: Boolean, + // default: false + // }, + + labelColor: { + type: String, + default: 'black' + }, + + // labelFlush (not sure what this is) + + labelFont: { + type: String, + default: 'Helvetica' + }, + + labelFontSize: { type: Number, default: 10 }, - rotateLabel: { + labelFontWeight: { + type: [String, Number], + default: 'normal' + }, + + // labelLimit (also not sure what this is) + + labelOpacity: { + type: Number, + default: 1 + }, + + // labelOverlap + + // Distance between tick and label ** + labelPadding: { + type: Number, + default: 0 + }, + + // minExtent, maxExtent, offset + + // POSITION??? + + labelRotate: { type: Boolean, default: false }, - format: { - type: [String, Function, undefined], + ticks: { + type: Boolean, + default: true + }, + + tickColor: { + type: String, + default: 'black' + }, + + tickValues: { + type: [Array, undefined], default: undefined }, - flip: { - type: Boolean, - default: false - } + tickCount: { + type: Number, + default: 10 + }, + + // tickExtra + + // What is this? + tickOffset: { + type: Number, + default: 0 + }, + + tickOpacity: { + type: Number, + default: 1 + }, + + // tickRound + + // TODO ** + tickSize: { + type: Number, + default: 5 + }, + + tickWidth: { + type: Number, + default: 0.5 + }, + + // New + tickPosition: { + type: Number, + default: 0.5 + }, + + title: { + type: String, + default: '' + }, + + // text-anchor + titleAlign: { + type: String, + default: 'middle' + }, + + // titleAngle + + titleBaseline: { + type: String, + default: 'middle' + }, + + titleColor: { + type: String, + default: 'black' + }, + + titleFont: { + type: String, + default: 'Helvetica' + }, + + titleFontSize: { + type: Number, + default: 12 + }, + + titleFontWeight: { + type: Number, + default: 500 + }, + + // titleLimit (what is this?) + + titleOpacity: { + type: Number, + default: 1 + }, + + titlePadding: { + type: Number, + default: 0 + }, + + // titleX, titleY + + // zindex + }, computed: { From 8a4d2bff1011a4d1077d9d84acb0adc6f2ba44ab Mon Sep 17 00:00:00 2001 From: gracegsy Date: Fri, 25 Jan 2019 16:09:18 +0800 Subject: [PATCH 17/37] feat: axis titles with styling options and hjust + vjust --- src/components/Guides/XAxis.vue | 59 ++++++++++++++++++++++++++++++++- src/components/Guides/YAxis.vue | 59 ++++++++++++++++++++++++++++++++- src/components/Marks/Label.vue | 2 +- src/mixins/Guides/BaseAxis.js | 29 +++------------- 4 files changed, 122 insertions(+), 27 deletions(-) diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index e2ab2277..e413c77c 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -24,6 +24,19 @@ :stroke-width="domainWidth" /> + + + diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue index cf6fbb66..fcfcee2e 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -24,6 +24,19 @@ :stroke-width="domainWidth" /> + + + diff --git a/src/components/Marks/Label.vue b/src/components/Marks/Label.vue index d60eb85d..3716f1c7 100644 --- a/src/components/Marks/Label.vue +++ b/src/components/Marks/Label.vue @@ -70,7 +70,7 @@ export default { }, fontWeight: { - type: String, + type: [String, Number], default: 'normal' }, diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index 049159ea..bcb853ce 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -50,18 +50,6 @@ export default { default: true }, - // text-anchor ** - labelAlign: { - type: String, - default: 'middle' - }, - - // alignment-baseline ** - labelBaseline: { - type: String, - default: 'middle' - }, - // hide labels that exceed axis range // labelBound: { // type: Boolean, @@ -171,18 +159,14 @@ export default { default: '' }, - // text-anchor - titleAlign: { + // text-anchor ** + titleAnchorPoint: { type: String, - default: 'middle' + default: 'center', + validator: p => ['center', 'lb', 'lt', 'rt', 'rb', 'l', 'r', 't', 'b'].includes(p) }, // titleAngle - - titleBaseline: { - type: String, - default: 'middle' - }, titleColor: { type: String, @@ -211,15 +195,12 @@ export default { default: 1 }, + // TODO ** titlePadding: { type: Number, default: 0 }, - // titleX, titleY - - // zindex - }, computed: { From d993bb9cf1cde0add420a24c6b81a40b215d99af Mon Sep 17 00:00:00 2001 From: gracegsy Date: Fri, 25 Jan 2019 16:24:03 +0800 Subject: [PATCH 18/37] refactor: titleHjust, titleVjust, add tickSize prop --- src/components/Guides/XAxis.vue | 15 ++++----------- src/components/Guides/YAxis.vue | 15 ++++----------- src/mixins/Guides/BaseAxis.js | 33 +++++++++++++++++++++++++-------- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index e413c77c..abba435e 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -35,6 +35,7 @@ :font-size="titleFontSize" :font-weight="titleFontWeight" :opacity="titleOpacity" + :rotation="titleAngle" /> @@ -59,7 +60,7 @@ :x1="tick => tick.value" :y1="0.5" :x2="tick => tick.value" - :y2="flip ? 0.35 : 0.65" + :y2="flip ? tickMin : tickMax" :stroke="tickColor" :stroke-opacity="tickOpacity" :stroke-width="tickWidth" @@ -110,19 +111,11 @@ export default { props: { titleHjust: { - type: [Number, String], - default: -0.08, - validator: function (p) { - return (p.constructor === Number) || (['center', 'l', 'r'].includes(p)) - } + default: -0.08 }, titleVjust: { - type: [Number, String], - default: 'center', - validator: function (p) { - return (p.constructor === Number) || (['center', 't', 'b'].includes(p)) - } + default: 'center' } }, diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue index fcfcee2e..a0e5dab1 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -35,6 +35,7 @@ :font-size="titleFontSize" :font-weight="titleFontWeight" :opacity="titleOpacity" + :rotation="titleAngle" /> @@ -59,7 +60,7 @@ v-if="ticks" :x1="0.5" :y1="tick => tick.value" - :x2="flip ? 0.65 : 0.35" + :x2="flip ? tickMax : tickMin" :y2="tick => tick.value" :stroke="tickColor" :stroke-opacity="tickOpacity" @@ -111,19 +112,11 @@ export default { props: { titleHjust: { - type: [Number, String], - default: 'center', - validator: function (p) { - return (p.constructor === Number) || (['center', 'l', 'r'].includes(p)) - } + default: 'center' }, titleVjust: { - type: [Number, String], - default: 1.05, - validator: function (p) { - return (p.constructor === Number) || (['center', 't', 'b'].includes(p)) - } + default: 1.05 } }, diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index bcb853ce..bc632ef4 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -140,7 +140,7 @@ export default { // TODO ** tickSize: { type: Number, - default: 5 + default: 0.15 }, tickWidth: { @@ -148,7 +148,6 @@ export default { default: 0.5 }, - // New tickPosition: { type: Number, default: 0.5 @@ -159,14 +158,16 @@ export default { default: '' }, - // text-anchor ** titleAnchorPoint: { type: String, default: 'center', validator: p => ['center', 'lb', 'lt', 'rt', 'rb', 'l', 'r', 't', 'b'].includes(p) }, - // titleAngle + titleAngle: { + type: Number, + default: 0 + }, titleColor: { type: String, @@ -195,12 +196,20 @@ export default { default: 1 }, - // TODO ** - titlePadding: { - type: Number, - default: 0 + 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: { @@ -228,6 +237,14 @@ export default { return this.convertCoordinateSpecification(this.aesthetics) }, + tickMin () { + return 0.5 - this.tickSize + }, + + tickMax () { + return 0.5 + this.tickSize + }, + tickData () { if (this.tickValues) { return this.tickValues.map(value => { From f3ba7b7c40c601f0ede015335ccab0587208ba60 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Fri, 25 Jan 2019 17:05:48 +0800 Subject: [PATCH 19/37] feat: preliminary work on auto positioning for axes --- src/components/Guides/XAxis.vue | 42 +++++++++++++++++++++++++++++++++ src/components/Guides/YAxis.vue | 42 +++++++++++++++++++++++++++++++++ src/mixins/Guides/BaseAxis.js | 26 ++++++++++++++++++-- stories/sandbox/TestSymbol.vue | 24 +++++++------------ 4 files changed, 116 insertions(+), 18 deletions(-) diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index abba435e..606d291d 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -143,6 +143,48 @@ export default { return this.titleVjust } }, + + posY () { + let yRange = this.yRange + + let yMin = Math.min(yRange[0], yRange[1]) + let yMax = Math.max(yRange[0], yRange[1]) + + if (this.vjust.constructor === Number) { + let scaledVal = (yMax - yMin) * this.hjust + return scaledVal + } else if (this.vjust === 'center') { + return (yMax - yMin) / 2 + yMin + } else if (this.vjust === 't') { + return yMax + } else { + return yMin + } + }, + + ranges () { + let newRange = {} + + let aesRange = this.convertCoordinateSpecification(this.aesthetics) + + if (aesRange.x1 && aesRange.x2) { + newRange.x1 = aesRange.x1 + newRange.x2 = aesRange.x2 + } else { + newRange.x1 = this.xRange[0] + newRange.x2 = this.xRange[1] + } + + if (aesRange.y1 && aesRange.y2) { + newRange.y1 = aesRange.y1 + newRange.y2 = aesRange.y2 + } else { + newRange.y1 = this.posY - 50 + newRange.y2 = this.posY + } + + return newRange + }, } } diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue index a0e5dab1..5aed6a21 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -144,6 +144,48 @@ export default { return this.titleVjust } }, + + posX () { + let xRange = this.xRange + + let xMin = Math.min(xRange[0], xRange[1]) + let xMax = Math.max(xRange[0], xRange[1]) + + if (this.hjust.constructor === Number) { + let scaledVal = (xMax - xMin) * this.vjust + return scaledVal + } else if (this.hjust === 'center') { + return (xMax - xMin) / 2 + xRange[0] + } else if (this.hjust === 'l') { + return xMin + } else { + return xMax + } + }, + + ranges () { + let newRange = {} + + let aesRange = this.convertCoordinateSpecification(this.aesthetics) + + if (aesRange.x1 && aesRange.x2) { + newRange.x1 = aesRange.x1 + newRange.x2 = aesRange.x2 + } else { + newRange.x1 = this.posX - 50 + newRange.x2 = this.posX + } + + if (aesRange.y1 && aesRange.y2) { + newRange.y1 = aesRange.y1 + newRange.y2 = aesRange.y2 + } else { + newRange.y1 = this.yRange[0] + newRange.y2 = this.yRange[1] + } + + return newRange + }, } } diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index bc632ef4..2a8f6a1f 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -24,6 +24,24 @@ export default { 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, @@ -233,8 +251,12 @@ export default { return this._parsedScalingOptions[2] }, - ranges () { - return this.convertCoordinateSpecification(this.aesthetics) + xRange () { + return this.parentBranch.domains.x + }, + + yRange () { + return this.parentBranch.domains.y }, tickMin () { diff --git a/stories/sandbox/TestSymbol.vue b/stories/sandbox/TestSymbol.vue index 6288def9..9d887d60 100644 --- a/stories/sandbox/TestSymbol.vue +++ b/stories/sandbox/TestSymbol.vue @@ -28,6 +28,14 @@ /> + + + + - - - -
From 058bbe1b2ab5b5eab4d73aef5a6c91b9e6b23ddc Mon Sep 17 00:00:00 2001 From: gracegsy Date: Tue, 29 Jan 2019 13:28:28 +0800 Subject: [PATCH 20/37] fix: hardcode positioning for when axes are on top/right --- src/components/Guides/XAxis.vue | 2 +- src/components/Guides/YAxis.vue | 2 +- stories/sandbox/TestSymbol.vue | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index 606d291d..1a1dda45 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -156,7 +156,7 @@ export default { } else if (this.vjust === 'center') { return (yMax - yMin) / 2 + yMin } else if (this.vjust === 't') { - return yMax + return yMax + 50 } else { return yMin } diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue index 5aed6a21..3437cd42 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -159,7 +159,7 @@ export default { } else if (this.hjust === 'l') { return xMin } else { - return xMax + return xMax + 50 } }, diff --git a/stories/sandbox/TestSymbol.vue b/stories/sandbox/TestSymbol.vue index 9d887d60..e7ababbd 100644 --- a/stories/sandbox/TestSymbol.vue +++ b/stories/sandbox/TestSymbol.vue @@ -30,10 +30,12 @@ From 42155c5e98ddeb42fd32e3f5fc8f9bee769c4edc Mon Sep 17 00:00:00 2001 From: gracegsy Date: Wed, 30 Jan 2019 16:33:48 +0800 Subject: [PATCH 21/37] feat: automatic positioning of axes in nested sections --- src/components/Guides/XAxis.vue | 47 +++++++++++++++------------------ src/components/Guides/YAxis.vue | 43 +++++++++++++----------------- src/mixins/Guides/BaseAxis.js | 16 ++++++++--- stories/index.js | 2 ++ stories/sandbox/Areas.vue | 31 +++++++++------------- stories/sandbox/BarChart.vue | 30 +++++++++------------ stories/sandbox/BinningTest.vue | 30 +++++++++------------ stories/sandbox/PlotLines.vue | 30 +++++++++------------ stories/sandbox/Scatterplot.vue | 28 +++++++++----------- stories/sandbox/TestSymbol.vue | 5 ++-- 10 files changed, 121 insertions(+), 141 deletions(-) diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index 1a1dda45..f6f61952 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -28,7 +28,7 @@ @@ -60,7 +60,7 @@ :x1="tick => tick.value" :y1="0.5" :x2="tick => tick.value" - :y2="flip ? tickMin : tickMax" + :y2="flip ? tickMax : tickMin" :stroke="tickColor" :stroke-opacity="tickOpacity" :stroke-width="tickWidth" @@ -70,7 +70,7 @@ (Scatterplot)) @@ -33,3 +34,4 @@ storiesOf('Sandbox', module) .add('Test: Area Mark', () => (Areas)) .add('MultiLines', () => (MultiLines)) .add('TestSymbol', () => (TestSymbol)) + .add('idcGraphs', () => (idcGraphs)) diff --git a/stories/sandbox/Areas.vue b/stories/sandbox/Areas.vue index b3a91e5d..dd8ee6dc 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 87953629..d800a677 100644 --- a/stories/sandbox/BarChart.vue +++ b/stories/sandbox/BarChart.vue @@ -61,24 +61,20 @@ - + + + - - - + diff --git a/stories/sandbox/BinningTest.vue b/stories/sandbox/BinningTest.vue index 719805b6..5135a803 100644 --- a/stories/sandbox/BinningTest.vue +++ b/stories/sandbox/BinningTest.vue @@ -49,24 +49,20 @@ - + + + - - - + diff --git a/stories/sandbox/PlotLines.vue b/stories/sandbox/PlotLines.vue index 93d02ea0..29637e9f 100644 --- a/stories/sandbox/PlotLines.vue +++ b/stories/sandbox/PlotLines.vue @@ -4,23 +4,6 @@ :height="600" > - - - - - + + + + + diff --git a/stories/sandbox/Scatterplot.vue b/stories/sandbox/Scatterplot.vue index a1902263..9bd85115 100644 --- a/stories/sandbox/Scatterplot.vue +++ b/stories/sandbox/Scatterplot.vue @@ -25,6 +25,18 @@ /> + + + + - - - -
diff --git a/stories/sandbox/TestSymbol.vue b/stories/sandbox/TestSymbol.vue index e7ababbd..60eee5a3 100644 --- a/stories/sandbox/TestSymbol.vue +++ b/stories/sandbox/TestSymbol.vue @@ -30,12 +30,13 @@ From 686e595b30f4af07eb74f438a2bd0a0f306ee636 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Fri, 1 Feb 2019 13:08:05 +0800 Subject: [PATCH 22/37] feat: option to add extra tick at start of axes --- src/components/Guides/XAxis.vue | 11 +++++++++++ src/components/Guides/YAxis.vue | 11 +++++++++++ src/mixins/Guides/BaseAxis.js | 29 +++-------------------------- stories/sandbox/MultiLines.vue | 8 ++++++++ 4 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index f6f61952..1cfde908 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -52,6 +52,17 @@ + + diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue index 349ddcda..8f9c0117 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -53,6 +53,17 @@ + + diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index 99c9a23c..3157d9ac 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -78,8 +78,6 @@ export default { type: String, default: 'black' }, - - // labelFlush (not sure what this is) labelFont: { type: String, @@ -95,26 +93,18 @@ export default { type: [String, Number], default: 'normal' }, - - // labelLimit (also not sure what this is) labelOpacity: { type: Number, default: 1 }, - - // labelOverlap // Distance between tick and label ** labelPadding: { type: Number, default: 0 }, - - // minExtent, maxExtent, offset - // POSITION??? - labelRotate: { type: Boolean, default: false @@ -140,22 +130,16 @@ export default { default: 10 }, - // tickExtra - - // What is this? - tickOffset: { - type: Number, - default: 0 + tickExtra: { + type: Boolean, + default: true }, tickOpacity: { type: Number, default: 1 }, - - // tickRound - // TODO ** tickSize: { type: Number, default: 7 @@ -165,11 +149,6 @@ export default { type: Number, default: 0.5 }, - - tickPosition: { - type: Number, - default: 0.5 - }, title: { type: String, @@ -206,8 +185,6 @@ export default { type: Number, default: 500 }, - - // titleLimit (what is this?) titleOpacity: { type: Number, diff --git a/stories/sandbox/MultiLines.vue b/stories/sandbox/MultiLines.vue index ad5ea674..a69296e4 100644 --- a/stories/sandbox/MultiLines.vue +++ b/stories/sandbox/MultiLines.vue @@ -72,6 +72,14 @@ + + + + From f612245909ef8589953e3d4322dfabfe201b2833 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Mon, 4 Feb 2019 12:50:38 +0800 Subject: [PATCH 23/37] docs: axis docs --- docs/axes/cartesian.md | 78 ++++++++++++++++++++++++++------- src/components/Guides/XAxis.vue | 7 +++ src/mixins/Guides/BaseAxis.js | 19 ++++---- stories/sandbox/TestSymbol.vue | 2 +- 4 files changed, 81 insertions(+), 25 deletions(-) diff --git a/docs/axes/cartesian.md b/docs/axes/cartesian.md index 245505f8..f61a623a 100644 --- a/docs/axes/cartesian.md +++ b/docs/axes/cartesian.md @@ -2,27 +2,75 @@ 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 +### Positioning -### Format Tick Values +| Prop | Required | Regular types | Default | Description | +| ---- | -------- | ---------------- | --------- | --------------------------------------- | +| hjust| false | [Number, String] | 'l' | horizontal position of title | +| vjust| false | [Number, String] | 'b' | vertical position of title | -### Custom Ticks \ No newline at end of file +### Main Line + +| Prop | Required | Regular types | Default | Description | +| -------------- | -------- | ---------------- | --------- | --------------------------------------- | +| domain | false | [Boolean] | true | if true render axis main line | +| domainColor | false | [String] | 'black' | color of main line | +| domainOpacity | false | [Number] | 1 | opacity of main line | +| domainWidth | false | [Number] | 1 | stroke width of main line | + +### Labels + +| Prop | Required | Regular types | Default | Description | +| -------------- | -------- | ------------------ | ----------- | --------------------------------------- | +| labels | false | [Boolean] | true | if true render labels | +| format | false | [String, Function] | undefined | formatting of axis labels | +| labelColor | false | [String] | 'black' | color of labels | +| labelFont | false | [String] | 'Helvetica' | font used for axis labels | +| labelFontSize | false | [Number] | 10 | size of font used for axis labels | +| labelFontWeight| false | [String, Number] | 'normal' | weight of font used for axis labels | +| labelOpacity | false | [Number] | 1 | opacity of labels | +| labelRotate | false | [Boolean] | false | if true rotate labels | + +### Ticks + +| Prop | Required | Regular types | Default | Description | +| -------------- | -------- | ---------------- | ----------- | ---------------------------------------------- | +| ticks | false | [Boolean] | true | if true render ticks | +| tickColor | false | [String] | 'black' | color of ticks | +| 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 | +| tickSize | false | [Number] | 7 | length of ticks | +| tickWidth | false | [Number] | 0.5 | stroke width of ticks | + +### Title + +| Prop | Required | Regular types | Default | Description | +| --------------- | -------- | ---------------- | ----------- | --------------------------------------- | +| titleHjust | false | [String, Number] | depends | position of axis title relative to axis; default -0.08 for x-axis; default 'center' for y-axis | +| titleVjust | false | [String, Number] | depends | position of axis title relative to axis; default 'center' for x-axis; default 1.05 for y-axis | +| 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 | +| titleFont | false | [String] | 'Helvetica' | font used for axis title | +| titleFontSize | false | [Number] | 12 | size of font used for axis title | +| titleFontWeight | false | [String, Number] | 'normal' | weight of font used for axis title | +| titleOpacity | false | [Number] | 1 | opacity of title | diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index 1cfde908..dacd62da 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -159,6 +159,8 @@ export default { let yRange = this.yRange let yDomain = this.yDomain + console.log(yRange, yDomain) + let yMin = Math.min(yRange[0], yRange[1]) let yMax = Math.max(yRange[0], yRange[1]) @@ -166,6 +168,11 @@ export default { let yDomainMax = Math.max(yDomain[0], yDomain[1]) let yHeight = (50 / (yMax - yMin)) * (yDomainMax - yDomainMin) + + if (this.x) { + let val = (yDomainMax - yDomainMin) * this.vjust + yDomainMin + return [scaledVal - yHeight, scaledVal + yHeight] + } if (this.vjust.constructor === Number) { let scaledVal = (yDomainMax - yDomainMin) * this.vjust + yDomainMin diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index 3157d9ac..9860c950 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -11,7 +11,8 @@ export default { props: { scale: { type: [Array, String, Object, undefined], - default: undefined + default: undefined, + required: true }, format: { @@ -100,10 +101,10 @@ export default { }, // Distance between tick and label ** - labelPadding: { - type: Number, - default: 0 - }, + // labelPadding: { + // type: Number, + // default: 0 + // }, labelRotate: { type: Boolean, @@ -161,10 +162,10 @@ export default { validator: p => ['center', 'lb', 'lt', 'rt', 'rb', 'l', 'r', 't', 'b'].includes(p) }, - titleAngle: { - type: Number, - default: 0 - }, + // titleAngle: { + // type: Number, + // default: 0 + // }, titleColor: { type: String, diff --git a/stories/sandbox/TestSymbol.vue b/stories/sandbox/TestSymbol.vue index 60eee5a3..d9be1441 100644 --- a/stories/sandbox/TestSymbol.vue +++ b/stories/sandbox/TestSymbol.vue @@ -29,7 +29,7 @@ From 582937a605b0436406fadc2760323fcfc99f4d3d Mon Sep 17 00:00:00 2001 From: gracegsy Date: Thu, 7 Feb 2019 12:07:56 +0800 Subject: [PATCH 24/37] refactor: extraTick logic added to tickData() --- src/components/Guides/XAxis.vue | 4 ++-- src/mixins/Guides/BaseAxis.js | 27 ++++++++++++++++++++--- stories/sandbox/TestCategoricalDomain.vue | 9 ++++++-- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index fb185cab..4d0ad561 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -53,7 +53,7 @@ class="x-axis-data" > - + /> --> diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index db1e1d6f..a514e453 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -250,8 +250,17 @@ export default { }, 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 { @@ -259,7 +268,13 @@ export default { let format = this.format && this.format.constructor === Function ? this.format : x => x if (this._domainType === 'quantitative') { - ticks = arrayTicks(...this._domain, this.tickCount).map(value => { + newTickValues = arrayTicks(...this._domain, this.tickCount) + + if (this.tickExtra && newTickValues[0] != firstValue) { + newTickValues.unshift(firstValue) + } + + ticks = newTickValues.map(value => { return { value, label: format(value) } }) } @@ -279,7 +294,13 @@ 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 => { let date = new Date(value) return { value: date, label: format(date) } }) diff --git a/stories/sandbox/TestCategoricalDomain.vue b/stories/sandbox/TestCategoricalDomain.vue index 8877edaf..9933c03c 100644 --- a/stories/sandbox/TestCategoricalDomain.vue +++ b/stories/sandbox/TestCategoricalDomain.vue @@ -36,16 +36,21 @@ ]" /> + + - + /> --> From 10673a289c69eee035152a80f88116f0a891f445 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Fri, 8 Feb 2019 13:18:28 +0800 Subject: [PATCH 25/37] fix: nested axes now accurately sized and positioned --- src/components/Guides/XAxis.vue | 33 +++++------------- src/components/Guides/YAxis.vue | 26 +++++--------- src/mixins/Guides/BaseAxis.js | 61 +++++++++++++++++++++++++++++---- stories/sandbox/MultiLines.vue | 3 ++ 4 files changed, 75 insertions(+), 48 deletions(-) diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index 4d0ad561..97c24013 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -53,17 +53,6 @@ class="x-axis-data" > - - @@ -157,21 +146,12 @@ export default { }, posY () { - let yRange = this.yRange let yDomain = this.yDomain - let yMin = Math.min(yRange[0], yRange[1]) - let yMax = Math.max(yRange[0], yRange[1]) - let yDomainMin = Math.min(yDomain[0], yDomain[1]) let yDomainMax = Math.max(yDomain[0], yDomain[1]) - let yHeight = (50 / (yMax - yMin)) * (yDomainMax - yDomainMin) - - if (this.x) { - let val = (yDomainMax - yDomainMin) * this.vjust + yDomainMin - return [scaledVal - yHeight, scaledVal + yHeight] - } + let yHeight = this.getLocalY(50) if (this.vjust.constructor === Number) { let scaledVal = (yDomainMax - yDomainMin) * this.vjust + yDomainMin @@ -189,12 +169,17 @@ export default { ranges () { let newRange = {} - newRange.x1 = this.xDomain[0] - newRange.x2 = this.xDomain[1] - newRange.y1 = this.posY[0] newRange.y2 = this.posY[1] + 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 a801caa9..3a140c9d 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -53,17 +53,6 @@ class="y-axis-data" > - - @@ -157,16 +146,12 @@ export default { }, posX () { - let xRange = this.xRange let xDomain = this.xDomain - let xMin = Math.min(xRange[0], xRange[1]) - let xMax = Math.max(xRange[0], xRange[1]) - let xDomainMin = Math.min(xDomain[0], xDomain[1]) let xDomainMax = Math.max(xDomain[0], xDomain[1]) - let xWidth = (50 / (xMax - xMin)) * (xDomainMax - xDomainMin) + let xWidth = this.getLocalX(50) if (this.hjust.constructor === Number) { let scaledVal = (xDomainMax - xDomainMin) * this.hjust + xDomainMin @@ -187,8 +172,13 @@ export default { newRange.x1 = this.posX[0] newRange.x2 = this.posX[1] - newRange.y1 = this.yDomain[0] - newRange.y2 = this.yDomain[1] + 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/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index a514e453..5041ab90 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -208,6 +208,59 @@ export default { }, + methods: { + // Get parents + getParents (b, result) { + if (b.parentID != null) { + let parentBranch = this.$$coordinateTree.getBranch(b.parentID) + result.unshift(parentBranch) + return this.getParents(parentBranch, result) + } else { + return result + } + }, + + getLocalX (n) { + let p = this._parentNodes + let result = n + for (let i = 0; i < p.length; i++) { + let b = p[i] + let bRange = b.ranges.x + let bDomain = b.domains.x + + let rangeMin = Math.min(bRange[0], bRange[1]) + let rangeMax = Math.max(bRange[0], bRange[1]) + + let domainMin = Math.min(bDomain[0], bDomain[1]) + let domainMax = Math.max(bDomain[0], bDomain[1]) + + result = (result/ (rangeMax - rangeMin)) * (domainMax - domainMin) + } + + return result + }, + + getLocalY (n) { + let p = this._parentNodes + let result = n + for (let i = 0; i < p.length; i++) { + let b = p[i] + let bRange = b.ranges.y + let bDomain = b.domains.y + + let rangeMin = Math.min(bRange[0], bRange[1]) + let rangeMax = Math.max(bRange[0], bRange[1]) + + let domainMin = Math.min(bDomain[0], bDomain[1]) + let domainMax = Math.max(bDomain[0], bDomain[1]) + + result = (result / (rangeMax - rangeMin)) * (domainMax - domainMin) + } + + return result + } + }, + computed: { _parsedScalingOptions () { return parseScaleOptions(this.scale, this.$$dataInterface, this.$$scaleManager) @@ -225,12 +278,8 @@ export default { return this._parsedScalingOptions[2] }, - xRange () { - return this.parentBranch.ranges.x - }, - - yRange () { - return this.parentBranch.ranges.y + _parentNodes () { + return this.getParents(this.parentBranch, [this.parentBranch]) }, xDomain () { diff --git a/stories/sandbox/MultiLines.vue b/stories/sandbox/MultiLines.vue index f566f3a8..87d2ddfb 100644 --- a/stories/sandbox/MultiLines.vue +++ b/stories/sandbox/MultiLines.vue @@ -71,10 +71,13 @@ From bc19c47e508034d35bcc7467adc601d17f2fdde0 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Fri, 8 Feb 2019 13:40:28 +0800 Subject: [PATCH 26/37] feat: additional axis positioning options using x, y, x1, x2, y1, y2 --- src/components/Guides/XAxis.vue | 41 +++++++++++++++++++++++++++++++-- src/components/Guides/YAxis.vue | 41 +++++++++++++++++++++++++++++++-- src/mixins/Guides/BaseAxis.js | 8 ------- 3 files changed, 78 insertions(+), 12 deletions(-) diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index 97c24013..6a328d73 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -145,13 +145,40 @@ export default { } }, + tickMin () { + if (this.y1 && this.y2) { + return 0.5 - (this.tickSize / (this.y2 - this.y1)) + } else { + return 0.5 - (this.tickSize / 100) + } + }, + + tickMax () { + if (this.y1 && this.y2) { + return 0.5 + (this.tickSize / (this.y2 - this.y1)) + } else { + return 0.5 + (this.tickSize / 100) + } + }, + posY () { + let yHeight = this.getLocalY(50) + + if (this.y) { + let scaledY = this.getLocalY(this.y) + return [scaledY - yHeight, scaledY + yHeight] + } + + if (this.y1 && this.y2) { + return [this.getLocalY(this.y1), this.getLocalY(this.y2)] + } else if (this.y1 ^ this.y2) { + throw new Error ('Please provide both y1 and y2 coordinates. Alternatively use the y prop') + } + 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) if (this.vjust.constructor === Number) { let scaledVal = (yDomainMax - yDomainMin) * this.vjust + yDomainMin @@ -172,6 +199,16 @@ export default { newRange.y1 = this.posY[0] newRange.y2 = this.posY[1] + if (this.x1 && this.x2) { + newRange.x1 = this.getLocalX(this.x1) + newRange.x2 = this.getLocalX(this.x2) + return newRange + } else if (this.x1 ^ this.x2) { + throw new Error ('Please provide both x1 and x2 coordinates') + } else if (this.x) { + throw new Error('Please provide x1, x2 start and end coordinates') + } + if (this._domainType === 'temporal') { newRange.x1 = this._domain[0] newRange.x2 = this._domain[1] diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue index 3a140c9d..8fdfc253 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -145,14 +145,41 @@ export default { } }, + tickMin () { + if (this.x1 && this.x2) { + return 0.5 - (this.tickSize / (this.x2 - this.x1)) + } else { + return 0.5 - (this.tickSize / 100) + } + }, + + tickMax () { + if (this.x1 && this.x2) { + return 0.5 + (this.tickSize / (this.x2 - this.x1)) + } else { + return 0.5 + (this.tickSize / 100) + } + }, + posX () { + let xWidth = this.getLocalX(50) + + if (this.x) { + let scaledX = this.getLocalX(this.x) + return [scaledX - xWidth, scaledX + xWidth] + } + + if (this.x1 && this.x2) { + return [this.getLocalX(this.x1), this.getLocalX(this.x2)] + } else if (this.x1 ^ this.x2) { + throw new Error ('Please provide both x1 and x2 coordinates. Alternatively use the x prop') + } + 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) - if (this.hjust.constructor === Number) { let scaledVal = (xDomainMax - xDomainMin) * this.hjust + xDomainMin return [scaledVal - xWidth, scaledVal + xWidth] @@ -172,6 +199,16 @@ export default { newRange.x1 = this.posX[0] newRange.x2 = this.posX[1] + if (this.y1 && this.y2) { + newRange.y1 = this.getLocalY(this.y1) + newRange.y2 = this.getLocalY(this.y2) + return newRange + } else if (this.y1 ^ this.y2) { + throw new Error ('Please provide both y1 and y2 coordinates') + } else if (this.y) { + throw new Error('Please provide y1, y2 start and end coordinates') + } + if (this._domainType === 'temporal') { newRange.y1 = this._domain[0] newRange.y2 = this._domain[1] diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index 5041ab90..734778b5 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -290,14 +290,6 @@ export default { return this.parentBranch.domains.y }, - tickMin () { - return 0.5 - (this.tickSize / 100) - }, - - tickMax () { - return 0.5 + (this.tickSize / 100) - }, - tickData () { let firstValue = this._domain[0] let newTickValues From 3382f5eb7969b73cd92a679377fa5240e7eec68a Mon Sep 17 00:00:00 2001 From: gracegsy Date: Fri, 8 Feb 2019 14:55:41 +0800 Subject: [PATCH 27/37] docs: update axis docs, add examples --- docs/.vuepress/components/Cartesian.vue | 145 +++++++++++++++++++ docs/.vuepress/components/SymbolMarkDemo.vue | 39 ++--- docs/axes/cartesian.md | 123 ++++++++++------ docs/marks/symbol.md | 4 +- 4 files changed, 240 insertions(+), 71 deletions(-) create mode 100644 docs/.vuepress/components/Cartesian.vue diff --git a/docs/.vuepress/components/Cartesian.vue b/docs/.vuepress/components/Cartesian.vue new file mode 100644 index 00000000..a3543ba1 --- /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 aae8b6ff..869be3cf 100644 --- a/docs/.vuepress/components/SymbolMarkDemo.vue +++ b/docs/.vuepress/components/SymbolMarkDemo.vue @@ -16,25 +16,28 @@ >>>>>> fb380af3d73f710f2d5cebefa401975448ebd89e :size="16" :shape="shape" :stroke="stroke" :fill="fill" -<<<<<<< HEAD - :strokeWidth="1" -======= :stroke-width="1" ->>>>>>> fb380af3d73f710f2d5cebefa401975448ebd89e /> + + + + + - - - -
@@ -111,7 +98,7 @@ export default { computed : { fill () { if (this.color === 'both' || this.color === 'fill') { - return { scale: { scale: 'viridis', variable: 'explanatory' } } + return { get: 'explanatory', scale: { type: 'viridis', domain: 'explanatory' } } } else { return 'none' } diff --git a/docs/axes/cartesian.md b/docs/axes/cartesian.md index f61a623a..7b7f6c2f 100644 --- a/docs/axes/cartesian.md +++ b/docs/axes/cartesian.md @@ -19,58 +19,97 @@ Axes are used as reference scales for values in the graph. Each axis is typicall | 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 | -### Positioning +### X Axis Positioning -| Prop | Required | Regular types | Default | Description | -| ---- | -------- | ---------------- | --------- | --------------------------------------- | -| hjust| false | [Number, String] | 'l' | horizontal position of title | -| vjust| false | [Number, String] | 'b' | vertical position of title | +There are three options for positioning the x axis on the graph. The `y` prop takes precedence, followed by `y1` and `y2`, lastly `vjust` encodes default behavior. + +When using `y` or `vjust`, the x axis defaults to a height of 100px. + +| 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 | Screen pixels | +| y1 | false | [Number] | undefined | starting y coordinate of x axis | Screen pixels | +| y2 | false | [Number] | undefined | ending y coordinate of x axis | Screen pixels | + +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 | Screen pixels | +| x2 | false | [Number] | undefined | ending x coordinate of x axis | Screen pixels | + + + +### Y Axis Positioning + +Similar to the x axis, there are three options for positioning the y axis on the graph. The `x` prop takes precedence, followed by `x1` and `x2`, lastly `hjust` encodes default behavior. + +When using `x` or `hjust`, the y axis defaults to a width of 100px. + +| 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 | Screen pixels | +| x1 | false | [Number] | undefined | starting x coordinate of y axis | Screen pixels | +| x2 | false | [Number] | undefined | ending x coordinate of y axis | Screen pixels | + +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 | Screen pixels | +| y2 | false | [Number] | undefined | ending y coordinate of y axis | Screen pixels | + + ### Main Line -| Prop | Required | Regular types | Default | Description | -| -------------- | -------- | ---------------- | --------- | --------------------------------------- | -| domain | false | [Boolean] | true | if true render axis main line | -| domainColor | false | [String] | 'black' | color of main line | -| domainOpacity | false | [Number] | 1 | opacity of main line | -| domainWidth | false | [Number] | 1 | stroke width of 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 -| Prop | Required | Regular types | Default | Description | -| -------------- | -------- | ------------------ | ----------- | --------------------------------------- | -| labels | false | [Boolean] | true | if true render labels | -| format | false | [String, Function] | undefined | formatting of axis labels | -| labelColor | false | [String] | 'black' | color of labels | -| labelFont | false | [String] | 'Helvetica' | font used for axis labels | -| labelFontSize | false | [Number] | 10 | size of font used for axis labels | -| labelFontWeight| false | [String, Number] | 'normal' | weight of font used for axis labels | -| labelOpacity | false | [Number] | 1 | opacity of labels | -| labelRotate | false | [Boolean] | false | if true rotate labels | +| 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 | -| -------------- | -------- | ---------------- | ----------- | ---------------------------------------------- | -| ticks | false | [Boolean] | true | if true render ticks | -| tickColor | false | [String] | 'black' | color of ticks | -| 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 | -| tickSize | false | [Number] | 7 | length of ticks | -| tickWidth | false | [Number] | 0.5 | stroke width of 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 | -| --------------- | -------- | ---------------- | ----------- | --------------------------------------- | -| titleHjust | false | [String, Number] | depends | position of axis title relative to axis; default -0.08 for x-axis; default 'center' for y-axis | -| titleVjust | false | [String, Number] | depends | position of axis title relative to axis; default 'center' for x-axis; default 1.05 for y-axis | -| 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 | -| titleFont | false | [String] | 'Helvetica' | font used for axis title | -| titleFontSize | false | [Number] | 12 | size of font used for axis title | -| titleFontWeight | false | [String, Number] | 'normal' | weight of font used for axis title | -| titleOpacity | false | [Number] | 1 | opacity of 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 | + + diff --git a/docs/marks/symbol.md b/docs/marks/symbol.md index 239782eb..a490ba29 100644 --- a/docs/marks/symbol.md +++ b/docs/marks/symbol.md @@ -4,11 +4,9 @@ title: Symbol Mark # Component tag -<<<<<<< HEAD `` -======= + `` ->>>>>>> fb380af3d73f710f2d5cebefa401975448ebd89e # Description From 18cf772bad150987298475bcf8b4ed193f695693 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Mon, 11 Feb 2019 11:33:43 +0800 Subject: [PATCH 28/37] fix: convert vgg-symbol to vgg-point --- stories/sandbox/BarChart.vue | 4 ++-- stories/sandbox/NestedCoordinateSystem.vue | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stories/sandbox/BarChart.vue b/stories/sandbox/BarChart.vue index 6c794471..8a35e9bb 100644 --- a/stories/sandbox/BarChart.vue +++ b/stories/sandbox/BarChart.vue @@ -55,10 +55,10 @@ color="white" /> - diff --git a/stories/sandbox/NestedCoordinateSystem.vue b/stories/sandbox/NestedCoordinateSystem.vue index 462fe546..9a38ecdd 100644 --- a/stories/sandbox/NestedCoordinateSystem.vue +++ b/stories/sandbox/NestedCoordinateSystem.vue @@ -27,13 +27,13 @@ :scale-y="domains.y" > - Date: Thu, 14 Feb 2019 12:50:32 +0800 Subject: [PATCH 29/37] feat: rendering of label for extraTick can now be toggled --- docs/axes/cartesian.md | 2 ++ src/mixins/Guides/BaseAxis.js | 28 +++++++++++++++++++++++----- stories/sandbox/TestSymbol.vue | 3 ++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/docs/axes/cartesian.md b/docs/axes/cartesian.md index 7b7f6c2f..a9e6be62 100644 --- a/docs/axes/cartesian.md +++ b/docs/axes/cartesian.md @@ -74,6 +74,8 @@ By default the y axis spans the entire height of the section. To customize the h ### 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 | | diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index ac3c6982..6c94aff9 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -138,6 +138,11 @@ export default { default: true }, + tickExtraLabel: { + type: Boolean, + default: true + }, + tickOpacity: { type: Number, default: 1 @@ -308,7 +313,7 @@ export default { }) } else { let ticks - let format = this.format && this.format.constructor === Function ? this.format : x => x + let format = this.format && this.format.constructor === Function ? this.format : x => x.toString() if (this._domainType === 'quantitative') { newTickValues = arrayTicks(...this._domain, this.tickCount) @@ -317,8 +322,14 @@ export default { newTickValues.unshift(firstValue) } - ticks = newTickValues.map(value => { - return { value, label: format(value) } + ticks = newTickValues.map((value, i) => { + if (i === 0 && this.tickExtra && this.tickExtraLabel) { + return { value, label: format(value) } + } else if (i != 0) { + return { value, label: format(value) } + } else { + return { value, label: '' } + } }) } @@ -343,9 +354,16 @@ export default { newTickValues.unshift(firstValue) } - ticks = newTickValues.map(value => { + 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: format(date) } + } else if (i != 0) { + return { value: date, label: format(date) } + } else { + return { value, label: '' } + } }) } diff --git a/stories/sandbox/TestSymbol.vue b/stories/sandbox/TestSymbol.vue index 07ada3d9..1950392e 100644 --- a/stories/sandbox/TestSymbol.vue +++ b/stories/sandbox/TestSymbol.vue @@ -37,6 +37,7 @@ @@ -47,7 +48,7 @@ :x2="500" :y1="100" :y2="500" - :scale="'explanatory'" + :scale="[0, 150]" /> Date: Thu, 14 Feb 2019 16:24:17 +0800 Subject: [PATCH 30/37] fix: coordinate tree updates now only apply to branch and its children --- src/classes/CoordinateTree/CoordinateTree.js | 10 +++------- src/mixins/Marks/Mark.js | 3 ++- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/classes/CoordinateTree/CoordinateTree.js b/src/classes/CoordinateTree/CoordinateTree.js index 88fc04e2..d98af56a 100644 --- a/src/classes/CoordinateTree/CoordinateTree.js +++ b/src/classes/CoordinateTree/CoordinateTree.js @@ -2,7 +2,6 @@ export default class CoordinateTree { constructor () { this._coordinateTree = null this._branchPaths = {} - this._update = 1 } setRoot (coordinateTransformation) { @@ -17,8 +16,6 @@ export default class CoordinateTree { let parentBranchPath = this._branchPaths[parentID] this._branchPaths[id] = [...parentBranchPath, id] - - this._update++ } getBranch (id) { @@ -35,8 +32,6 @@ export default class CoordinateTree { updateBranch (id, coordinateTransformation) { let branch = this.getBranch(id) branch.update(coordinateTransformation) - - this._update++ } removeBranch (id) { @@ -61,8 +56,6 @@ export default class CoordinateTree { } } } - - this._update++ } getTotalTransformation (id) { @@ -86,6 +79,7 @@ class Branch { constructor (id, parentID, coordinateTransformation) { this.id = id this.parentID = parentID + this.updateCount = 1 this.update(coordinateTransformation) @@ -96,5 +90,7 @@ class Branch { for (let key in coordinateTransformation) { this[key] = coordinateTransformation[key] } + + this.updateCount += 1 } } diff --git a/src/mixins/Marks/Mark.js b/src/mixins/Marks/Mark.js index 3b03473b..6eb0a512 100644 --- a/src/mixins/Marks/Mark.js +++ b/src/mixins/Marks/Mark.js @@ -15,7 +15,8 @@ export default { computed: { __update () { - return this.$$coordinateTree._update + return this.parentBranch.updateCount + // return this.$$coordinateTree._update }, _interpolate () { From 7e17667ee72a68d3df643132af7e132189a4994f Mon Sep 17 00:00:00 2001 From: gracegsy Date: Thu, 14 Feb 2019 16:47:39 +0800 Subject: [PATCH 31/37] chore: minor changes to default behavior in axes and scales --- src/mixins/Guides/BaseAxis.js | 2 +- src/scales/shorthands/coords/quantitative.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index 6c94aff9..a3d77ff1 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -140,7 +140,7 @@ export default { tickExtraLabel: { type: Boolean, - default: true + default: false }, tickOpacity: { diff --git a/src/scales/shorthands/coords/quantitative.js b/src/scales/shorthands/coords/quantitative.js index b9456763..0467046c 100644 --- a/src/scales/shorthands/coords/quantitative.js +++ b/src/scales/shorthands/coords/quantitative.js @@ -9,6 +9,9 @@ export default { } function linear (domain, range) { + if (domain[0] === range[0] && domain[1] === range[1]) { + return input => { return input } + } return d3.scaleLinear().domain(domain).range(range) } From f48b732e8f978cead0d8855da8c3d9f7ebd05d75 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Tue, 26 Feb 2019 11:34:10 +0800 Subject: [PATCH 32/37] fix: more robust logic for positioning and sizing axes using screen coordinates --- .../components/MappedSectionsGrid.vue | 32 +++++ .../components/ScatterplotMatrix.vue | 45 +++++++ docs/.vuepress/components/SectionsGrid.vue | 27 ++++ docs/core/grid.md | 127 ++++++++++++++++++ docs/core/repeat.md | 74 ++++++++++ .../CoordinateTransformation.js | 7 + src/classes/CoordinateTree/CoordinateTree.js | 33 +++++ src/components/Core/Grid.vue | 92 +++++++++++++ src/components/Core/Repeat.vue | 50 +++++++ src/components/Core/Section.vue | 8 +- src/components/Core/utils/grid.js | 109 +++++++++++++++ src/components/Core/utils/repeat.js | 39 ++++++ src/components/Guides/XAxis.vue | 42 ++---- src/components/Guides/YAxis.vue | 42 ++---- src/mixins/CoordinateSystem.js | 4 +- src/mixins/CoordinateTreeUser.js | 22 ++- src/mixins/Guides/BaseAxis.js | 52 ++----- src/mixins/Guides/defaultFormat.js | 28 ++++ src/mixins/Marks/Mark.js | 3 +- src/scales/shorthands/coords/quantitative.js | 3 - src/scales/utils/getPrimitive.js | 5 + stories/sandbox/MappingGridLayout.vue | 35 +++++ stories/sandbox/RepeatLayout.vue | 45 +++++++ stories/sandbox/Scatterplot.vue | 22 ++- stories/sandbox/SimpleGridLayout.vue | 52 +++++++ 25 files changed, 887 insertions(+), 111 deletions(-) create mode 100644 docs/.vuepress/components/MappedSectionsGrid.vue create mode 100644 docs/.vuepress/components/ScatterplotMatrix.vue create mode 100644 docs/.vuepress/components/SectionsGrid.vue create mode 100644 docs/core/grid.md create mode 100644 docs/core/repeat.md create mode 100644 src/components/Core/Grid.vue create mode 100644 src/components/Core/Repeat.vue create mode 100644 src/components/Core/utils/grid.js create mode 100644 src/components/Core/utils/repeat.js create mode 100644 src/mixins/Guides/defaultFormat.js create mode 100644 src/scales/utils/getPrimitive.js create mode 100644 stories/sandbox/MappingGridLayout.vue create mode 100644 stories/sandbox/RepeatLayout.vue create mode 100644 stories/sandbox/SimpleGridLayout.vue diff --git a/docs/.vuepress/components/MappedSectionsGrid.vue b/docs/.vuepress/components/MappedSectionsGrid.vue new file mode 100644 index 00000000..1d9e8977 --- /dev/null +++ b/docs/.vuepress/components/MappedSectionsGrid.vue @@ -0,0 +1,32 @@ + diff --git a/docs/.vuepress/components/ScatterplotMatrix.vue b/docs/.vuepress/components/ScatterplotMatrix.vue new file mode 100644 index 00000000..aa05c10e --- /dev/null +++ b/docs/.vuepress/components/ScatterplotMatrix.vue @@ -0,0 +1,45 @@ + + + diff --git a/docs/.vuepress/components/SectionsGrid.vue b/docs/.vuepress/components/SectionsGrid.vue new file mode 100644 index 00000000..181d8ea4 --- /dev/null +++ b/docs/.vuepress/components/SectionsGrid.vue @@ -0,0 +1,27 @@ + diff --git a/docs/core/grid.md b/docs/core/grid.md new file mode 100644 index 00000000..16ef8e6e --- /dev/null +++ b/docs/core/grid.md @@ -0,0 +1,127 @@ +--- +title: 'Grid' +--- + +# Component tag + +`` + +# Description + +The Grid component is used to quickly position and align [Section](./section.md) +components in a grid format. + +# Props + +| Prop | Required | Types | Default | Description | +| -------------- | -------- | ---------------- | --------- | ----------------------------------------- | +| rows | depends | Number | undefined | Max. number of rows the grid can have | +| cols | depends | Number | undefined | Max. number olf columns the grid can have | +| layout-padding | false | [Number, Object] | 0 | Padding with respect to parent element | +| cell-padding | false | [Number, Object] | 0 | Padding between child elements | + +The Grid component requires either the `rows`, _or_ the `cols` prop. If you use both, +or neither, the component will throw an error. The number given to `rows` or `cols` +will be the maximum number of respectively rows or columns that the grid will be +allowed to have. So, let's say that we set the `rows` to 3, and we use the Grid +component to position 5 Section components. This will give us a grid of three +rows, and 2 columns, with the 5 Sections positioned to 5 grid cells and one grid +cell left empty (see [positioning sections](#positioning-sections) below). + +`layout-padding` and `cell-padding` can both take either a number, or an object +of the following form: + +```js +{ + l: ..., + r: ..., + b: ..., + t: ... +} +``` + +where `l`, `r`, `b` and `t` are all optional. + +There are two main ways of using the Grid component: + +1. A number of Sections can be put into the Grid directly, manually or with `v-for` +2. A number of Sections can be created with the [Map](./map.md) component + +Both will be discussed below. + +# Usage + +### Positioning Sections + +When placing the Section components directly into the Grid component, all the +Section's coordinate props (`x1`, `y2`, `w`, etc.) must be left out- these +will automatically be determined by the Grid component. Note that the positioning +starts from the bottom left, and that rows will be filled out before columns. +See the example below: + +::: v-pre +```html + + + + + + + + + +``` +::: + + + +### Position Sections with the Map component + +The Grid component can also be used in combination with the Map component. +See the example below, where we create one Section for each row in the data, +which are scaled and positioned into a grid layout automatically: + +::: v-pre +```html + + + + + + + + + + + + + + + + + +``` +::: + + diff --git a/docs/core/repeat.md b/docs/core/repeat.md new file mode 100644 index 00000000..6e0b1403 --- /dev/null +++ b/docs/core/repeat.md @@ -0,0 +1,74 @@ +--- +title: 'Repeat' +--- + +# Component tag + +`` + +# Description + +The Repeat component is used to quickly position and align [Section](./section.md) +components in a 2d matrix format. + +# Props + +| Prop | Required | Types | Default | Description | +| -------------- | -------- | ---------------- | --------- | -------------------------------------- | +| x | depends | Array | undefined | Values corresponding to matrix columns | +| y | depends | Array | undefined | Values corresponding to matrix rows | +| layout-padding | false | [Number, Object] | 0 | Padding with respect to parent element | +| cell-padding | false | [Number, Object] | 0 | Padding between child elements | + +The repeat component is useful for quickly creating a 2d matrix of Sections. This +is useful for creating, for example, a [scatterplot matrix](#scatterplot-matrix). + +Either the `x` prop, `y` prop, or both the `x` and `y` props are required. +The `x` and `y` props take an Array of values. For every entry in the Array passed +to the `x` prop, one column will be rendered- the same for the `y` prop and rows. +Besides creating one Section for each matrix cell and positioning the Section (like +the [Grid](./grid.md) component), the Repeat component also exposes the values +that are in the Arrays passed to `x` and `y`. + +The `layout-padding` and `cell-padding` props work exactly the same as props +of the same names used in the [Grid](./grid.md#props) component. + +# Usage + +### Scatterplot matrix + +In this example, `someData` is a data structure with three columns of quantitative +data, called `a`, `b` and `c`. + +::: v-pre +```html + + + + + + + + + + + + + + + + + +``` +::: + + diff --git a/src/classes/CoordinateTree/CoordinateTransformation.js b/src/classes/CoordinateTree/CoordinateTransformation.js index fc583c5d..068b13c9 100644 --- a/src/classes/CoordinateTree/CoordinateTransformation.js +++ b/src/classes/CoordinateTree/CoordinateTransformation.js @@ -66,13 +66,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') { @@ -122,6 +126,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..27514d6d 100644 --- a/src/classes/CoordinateTree/CoordinateTree.js +++ b/src/classes/CoordinateTree/CoordinateTree.js @@ -73,6 +73,39 @@ export default class CoordinateTree { return transformation.bind(this) } + + getLocalX (id) { + let transformation = function (x) { + let branchParents = this._branchPaths[id] + let result = x + + 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 + + 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/Grid.vue b/src/components/Core/Grid.vue new file mode 100644 index 00000000..1ddddd4b --- /dev/null +++ b/src/components/Core/Grid.vue @@ -0,0 +1,92 @@ + diff --git a/src/components/Core/Repeat.vue b/src/components/Core/Repeat.vue new file mode 100644 index 00000000..4da56b1c --- /dev/null +++ b/src/components/Core/Repeat.vue @@ -0,0 +1,50 @@ + diff --git a/src/components/Core/Section.vue b/src/components/Core/Section.vue index bda36150..e618c175 100644 --- a/src/components/Core/Section.vue +++ b/src/components/Core/Section.vue @@ -158,11 +158,11 @@ export default { id = '_' + randomID() } return id - } + }, }, watch: { - transformation: 'updateCoordinateTreeBranch' + transformation: 'updateCoordinateTreeBranch', }, beforeDestroy () { @@ -205,8 +205,10 @@ export default { provide () { let $$transform = this.$$coordinateTree.getTotalTransformation(this.coordinateTreeBranchID) let $$coordinateTreeParent = this.coordinateTreeBranchID + let $$getLocalX = this.$$coordinateTree.getLocalX(this.coordinateTreeBranchID) + let $$getLocalY = this.$$coordinateTree.getLocalY(this.coordinateTreeBranchID) - return { $$transform, $$coordinateTreeParent, $$map: false } + return { $$transform, $$coordinateTreeParent, $$map: false, $$getLocalX, $$getLocalY } } } diff --git a/src/components/Core/utils/grid.js b/src/components/Core/utils/grid.js new file mode 100644 index 00000000..a2607c85 --- /dev/null +++ b/src/components/Core/utils/grid.js @@ -0,0 +1,109 @@ +import Section from '../Section.vue' + +export function validateGridOptions (options) { + let hasRows = options.rows !== undefined + let hasCols = options.cols !== undefined + if (hasRows && hasCols) { throw new Error('Cannot have both rows and cols') } + if (!hasRows && !hasCols) { + throw new Error('Layout must have either rows or cols specified') + } + if (hasCols && options.cols < 1) { throw new Error('Cols must be higher than 0') } + if (hasRows && options.rows < 1) { throw new Error('Rows must be higher than 0') } +} + +export function calculateRowsCols (options, numberOfCells) { + let rows + let cols + + if (options.cols) { + rows = Math.ceil(numberOfCells / options.cols) + cols = options.cols + } + + if (options.rows) { + rows = options.rows + cols = Math.ceil(numberOfCells / options.rows) + } + + return { rows, cols } +} + +export function calculateGridLayout (rows, cols, options, ranges) { + let lP = getPadding(options.layoutPadding) + let cP = getPadding(options.cellPadding) + + let left = ranges.x[0] + lP.l + let right = ranges.x[1] - lP.r + let bottom = ranges.y[0] + lP.b + let top = ranges.y[1] - lP.t + + let width = right - left + let height = top - bottom + + let cellWidth = width / cols + let cellHeight = height / rows + + let cells = [] + + for (let rowIndex = 0; rowIndex < rows; rowIndex++) { + for (let colIndex = 0; colIndex < cols; colIndex++) { + let x1 = left + colIndex * cellWidth + cP.l + let x2 = x1 + cellWidth - cP.l - cP.r + let y1 = bottom + rowIndex * cellHeight + cP.b + let y2 = y1 + cellHeight - cP.b - cP.t + + cells.push({ x1, x2, y1, y2 }) + } + } + + return cells +} + +export function updateGridSections (createElement, sections, gridLayout) { + let newSections = [] + for (let i = 0; i < sections.length; i++) { + let section = sections[i] + let layout = gridLayout[i] + newSections.push(updateSection(createElement, section, layout)) + } + + return newSections +} + +function getPadding (padding) { + let paddings = { + l: 0, + r: 0, + t: 0, + b: 0 + } + + if (!padding) return paddings + + if (padding.constructor === Number) { + for (let key in paddings) { paddings[key] = padding } + } + + if (padding.constructor === Object) { + for (let key in padding) { paddings[key] = padding[key] } + } + + return paddings +} + +export function updateSection (createElement, section, layout) { + let props = mergeProps(layout, section.componentOptions.propsData) + let slots = section.componentOptions.children + let newSection = createElement(Section, { props }, slots) + return newSection +} + +function mergeProps (coords, other) { + for (let key in other) { + if (!['x1', 'x2', 'y1', 'y2', 'x', 'y', 'w', 'h'].includes(key)) { + coords[key] = other[key] + } + } + + return coords +} diff --git a/src/components/Core/utils/repeat.js b/src/components/Core/utils/repeat.js new file mode 100644 index 00000000..55f00706 --- /dev/null +++ b/src/components/Core/utils/repeat.js @@ -0,0 +1,39 @@ +import { updateSection } from './grid.js' + +export function repeatSections (createElement, slot, layout, xValues, yValues) { + let newSections = [] + + for (let rowIndex = 0; rowIndex < yValues.length; rowIndex++) { + let y = yValues[rowIndex] + for (let colIndex = 0; colIndex < xValues.length; colIndex++) { + let x = xValues[colIndex] + let slotContent = slot({ x, y }) + let sections = validateSlotContent(slotContent) + + let layoutIndex = (rowIndex * xValues.length) + colIndex + let currentLayout = layout[layoutIndex] + + let updatedSections = sections.map(section => { + return updateSection(createElement, section, currentLayout) + }) + + newSections.push(...updatedSections) + } + } + + return newSections +} + +export function calculateRowsCols (x, y) { + let rows = x ? x.length : 1 + let cols = y ? y.length : 1 + return { rows, cols } +} + +function validateSlotContent (slotContent) { + let definedElements = slotContent.filter(c => c.tag !== undefined) + if (definedElements.some(c => c.componentOptions.tag !== 'vgg-section')) { + throw new Error(`vgg-repeat can only contain sections`) + } + return definedElements +} diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index 391bdcf5..c6b72d65 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -146,39 +146,28 @@ export default { }, tickMin () { - if (this.y1 && this.y2) { - return 0.5 - (this.tickSize / (this.y2 - this.y1)) - } else { - return 0.5 - (this.tickSize / 100) - } + let localTickSize = this.getLocalY(this.tickSize) - this.getLocalY(0) + let scaledSize = localTickSize / (this.ranges.y2 - this.ranges.y1) + return 0.5 - scaledSize }, tickMax () { - if (this.y1 && this.y2) { - return 0.5 + (this.tickSize / (this.y2 - this.y1)) - } else { - return 0.5 + (this.tickSize / 100) - } + let localTickSize = this.getLocalY(this.tickSize) - this.getLocalY(0) + let scaledSize = localTickSize / (this.ranges.y2 - this.ranges.y1) + return 0.5 + scaledSize }, posY () { - let yHeight = this.getLocalY(50) - - if (this.y) { - let scaledY = this.getLocalY(this.y) - return [scaledY - yHeight, scaledY + yHeight] - } - - if (this.y1 && this.y2) { - return [this.getLocalY(this.y1), this.getLocalY(this.y2)] - } else if (this.y1 ^ this.y2) { - throw new Error ('Please provide both y1 and y2 coordinates. Alternatively use the y prop') + if (this.coords) { + return [this.getLocalY(this.coords.y1), this.getLocalY(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 @@ -199,14 +188,11 @@ export default { newRange.y1 = this.posY[0] newRange.y2 = this.posY[1] - if (this.x1 && this.x2) { - newRange.x1 = this.getLocalX(this.x1) - newRange.x2 = this.getLocalX(this.x2) + if (this.coords) { + newRange.x1 = this.getLocalX(this.coords.x1) + newRange.x2 = this.getLocalX(this.coords.x2) + return newRange - } else if (this.x1 ^ this.x2) { - throw new Error ('Please provide both x1 and x2 coordinates') - } else if (this.x) { - throw new Error('Please provide x1, x2 start and end coordinates') } if (this._domainType === 'temporal') { diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue index c4b999c1..edb70d19 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -146,33 +146,20 @@ export default { }, tickMin () { - if (this.x1 && this.x2) { - return 0.5 - (this.tickSize / (this.x2 - this.x1)) - } else { - return 0.5 - (this.tickSize / 100) - } + let localTickSize = this.getLocalX(this.tickSize) - this.getLocalX(0) + let scaledSize = localTickSize / (this.ranges.x2 - this.ranges.x1) + return 0.5 - scaledSize }, tickMax () { - if (this.x1 && this.x2) { - return 0.5 + (this.tickSize / (this.x2 - this.x1)) - } else { - return 0.5 + (this.tickSize / 100) - } + let localTickSize = this.getLocalX(this.tickSize) - this.getLocalX(0) + let scaledSize = localTickSize / (this.ranges.x2 - this.ranges.x1) + return 0.5 + scaledSize }, posX () { - let xWidth = this.getLocalX(50) - - if (this.x) { - let scaledX = this.getLocalX(this.x) - return [scaledX - xWidth, scaledX + xWidth] - } - - if (this.x1 && this.x2) { - return [this.getLocalX(this.x1), this.getLocalX(this.x2)] - } else if (this.x1 ^ this.x2) { - throw new Error ('Please provide both x1 and x2 coordinates. Alternatively use the x prop') + if (this.coords) { + return [this.getLocalX(this.coords.x1), this.getLocalX(this.coords.x2)] } let xDomain = this.xDomain @@ -180,6 +167,8 @@ export default { 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] @@ -199,14 +188,11 @@ export default { newRange.x1 = this.posX[0] newRange.x2 = this.posX[1] - if (this.y1 && this.y2) { - newRange.y1 = this.getLocalY(this.y1) - newRange.y2 = this.getLocalY(this.y2) + if (this.coords) { + newRange.y1 = this.getLocalY(this.coords.y1) + newRange.y2 = this.getLocalY(this.coords.y2) + return newRange - } else if (this.y1 ^ this.y2) { - throw new Error ('Please provide both y1 and y2 coordinates') - } else if (this.y) { - throw new Error('Please provide y1, y2 start and end coordinates') } if (this._domainType === 'temporal') { diff --git a/src/mixins/CoordinateSystem.js b/src/mixins/CoordinateSystem.js index 16f1683c..6ce2c181 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, $$map: false } + return { $$coordinateTree, $$transform, $$coordinateTreeParent, $$map: false, $$getLocalX, $$getLocalY } } } diff --git a/src/mixins/CoordinateTreeUser.js b/src/mixins/CoordinateTreeUser.js index 115b6f8c..893b9d32 100644 --- a/src/mixins/CoordinateTreeUser.js +++ b/src/mixins/CoordinateTreeUser.js @@ -1,13 +1,25 @@ export default { inject: ['$$coordinateTree', '$$coordinateTreeParent'], - computed: { - parentBranch () { - return this.$$coordinateTree.getBranch(this.$$coordinateTreeParent) - }, + data () { + 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 a3d77ff1..1d6fcc76 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -227,45 +227,9 @@ export default { } }, - getLocalX (n) { - let p = this._parentNodes - let result = n - for (let i = 0; i < p.length; i++) { - let b = p[i] - let bRange = b.ranges.x - let bDomain = b.domains.x + getLocalX (n) { return this.$$getLocalX(n) }, - let rangeMin = Math.min(bRange[0], bRange[1]) - let rangeMax = Math.max(bRange[0], bRange[1]) - - let domainMin = Math.min(bDomain[0], bDomain[1]) - let domainMax = Math.max(bDomain[0], bDomain[1]) - - result = (result/ (rangeMax - rangeMin)) * (domainMax - domainMin) - } - - return result - }, - - getLocalY (n) { - let p = this._parentNodes - let result = n - for (let i = 0; i < p.length; i++) { - let b = p[i] - let bRange = b.ranges.y - let bDomain = b.domains.y - - let rangeMin = Math.min(bRange[0], bRange[1]) - let rangeMax = Math.max(bRange[0], bRange[1]) - - let domainMin = Math.min(bDomain[0], bDomain[1]) - let domainMax = Math.max(bDomain[0], bDomain[1]) - - result = (result / (rangeMax - rangeMin)) * (domainMax - domainMin) - } - - return result - } + getLocalY (n) { return this.$$getLocalY(n) } }, computed: { @@ -289,6 +253,18 @@ export default { 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) + }, + + coords () { + if (this.validX && this.validY) {return this.coordinateSpecification} + }, + xDomain () { return this.parentBranch.domains.x }, diff --git a/src/mixins/Guides/defaultFormat.js b/src/mixins/Guides/defaultFormat.js new file mode 100644 index 00000000..b2c1ca07 --- /dev/null +++ b/src/mixins/Guides/defaultFormat.js @@ -0,0 +1,28 @@ +export default function (value) { + if (value.constructor === Number) { + let stringValue = value.toString() + let length = stringValue.length + if (length < 6) { return value } + + let nIntegers = stringValue.split('.')[0].length + + if (nIntegers > 4) { + return Math.floor(value / 1000).toString() + 'k' + } else { + return round(stringValue, 5 - nIntegers) + } + } + + if (value.constructor === String) { + if (value.length < 15) { + return value + } else { + return value.slice(0, 14) + '...' + } + } +} + +function round (value, decimals) { + let z = 10 ** decimals + return Math.floor(value * z) / z +} diff --git a/src/mixins/Marks/Mark.js b/src/mixins/Marks/Mark.js index 6eb0a512..ae404bb1 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: { @@ -16,7 +16,6 @@ export default { computed: { __update () { return this.parentBranch.updateCount - // return this.$$coordinateTree._update }, _interpolate () { diff --git a/src/scales/shorthands/coords/quantitative.js b/src/scales/shorthands/coords/quantitative.js index 0467046c..b9456763 100644 --- a/src/scales/shorthands/coords/quantitative.js +++ b/src/scales/shorthands/coords/quantitative.js @@ -9,9 +9,6 @@ export default { } function linear (domain, range) { - if (domain[0] === range[0] && domain[1] === range[1]) { - return input => { return input } - } return d3.scaleLinear().domain(domain).range(range) } diff --git a/src/scales/utils/getPrimitive.js b/src/scales/utils/getPrimitive.js new file mode 100644 index 00000000..89a2da94 --- /dev/null +++ b/src/scales/utils/getPrimitive.js @@ -0,0 +1,5 @@ +export default function (domainType) { + return domainType.startsWith('interval') + ? domainType.split(':')[1] + : domainType +} diff --git a/stories/sandbox/MappingGridLayout.vue b/stories/sandbox/MappingGridLayout.vue new file mode 100644 index 00000000..aa00c7d8 --- /dev/null +++ b/stories/sandbox/MappingGridLayout.vue @@ -0,0 +1,35 @@ + diff --git a/stories/sandbox/RepeatLayout.vue b/stories/sandbox/RepeatLayout.vue new file mode 100644 index 00000000..aa05c10e --- /dev/null +++ b/stories/sandbox/RepeatLayout.vue @@ -0,0 +1,45 @@ + + + diff --git a/stories/sandbox/Scatterplot.vue b/stories/sandbox/Scatterplot.vue index a08ecd4c..53c468b9 100644 --- a/stories/sandbox/Scatterplot.vue +++ b/stories/sandbox/Scatterplot.vue @@ -26,16 +26,32 @@
- + /> --> - --> + + + + diff --git a/stories/sandbox/SimpleGridLayout.vue b/stories/sandbox/SimpleGridLayout.vue new file mode 100644 index 00000000..9477e6fa --- /dev/null +++ b/stories/sandbox/SimpleGridLayout.vue @@ -0,0 +1,52 @@ + + + From 121fe73119a5b1f12c3071af151009d3972f5ce0 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Tue, 26 Feb 2019 12:02:01 +0800 Subject: [PATCH 33/37] docs: updated axis docs, minor changes to axis code --- docs/.vuepress/components/Cartesian.vue | 42 ++++++++++++------------- docs/axes/cartesian.md | 14 ++++----- src/components/Guides/XAxis.vue | 4 +-- src/components/Guides/YAxis.vue | 6 ++-- src/mixins/Guides/BaseAxis.js | 18 +++++------ 5 files changed, 40 insertions(+), 44 deletions(-) diff --git a/docs/.vuepress/components/Cartesian.vue b/docs/.vuepress/components/Cartesian.vue index a3543ba1..69e26a4a 100644 --- a/docs/.vuepress/components/Cartesian.vue +++ b/docs/.vuepress/components/Cartesian.vue @@ -4,39 +4,42 @@ :height="300" :data="data"> + + + + @@ -46,7 +49,7 @@ :x1="50" :x2="550" :y1="25" - :y2="275" + :y2="200" :scale-x="'xValues'" :scale-y="'yValues'" > @@ -54,28 +57,25 @@ diff --git a/docs/axes/cartesian.md b/docs/axes/cartesian.md index a9e6be62..23a1bde1 100644 --- a/docs/axes/cartesian.md +++ b/docs/axes/cartesian.md @@ -21,14 +21,15 @@ Axes are used as reference scales for values in the graph. Each axis is typicall ### X Axis Positioning -There are three options for positioning the x axis on the graph. The `y` prop takes precedence, followed by `y1` and `y2`, lastly `vjust` encodes default behavior. +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). -When using `y` or `vjust`, the x axis defaults to a height of 100px. +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 | Screen pixels | +| h | false | [Number] | undefined | height of x axis | Screen pixels | | y1 | false | [Number] | undefined | starting y coordinate of x axis | Screen pixels | | y2 | false | [Number] | undefined | ending y coordinate of x axis | Screen pixels | @@ -43,14 +44,15 @@ By default the x axis spans the entire width of the section. To customize the wi ### Y Axis Positioning -Similar to the x axis, there are three options for positioning the y axis on the graph. The `x` prop takes precedence, followed by `x1` and `x2`, lastly `hjust` encodes default behavior. +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 `x` or `hjust`, the y axis defaults to a width of 100px. +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 | Screen pixels | +| w | false | [Number] | undefined | width of y axis | Screen pixels | | x1 | false | [Number] | undefined | starting x coordinate of y axis | Screen pixels | | x2 | false | [Number] | undefined | ending x coordinate of y axis | Screen pixels | @@ -112,6 +114,4 @@ Note that if a `Function` is passed to the `format` prop to format labels before | 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 | - - +| titleOpacity | false | [Number] | 1 | opacity of title | Number between 0 and 1 | \ No newline at end of file diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index c6b72d65..38b01b57 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -158,7 +158,7 @@ export default { }, posY () { - if (this.coords) { + if (this.validY) { return [this.getLocalY(this.coords.y1), this.getLocalY(this.coords.y2)] } @@ -188,7 +188,7 @@ export default { newRange.y1 = this.posY[0] newRange.y2 = this.posY[1] - if (this.coords) { + if (this.validX) { newRange.x1 = this.getLocalX(this.coords.x1) newRange.x2 = this.getLocalX(this.coords.x2) diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue index edb70d19..a80ae08a 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -116,7 +116,7 @@ export default { }, titleVjust: { - default: 1.05 + default: 1.08 } }, @@ -158,7 +158,7 @@ export default { }, posX () { - if (this.coords) { + if (this.validX) { return [this.getLocalX(this.coords.x1), this.getLocalX(this.coords.x2)] } @@ -188,7 +188,7 @@ export default { newRange.x1 = this.posX[0] newRange.x2 = this.posX[1] - if (this.coords) { + if (this.validY) { newRange.y1 = this.getLocalY(this.coords.y1) newRange.y2 = this.getLocalY(this.coords.y2) diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index 1d6fcc76..f8562e54 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -262,7 +262,7 @@ export default { }, coords () { - if (this.validX && this.validY) {return this.coordinateSpecification} + if (this.validX || this.validY) {return this.coordinateSpecification} }, xDomain () { @@ -299,12 +299,10 @@ export default { } ticks = newTickValues.map((value, i) => { - if (i === 0 && this.tickExtra && this.tickExtraLabel) { - return { value, label: format(value) } - } else if (i != 0) { - return { value, label: format(value) } - } else { + if (i === 0 && this.tickExtra && !this.tickExtraLabel) { return { value, label: '' } + } else { + return { value, label: format(value) } } }) } @@ -333,12 +331,10 @@ export default { ticks = newTickValues.map((value, i) => { let date = new Date(value) - if (i === 0 && this.tickExtra && this.tickExtraLabel) { - return { value: date, label: format(date) } - } else if (i != 0) { - return { value: date, label: format(date) } + if (i === 0 && this.tickExtra && !this.tickExtraLabel) { + return { value: date, label: '' } } else { - return { value, label: '' } + return { value: date, label: format(date) } } }) } From 41b55ccfd99cd3caf6f731d4b57cb69c8b8c710f Mon Sep 17 00:00:00 2001 From: gracegsy Date: Tue, 26 Feb 2019 15:19:45 +0800 Subject: [PATCH 34/37] test: change axes to intersect at center as per original --- stories/sandbox/PlotLines.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stories/sandbox/PlotLines.vue b/stories/sandbox/PlotLines.vue index 92a4049e..7dc8851e 100644 --- a/stories/sandbox/PlotLines.vue +++ b/stories/sandbox/PlotLines.vue @@ -54,12 +54,12 @@ From dbf2d64e2cbaf7086022eab68b5649fca8c7b8b4 Mon Sep 17 00:00:00 2001 From: Luuc van der Zee Date: Tue, 26 Feb 2019 09:58:49 +0100 Subject: [PATCH 35/37] fix: broken SymbolMarkDemo --- docs/.vuepress/components/SymbolMarkDemo.vue | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/.vuepress/components/SymbolMarkDemo.vue b/docs/.vuepress/components/SymbolMarkDemo.vue index fef4aabc..e897210a 100644 --- a/docs/.vuepress/components/SymbolMarkDemo.vue +++ b/docs/.vuepress/components/SymbolMarkDemo.vue @@ -21,7 +21,7 @@ :size="16" :shape="shape" :stroke="stroke" - :fill="fill" + :fill="fill(row.explanatory)" :stroke-width="1" /> @@ -96,14 +96,6 @@ export default { }, computed : { - fill () { - if (this.color === 'both' || this.color === 'fill') { - return { get: 'explanatory', scale: { type: 'viridis', domain: 'explanatory' } } - } else { - return 'none' - } - }, - stroke () { if (this.color === 'both' || this.color === 'stroke') { return 'black' @@ -129,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' + } + }, } } From 5636b447a3b65f0418f1540e78920346d086b0c2 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Tue, 26 Feb 2019 17:35:03 +0800 Subject: [PATCH 36/37] fix: change != to !== --- src/mixins/Guides/BaseAxis.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mixins/Guides/BaseAxis.js b/src/mixins/Guides/BaseAxis.js index f8dffcad..a5d0f8b7 100644 --- a/src/mixins/Guides/BaseAxis.js +++ b/src/mixins/Guides/BaseAxis.js @@ -238,11 +238,11 @@ export default { }, validX () { - return (this.x1 != undefined && this.x2 != undefined) || (this.x != undefined && this.w != undefined) + 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) + return (this.y1 !== undefined && this.y2 !== undefined) || (this.y !== undefined && this.h !== undefined) }, coords () { @@ -264,7 +264,7 @@ export default { if (this.tickValues) { newTickValues = this.tickValues - if (this.tickExtra && this.tickValues[0] != firstValue) { + if (this.tickExtra && this.tickValues[0] !== firstValue) { newTickValues.unshift(firstValue) } @@ -278,7 +278,7 @@ export default { if (this._domainType === 'quantitative') { newTickValues = arrayTicks(...this._domain, this.tickCount) - if (this.tickExtra && newTickValues[0] != firstValue) { + if (this.tickExtra && newTickValues[0] !== firstValue) { newTickValues.unshift(firstValue) } @@ -308,7 +308,7 @@ export default { newTickValues = scale.ticks(this.tickCount) - if (this.tickExtra && newTickValues[0] != firstValue) { + if (this.tickExtra && newTickValues[0] !== firstValue) { newTickValues.unshift(firstValue) } From cd1bd4aa295e3dcfc4589de61e32584bf7480180 Mon Sep 17 00:00:00 2001 From: gracegsy Date: Tue, 26 Feb 2019 17:57:15 +0800 Subject: [PATCH 37/37] fix: axes x/x1/x2/w and y/y1/y2/h are now defined in local coordinates --- docs/axes/cartesian.md | 24 ++++++++++++------------ src/components/Guides/XAxis.vue | 6 +++--- src/components/Guides/YAxis.vue | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/axes/cartesian.md b/docs/axes/cartesian.md index 23a1bde1..cdf45089 100644 --- a/docs/axes/cartesian.md +++ b/docs/axes/cartesian.md @@ -28,17 +28,17 @@ When using `vjust`, the x axis defaults to a height of 100px in screen coordinat | 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 | Screen pixels | -| h | false | [Number] | undefined | height of x axis | Screen pixels | -| y1 | false | [Number] | undefined | starting y coordinate of x axis | Screen pixels | -| y2 | false | [Number] | undefined | ending y coordinate of x axis | Screen pixels | +| 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 | Screen pixels | -| x2 | false | [Number] | undefined | ending x coordinate of x axis | Screen pixels | +| x1 | false | [Number] | undefined | starting x coordinate of x axis | Local Coordinates | +| x2 | false | [Number] | undefined | ending x coordinate of x axis | Local Coordinates | @@ -51,17 +51,17 @@ When using `hjust`, the y axis defaults to a width of 100px in screen coordinate | 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 | Screen pixels | -| w | false | [Number] | undefined | width of y axis | Screen pixels | -| x1 | false | [Number] | undefined | starting x coordinate of y axis | Screen pixels | -| x2 | false | [Number] | undefined | ending x coordinate of y axis | Screen pixels | +| 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 | Screen pixels | -| y2 | false | [Number] | undefined | ending y coordinate of y axis | Screen pixels | +| y1 | false | [Number] | undefined | starting y coordinate of y axis | Local Coordinates | +| y2 | false | [Number] | undefined | ending y coordinate of y axis | Local Coordinates | diff --git a/src/components/Guides/XAxis.vue b/src/components/Guides/XAxis.vue index 38b01b57..7ff72ef1 100644 --- a/src/components/Guides/XAxis.vue +++ b/src/components/Guides/XAxis.vue @@ -159,7 +159,7 @@ export default { posY () { if (this.validY) { - return [this.getLocalY(this.coords.y1), this.getLocalY(this.coords.y2)] + return [this.coords.y1, this.coords.y2] } let yDomain = this.yDomain @@ -189,8 +189,8 @@ export default { newRange.y2 = this.posY[1] if (this.validX) { - newRange.x1 = this.getLocalX(this.coords.x1) - newRange.x2 = this.getLocalX(this.coords.x2) + newRange.x1 = this.coords.x1 + newRange.x2 = this.coords.x2 return newRange } diff --git a/src/components/Guides/YAxis.vue b/src/components/Guides/YAxis.vue index a80ae08a..be95ffec 100644 --- a/src/components/Guides/YAxis.vue +++ b/src/components/Guides/YAxis.vue @@ -159,7 +159,7 @@ export default { posX () { if (this.validX) { - return [this.getLocalX(this.coords.x1), this.getLocalX(this.coords.x2)] + return [this.coords.x1, this.coords.x2] } let xDomain = this.xDomain @@ -189,8 +189,8 @@ export default { newRange.x2 = this.posX[1] if (this.validY) { - newRange.y1 = this.getLocalY(this.coords.y1) - newRange.y2 = this.getLocalY(this.coords.y2) + newRange.y1 = this.coords.y1 + newRange.y2 = this.coords.y2 return newRange }