beyond-rails 0.0.185 → 0.0.190
Sign up to get free protection for your applications and to get access to all the features.
- 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 +2 -0
- data/src/sass/abstracts/_variables.scss +5 -0
- data/src/sass/components/_breadcrumb.scss +3 -0
- data/src/sass/components/_chart.scss +14 -0
- data/src/sass/components/_mega-menu.scss +57 -0
- data/src/sass/components/_modal.scss +12 -1
- data/src/sass/components/_nav.scss +1 -0
- data/src/sass/layout/_flex-util.scss +3 -0
- metadata +34 -15
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
|
+
}
|