beyond-rails 0.0.186 → 0.0.191
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/src/js/components/Alert.js +1 -1
- data/src/js/components/Autocomplete.js +1 -1
- data/src/js/components/AutocompleteMenu.js +1 -1
- data/src/js/components/BarChart.js +452 -0
- data/src/js/components/Btn.js +1 -1
- data/src/js/components/Checkbox.js +1 -1
- data/src/js/components/DateInput.js +1 -1
- data/src/js/components/DateMenu.js +1 -1
- data/src/js/components/DateTimeRanger.js +1 -1
- data/src/js/components/Datepicker.js +1 -1
- data/src/js/components/DatepickerBtnArrow.js +1 -1
- data/src/js/components/Dropdown.js +1 -1
- data/src/js/components/LineChart.js +535 -0
- data/src/js/components/Menu.js +1 -1
- data/src/js/components/Modal.js +64 -13
- data/src/js/components/Navbar.js +1 -1
- data/src/js/components/Radio.js +1 -1
- data/src/js/components/SearchDropdown.js +1 -1
- data/src/js/components/Sidebar.js +1 -1
- data/src/js/components/Tabbox.js +1 -1
- data/src/js/components/TimeInput.js +1 -1
- data/src/js/components/TimeMenu.js +1 -1
- data/src/js/components/Timepicker.js +1 -1
- data/src/js/components/Toast.js +1 -1
- data/src/js/components/ToastItem.js +1 -1
- data/src/js/components/Tooltip.js +1 -1
- data/src/js/decorators/chartCommon.js +218 -0
- data/src/js/{utils → decorators}/supportDom.js +1 -1
- data/src/js/index.js +6 -2
- data/src/js/jquery/bindModalFn.js +57 -6
- data/src/js/utils/index.js +10 -1
- data/src/js/utils/isDef.js +3 -0
- data/src/js/utils/isInt.js +3 -0
- data/src/js/utils/isUndef.js +3 -0
- data/src/sass/_beyond.scss +1 -0
- data/src/sass/abstracts/_variables.scss +1 -1
- data/src/sass/components/_breadcrumb.scss +3 -0
- data/src/sass/components/_chart.scss +14 -0
- data/src/sass/components/_mega-menu.scss +28 -28
- data/src/sass/components/_modal.scss +12 -1
- data/src/sass/components/_nav.scss +1 -0
- metadata +28 -9
data/src/js/components/Btn.js
CHANGED
@@ -2,7 +2,7 @@ import getFloatedTargetPos from '../utils/getFloatedTargetPos'
|
|
2
2
|
import isTouchDevice from '../utils/isTouchDevice'
|
3
3
|
import dateLt from '../utils/dateLt'
|
4
4
|
import dateEq from '../utils/dateEq'
|
5
|
-
import supportDom from '../
|
5
|
+
import supportDom from '../decorators/supportDom'
|
6
6
|
import {
|
7
7
|
addDays,
|
8
8
|
addMonths,
|
@@ -5,7 +5,7 @@ import TimeMenu from './TimeMenu'
|
|
5
5
|
import DatepickerBtnArrow from './DatepickerBtnArrow'
|
6
6
|
import dateGt from '../utils/dateGt'
|
7
7
|
import dateLt from '../utils/dateLt'
|
8
|
-
import supportDom from '../
|
8
|
+
import supportDom from '../decorators/supportDom'
|
9
9
|
import {
|
10
10
|
endOfDay,
|
11
11
|
dateToTimestamp,
|
@@ -2,7 +2,7 @@ import DateInput from './DateInput'
|
|
2
2
|
import TimeInput from './TimeInput'
|
3
3
|
import DateMenu from './DateMenu'
|
4
4
|
import TimeMenu from './TimeMenu'
|
5
|
-
import supportDom from '../
|
5
|
+
import supportDom from '../decorators/supportDom'
|
6
6
|
import { DEFAULT_TIMEZONE } from '../consts'
|
7
7
|
import {
|
8
8
|
dateToTimestamp,
|
@@ -0,0 +1,535 @@
|
|
1
|
+
import supportDom from '../decorators/supportDom'
|
2
|
+
import chartCommon from '../decorators/chartCommon'
|
3
|
+
import isDef from '../utils/isDef'
|
4
|
+
import isUndef from '../utils/isUndef'
|
5
|
+
import { mem, range, sortBy, throttle, uniqBy } from '../utils'
|
6
|
+
|
7
|
+
/**
|
8
|
+
* -------------------------------------------------------------------------------------------------
|
9
|
+
* ^ |
|
10
|
+
* | |
|
11
|
+
* yPadding |
|
12
|
+
* | |
|
13
|
+
* v |
|
14
|
+
* ----------------------------------------------------------- yLabel |
|
15
|
+
* ----------------------------------------------------------- yLabel |
|
16
|
+
* <- xPadding -> ----------------------------------------------------------- yLabel <- xPadding -> |
|
17
|
+
* ----------------------------------------------------------- yLabel |
|
18
|
+
* ^ |
|
19
|
+
* yGutter |
|
20
|
+
* v |
|
21
|
+
* ----------------------------------------------------------- yLabel |
|
22
|
+
* xLabel <- xGutter -> xLabel <- xGutter -> xLabel |
|
23
|
+
* ^ |
|
24
|
+
* | |
|
25
|
+
* yPadding |
|
26
|
+
* | |
|
27
|
+
* v |
|
28
|
+
* --------------------------------------------------------------------------------------------------
|
29
|
+
**/
|
30
|
+
const defaultLineStyles = [
|
31
|
+
'#5469d4',
|
32
|
+
'#7c54d4',
|
33
|
+
'#a254d4'
|
34
|
+
]
|
35
|
+
|
36
|
+
@supportDom
|
37
|
+
@chartCommon
|
38
|
+
export default class LineChart {
|
39
|
+
|
40
|
+
constructor(dom, options = {}) {
|
41
|
+
this.dom = dom
|
42
|
+
this.options = options
|
43
|
+
this.pointsArr = []
|
44
|
+
this.height = options.height || 150
|
45
|
+
this.width = options.width
|
46
|
+
|
47
|
+
this.toXLabel = isDef(options.toXLabel) ? mem(options.toXLabel) : (v => v)
|
48
|
+
this.toYLabel = isDef(options.toYLabel) ? mem(options.toYLabel) : (v => v)
|
49
|
+
|
50
|
+
this.xPadding = isDef(options.xPadding) ? options.xPadding : 20
|
51
|
+
this.yPadding = isDef(options.yPadding) ? options.yPadding : 20
|
52
|
+
|
53
|
+
this.xGutter = isDef(options.xGutter) ? options.xGutter : 100
|
54
|
+
this.yGutter = isDef(options.yGutter) ? options.yGutter : 10
|
55
|
+
|
56
|
+
this.xLabelMargin = isDef(options.xLabelMargin) ? options.xLabelMargin : 10
|
57
|
+
this.yLabelMargin = isDef(options.yLanelMargin) ? options.yLabelMargin : 10
|
58
|
+
|
59
|
+
this.lineStyles = options.lineStyles || defaultLineStyles
|
60
|
+
|
61
|
+
this.bgColor = options.bgColor || '#fff'
|
62
|
+
this.fontSize = options.fontSize || 12
|
63
|
+
|
64
|
+
this.xStep = options.xStep
|
65
|
+
this.yStep = options.yStep
|
66
|
+
|
67
|
+
this.lineLabels = options.lineLabels || []
|
68
|
+
this.lineLabelMargin = isDef(options.lineLabelMargin) ? options.lineLabelMargin : 20
|
69
|
+
|
70
|
+
this.pointPosMap = new Map()
|
71
|
+
this.xLabelRows = []
|
72
|
+
this.yLabelRows = []
|
73
|
+
|
74
|
+
this.init()
|
75
|
+
}
|
76
|
+
|
77
|
+
init() {
|
78
|
+
this.setDpr()
|
79
|
+
this.setDomWidthIfNeeded()
|
80
|
+
this.setCanvas()
|
81
|
+
this.clear()
|
82
|
+
this.bindMedia()
|
83
|
+
this.bindPointMouseOver()
|
84
|
+
}
|
85
|
+
|
86
|
+
get contentWidth() {
|
87
|
+
return this.width - (this.xPadding * 2) - this.yLabelMargin -
|
88
|
+
this.yLabelWidth - (this.xLabelWidth / 2)
|
89
|
+
}
|
90
|
+
|
91
|
+
get contentHeight() {
|
92
|
+
return this.height - (this.yPadding * 2) - this.xLabelMargin -
|
93
|
+
this.xLabelHeight - this.lineLabelBoxHeight
|
94
|
+
}
|
95
|
+
|
96
|
+
get firstX() {
|
97
|
+
return this.xLabelRows[0].value
|
98
|
+
}
|
99
|
+
|
100
|
+
get lastX() {
|
101
|
+
const { xLabelRows } = this
|
102
|
+
return xLabelRows[xLabelRows.length - 1].value
|
103
|
+
}
|
104
|
+
|
105
|
+
get firstY() {
|
106
|
+
return this.yLabelRows[0].value
|
107
|
+
}
|
108
|
+
|
109
|
+
get lastY() {
|
110
|
+
const { yLabelRows } = this
|
111
|
+
return yLabelRows[yLabelRows.length - 1].value
|
112
|
+
}
|
113
|
+
|
114
|
+
get lineLabelHeight() {
|
115
|
+
return this.fontSize
|
116
|
+
}
|
117
|
+
|
118
|
+
get lineLabelBoxHeight() {
|
119
|
+
if (this.lineLabels.length > 0) {
|
120
|
+
return this.lineLabelMargin + this.lineLabelHeight
|
121
|
+
}
|
122
|
+
return 0
|
123
|
+
}
|
124
|
+
|
125
|
+
get xAxisStart() {
|
126
|
+
return this.xPadding + (this.xLabelWidth / 2)
|
127
|
+
}
|
128
|
+
|
129
|
+
get xAxisEnd() {
|
130
|
+
return this.xAxisStart + this.contentWidth
|
131
|
+
}
|
132
|
+
|
133
|
+
get xRatio() {
|
134
|
+
const lineWidth = this.xAxisEnd - this.xAxisStart
|
135
|
+
const xDelta = this.lastX - this.firstX
|
136
|
+
return xDelta / lineWidth
|
137
|
+
}
|
138
|
+
|
139
|
+
get yAxisStart() {
|
140
|
+
return this.height - this.yPadding - this.lineLabelBoxHeight -
|
141
|
+
this.xLabelHeight - this.xLabelMargin + (this.yLabelHeight / 2)
|
142
|
+
}
|
143
|
+
|
144
|
+
get yAxisEnd() {
|
145
|
+
return this.yAxisStart - this.contentHeight
|
146
|
+
}
|
147
|
+
|
148
|
+
get yRatio() {
|
149
|
+
const lineHeight = this.yAxisStart - this.yAxisEnd
|
150
|
+
const yDelta = Math.abs(this.lastY - this.firstY)
|
151
|
+
return yDelta / lineHeight
|
152
|
+
}
|
153
|
+
|
154
|
+
bindPointMouseOver() {
|
155
|
+
if (isUndef(this.options.onPointMouseOver)) {
|
156
|
+
return
|
157
|
+
}
|
158
|
+
if (! ('onmousemove' in this.canvas)) {
|
159
|
+
return
|
160
|
+
}
|
161
|
+
this.addLayer()
|
162
|
+
const canvas = this.getHighestCanvas()
|
163
|
+
this.addEvent(canvas, 'mousemove', throttle(this.handleMouseMove.bind(this), 30))
|
164
|
+
}
|
165
|
+
|
166
|
+
clearPointPos() {
|
167
|
+
this.pointPosMap.clear()
|
168
|
+
}
|
169
|
+
|
170
|
+
draw() {
|
171
|
+
this.clear()
|
172
|
+
this.drawXAxis()
|
173
|
+
this.drawYAxis()
|
174
|
+
this.drawBgLines()
|
175
|
+
this.drawLines()
|
176
|
+
this.drawLineLables()
|
177
|
+
}
|
178
|
+
|
179
|
+
drawBgLines() {
|
180
|
+
|
181
|
+
const { ctx, yLabelRows, contentWidth, firstY, xAxisStart, yAxisStart, yRatio } = this
|
182
|
+
|
183
|
+
ctx.strokeStyle = 'rgba(224, 224, 224, .5)'
|
184
|
+
ctx.lineWidth = 1
|
185
|
+
|
186
|
+
yLabelRows.forEach(row => {
|
187
|
+
|
188
|
+
const y = yAxisStart - ((row.value - firstY) / yRatio)
|
189
|
+
|
190
|
+
ctx.beginPath()
|
191
|
+
ctx.moveTo(xAxisStart, y)
|
192
|
+
ctx.lineTo(xAxisStart + contentWidth, y)
|
193
|
+
ctx.stroke()
|
194
|
+
ctx.closePath
|
195
|
+
})
|
196
|
+
}
|
197
|
+
|
198
|
+
drawLines() {
|
199
|
+
const { ctx, pointPosMap, lineStyles } = this
|
200
|
+
ctx.lineWidth = 2
|
201
|
+
|
202
|
+
this.pointsArr.forEach((points, i) => {
|
203
|
+
ctx.beginPath()
|
204
|
+
ctx.strokeStyle = lineStyles[i] ? lineStyles[i] : '#000'
|
205
|
+
points.forEach(p => {
|
206
|
+
const pos = pointPosMap.get(p)
|
207
|
+
ctx.lineTo(pos.x, pos.y)
|
208
|
+
})
|
209
|
+
ctx.stroke()
|
210
|
+
ctx.closePath()
|
211
|
+
})
|
212
|
+
}
|
213
|
+
|
214
|
+
drawLineLables() {
|
215
|
+
const { ctx, lineStyles, lineLabelHeight } = this
|
216
|
+
const rectSize = 7
|
217
|
+
|
218
|
+
const rectGutter = 7
|
219
|
+
const labelGutter = 14
|
220
|
+
const rectMargin = 1
|
221
|
+
const y = this.height - this.yPadding
|
222
|
+
let x = this.xPadding
|
223
|
+
|
224
|
+
this.lineLabels.forEach((name, i) => {
|
225
|
+
ctx.fillStyle = lineStyles[i] || '#000'
|
226
|
+
ctx.fillRect(x, y - lineLabelHeight + rectMargin, rectSize, rectSize)
|
227
|
+
|
228
|
+
x += (rectSize + rectGutter)
|
229
|
+
ctx.fillStyle = '#000'
|
230
|
+
ctx.textAlign = 'left'
|
231
|
+
ctx.textBaseline = 'top'
|
232
|
+
ctx.fillText(name, x, y - lineLabelHeight)
|
233
|
+
x += (ctx.measureText(name).width + labelGutter)
|
234
|
+
})
|
235
|
+
}
|
236
|
+
|
237
|
+
clearVerticalLine() {
|
238
|
+
const { ctx } = this.firstLayer
|
239
|
+
ctx.clearRect(0, 0, this.width, this.height)
|
240
|
+
}
|
241
|
+
|
242
|
+
drawVerticalLine(point, index) {
|
243
|
+
const { ctx } = this.firstLayer
|
244
|
+
const pos = this.pointPosMap.get(point)
|
245
|
+
const style = this.lineStyles[index] || '#000'
|
246
|
+
ctx.strokeStyle = style
|
247
|
+
ctx.lineWidth = 1
|
248
|
+
ctx.beginPath()
|
249
|
+
ctx.moveTo(pos.x, 0)
|
250
|
+
ctx.lineTo(pos.x, this.height)
|
251
|
+
ctx.stroke()
|
252
|
+
ctx.closePath()
|
253
|
+
|
254
|
+
this.fillCircle(ctx, pos.x, pos.y, 8, style, .2)
|
255
|
+
this.fillCircle(ctx, pos.x, pos.y, 4, style)
|
256
|
+
}
|
257
|
+
|
258
|
+
drawXAxis() {
|
259
|
+
const { ctx, firstX, xLabelRows, xAxisStart, xRatio } = this
|
260
|
+
|
261
|
+
const y = this.height - this.yPadding - this.lineLabelBoxHeight
|
262
|
+
|
263
|
+
const scaleMargin = 4
|
264
|
+
const scaleSize = 4
|
265
|
+
const scaleStart = y - scaleMargin - scaleSize
|
266
|
+
const scaleEnd = y - scaleMargin
|
267
|
+
|
268
|
+
ctx.textBaseline = 'top'
|
269
|
+
ctx.fillStyle = '#3c4257'
|
270
|
+
ctx.textAlign = 'center'
|
271
|
+
|
272
|
+
ctx.strokeStyle = '#3c4257'
|
273
|
+
|
274
|
+
xLabelRows.forEach((row, i) => {
|
275
|
+
|
276
|
+
const x = xAxisStart + ((row.value - firstX) / xRatio)
|
277
|
+
|
278
|
+
ctx.beginPath()
|
279
|
+
ctx.moveTo(x, scaleStart)
|
280
|
+
ctx.lineTo(x, scaleEnd)
|
281
|
+
ctx.stroke()
|
282
|
+
ctx.closePath()
|
283
|
+
|
284
|
+
ctx.fillText(row.label, x, y)
|
285
|
+
})
|
286
|
+
}
|
287
|
+
|
288
|
+
drawYAxis() {
|
289
|
+
const { ctx, firstY, yLabelRows, yAxisStart, yRatio } = this
|
290
|
+
const x = this.width - this.xPadding
|
291
|
+
const halfYLabelHeight = this.yLabelHeight / 2
|
292
|
+
|
293
|
+
ctx.fillStyle = '#3c4257'
|
294
|
+
ctx.textAlign = 'right'
|
295
|
+
|
296
|
+
yLabelRows.forEach(row => {
|
297
|
+
const y = yAxisStart - ((row.value - firstY) / yRatio)
|
298
|
+
ctx.fillText(row.label, x, y - halfYLabelHeight)
|
299
|
+
})
|
300
|
+
}
|
301
|
+
|
302
|
+
findClosetPoint(canvasMousePos) {
|
303
|
+
const { pointsArr, pointPosMap } = this
|
304
|
+
let index = 0
|
305
|
+
for (const points of pointsArr) {
|
306
|
+
for (const point of points) {
|
307
|
+
const pos = pointPosMap.get(point)
|
308
|
+
if (this.inDetectedZone(canvasMousePos, pos)) {
|
309
|
+
return {
|
310
|
+
index,
|
311
|
+
point
|
312
|
+
}
|
313
|
+
}
|
314
|
+
}
|
315
|
+
index++
|
316
|
+
}
|
317
|
+
}
|
318
|
+
|
319
|
+
handleDprChange() {
|
320
|
+
this.setDpr()
|
321
|
+
this.refresh()
|
322
|
+
}
|
323
|
+
|
324
|
+
handleMouseMove(event) {
|
325
|
+
|
326
|
+
const canvasMousePos = this.getMousePosInCanvas(event)
|
327
|
+
const res = this.findClosetPoint(canvasMousePos)
|
328
|
+
|
329
|
+
this.raf(() => {
|
330
|
+
this.clearVerticalLine()
|
331
|
+
if (res) {
|
332
|
+
this.drawVerticalLine(res.point, res.index)
|
333
|
+
}
|
334
|
+
// only fires if res differs
|
335
|
+
if (this.lastClosetPointRes !== res) {
|
336
|
+
const mousePos = this.getMousePos(canvasMousePos)
|
337
|
+
this.options.onPointMouseOver(mousePos, res)
|
338
|
+
}
|
339
|
+
this.lastClosetPointRes = res
|
340
|
+
})
|
341
|
+
}
|
342
|
+
|
343
|
+
inDetectedZone(canvasMousePos, pointPos) {
|
344
|
+
const zoneLength = 14
|
345
|
+
const { x: mouseX, y: mouseY } = canvasMousePos
|
346
|
+
const { x: pointX, y: pointY } = pointPos
|
347
|
+
/**
|
348
|
+
* # is canvasMousePos
|
349
|
+
* see if PointPos is landed in the zone below
|
350
|
+
*
|
351
|
+
* A -------- B
|
352
|
+
* | |
|
353
|
+
* | |
|
354
|
+
* #
|
355
|
+
* | |
|
356
|
+
* | |
|
357
|
+
* C -------- D
|
358
|
+
*/
|
359
|
+
const a = {
|
360
|
+
x: mouseX - zoneLength,
|
361
|
+
y: mouseY - zoneLength
|
362
|
+
}
|
363
|
+
const b = {
|
364
|
+
x: mouseX + zoneLength,
|
365
|
+
y: mouseY - zoneLength
|
366
|
+
}
|
367
|
+
const c = {
|
368
|
+
x: mouseX - zoneLength,
|
369
|
+
y: mouseY + zoneLength
|
370
|
+
}
|
371
|
+
return (a.x <= pointX) && (pointX <= b.x) &&
|
372
|
+
(a.y <= pointY) && (pointY <= c.y)
|
373
|
+
}
|
374
|
+
|
375
|
+
getUniqSortedPoints(axis) {
|
376
|
+
const points = uniqBy(this.pointsArr.flat(), axis)
|
377
|
+
return sortBy(points, [axis])
|
378
|
+
}
|
379
|
+
|
380
|
+
getLabelRows(options = {}) {
|
381
|
+
|
382
|
+
const axis = options.axis || 'x'
|
383
|
+
const gutter = options.gutter || this.xGutter
|
384
|
+
const contentLength = options.contentLength || this.contentWidth
|
385
|
+
const toLabel = options.toLabel || this.toXLabel
|
386
|
+
const measureLength = options.measureLength || (v => this.ctx.measureText(v).width)
|
387
|
+
|
388
|
+
const points = this.getUniqSortedPoints(axis)
|
389
|
+
const firstPoint = points[0]
|
390
|
+
const lastPoint = points[points.length - 1]
|
391
|
+
|
392
|
+
if (points.length <= 2) {
|
393
|
+
return points.map(p => {
|
394
|
+
const value = p[axis]
|
395
|
+
const label = toLabel(value)
|
396
|
+
const length = measureLength(label)
|
397
|
+
return { label, length, value }
|
398
|
+
})
|
399
|
+
}
|
400
|
+
|
401
|
+
const firstPointValue = firstPoint[axis]
|
402
|
+
const lastPointValue = lastPoint[axis]
|
403
|
+
const pointLength = points.length
|
404
|
+
|
405
|
+
let step = options.step
|
406
|
+
|
407
|
+
if (isUndef(step)) {
|
408
|
+
step = this.getAutoStep(firstPointValue, lastPointValue, pointLength)
|
409
|
+
}
|
410
|
+
|
411
|
+
const [stepStart, stepEnd] = this.getStepStartEnd(step, firstPointValue, lastPointValue)
|
412
|
+
const values = range(stepStart, stepEnd + step, step)
|
413
|
+
|
414
|
+
const valueCount = values.length
|
415
|
+
const initialGap = parseInt((valueCount - 2) / 2, 10)
|
416
|
+
|
417
|
+
const firstValue = values[0]
|
418
|
+
const lastValue = values[valueCount - 1]
|
419
|
+
const firstLabel = toLabel(firstValue)
|
420
|
+
const lastLabel = toLabel(lastValue)
|
421
|
+
|
422
|
+
let stepRows = [
|
423
|
+
{ label: firstLabel, length: measureLength(firstLabel), value: firstValue },
|
424
|
+
{ label: lastLabel, length: measureLength(lastLabel), value: lastValue },
|
425
|
+
]
|
426
|
+
|
427
|
+
for (let gap = initialGap; gap >= 0; gap--) {
|
428
|
+
const { lengthTotal, rows } = this.getLengthTotalData(gap, gutter, values, measureLength, toLabel)
|
429
|
+
if (lengthTotal <= contentLength) {
|
430
|
+
stepRows = rows
|
431
|
+
continue
|
432
|
+
}
|
433
|
+
return stepRows
|
434
|
+
}
|
435
|
+
return stepRows
|
436
|
+
}
|
437
|
+
|
438
|
+
refresh() {
|
439
|
+
this.raf(() => {
|
440
|
+
this.clearPointPos()
|
441
|
+
this.setDomWidthIfNeeded()
|
442
|
+
this.setCanvasSize(this.canvas)
|
443
|
+
this.layers.forEach(layer => this.setCanvasSize(layer.canvas))
|
444
|
+
this.setLabelWidths()
|
445
|
+
this.setLabelHeights()
|
446
|
+
this.setAxisData()
|
447
|
+
this.setPointPos()
|
448
|
+
this.draw()
|
449
|
+
})
|
450
|
+
}
|
451
|
+
|
452
|
+
setLabelHeights() {
|
453
|
+
this.xLabelHeight = this.fontSize
|
454
|
+
this.yLabelHeight = this.fontSize
|
455
|
+
}
|
456
|
+
|
457
|
+
setLabelWidths() {
|
458
|
+
|
459
|
+
const { toXLabel, toYLabel, ctx } = this
|
460
|
+
const { xLabelWidth, yLabelWidth } = this.pointsArr.flat()
|
461
|
+
.filter(p => p)
|
462
|
+
.reduce((o, p) => {
|
463
|
+
|
464
|
+
const { xLabelWidth, yLabelWidth } = o
|
465
|
+
const measuredXLabelWidth = ctx.measureText(toXLabel(p.x)).width
|
466
|
+
const measuredYLabelWidth = ctx.measureText(toYLabel(p.y)).width
|
467
|
+
|
468
|
+
return {
|
469
|
+
xLabelWidth: (measuredXLabelWidth > xLabelWidth) ? measuredXLabelWidth : xLabelWidth,
|
470
|
+
yLabelWidth: (measuredYLabelWidth > yLabelWidth) ? measuredYLabelWidth : yLabelWidth,
|
471
|
+
}
|
472
|
+
}, {
|
473
|
+
xLabelWidth: 0,
|
474
|
+
yLabelWidth: 0
|
475
|
+
})
|
476
|
+
|
477
|
+
this.xLabelWidth = xLabelWidth
|
478
|
+
this.yLabelWidth = yLabelWidth
|
479
|
+
}
|
480
|
+
|
481
|
+
setAxisData() {
|
482
|
+
this.xLabelRows = this.getLabelRows({ step: this.xStep })
|
483
|
+
this.yLabelRows = this.getLabelRows({
|
484
|
+
axis: 'y',
|
485
|
+
step: this.yStep,
|
486
|
+
gutter: this.yGutter,
|
487
|
+
contentLength: this.contentHeight,
|
488
|
+
toLabel: this.toYLabel,
|
489
|
+
measureLength: () => this.yLabelHeight
|
490
|
+
})
|
491
|
+
}
|
492
|
+
|
493
|
+
setData(pointsArr) {
|
494
|
+
this.pointsArr = pointsArr
|
495
|
+
this.clearPointPos()
|
496
|
+
this.setLabelWidths()
|
497
|
+
this.setLabelHeights()
|
498
|
+
this.setAxisData()
|
499
|
+
this.setPointPos()
|
500
|
+
this.raf(() => this.draw())
|
501
|
+
}
|
502
|
+
|
503
|
+
setPointPos() {
|
504
|
+
const { firstX, firstY, pointPosMap, xAxisStart, xRatio, yAxisStart, yRatio } = this
|
505
|
+
|
506
|
+
this.pointsArr.forEach((points, i) => {
|
507
|
+
points.forEach(point => {
|
508
|
+
const x = xAxisStart + ((point.x - firstX) / xRatio)
|
509
|
+
const y = yAxisStart - ((point.y - firstY) / yRatio)
|
510
|
+
const pos = { x, y }
|
511
|
+
pointPosMap.set(point, pos)
|
512
|
+
})
|
513
|
+
})
|
514
|
+
}
|
515
|
+
|
516
|
+
destroy() {
|
517
|
+
const { dom, canvas } = this
|
518
|
+
const { toXLabel, toYLabel } = this.options
|
519
|
+
|
520
|
+
if (isDef(toXLabel)) {
|
521
|
+
mem.clear(this.toXLabel)
|
522
|
+
}
|
523
|
+
if (isDef(toYLabel)) {
|
524
|
+
mem.clear(this.toYLabel)
|
525
|
+
}
|
526
|
+
this.clearPointPos()
|
527
|
+
this.unbindMedia()
|
528
|
+
this.removeAllLayers()
|
529
|
+
|
530
|
+
if (dom.contains(canvas)) {
|
531
|
+
dom.removeChild(canvas)
|
532
|
+
dom.style.removeProperty('position')
|
533
|
+
}
|
534
|
+
}
|
535
|
+
}
|