UNPKG

apexcharts

Version:

A JavaScript Chart Library

373 lines (297 loc) 10.6 kB
import Graphics from '../Graphics' import Series from '../Series' /** * ApexCharts Tooltip.Position Class to move the tooltip based on x and y position. * * @module Tooltip.Position **/ export default class Position { constructor (tooltipContext) { this.ttCtx = tooltipContext this.ctx = tooltipContext.ctx this.w = tooltipContext.w } /** * This will move the crosshair (the vertical/horz line that moves along with mouse) * Along with this, this function also calls the xaxisMove function * @memberof Position * @param {int} - cx = point's x position, wherever point's x is, you need to move crosshair */ moveXCrosshairs (cx, j = null) { const ttCtx = this.ttCtx let w = this.w const xcrosshairs = ttCtx.getElXCrosshairs() let x = cx - ttCtx.xcrosshairsWidth / 2 let tickAmount = w.globals.labels.slice().length if (j !== null) { x = (w.globals.gridWidth / tickAmount) * j } if (w.config.xaxis.crosshairs.width === 'tickWidth' || w.config.xaxis.crosshairs.width === 'barWidth') { if (x + ttCtx.xcrosshairsWidth > w.globals.gridWidth) { x = w.globals.gridWidth - ttCtx.xcrosshairsWidth } } else { if (j !== null) { x = x + (w.globals.gridWidth / tickAmount) / 2 } } if (x < 0) { x = 0 } if (x > w.globals.gridWidth) { x = w.globals.gridWidth } if (xcrosshairs !== null) { xcrosshairs.setAttribute('x', x) xcrosshairs.classList.add('active') } if (ttCtx.blxaxisTooltip) { let tx = x if (w.config.xaxis.crosshairs.width === 'tickWidth' || w.config.xaxis.crosshairs.width === 'barWidth') { tx = x + ttCtx.xcrosshairsWidth / 2 } this.moveXAxisTooltip(tx) } } /** * This will move the crosshair (the vertical/horz line that moves along with mouse) * Along with this, this function also calls the xaxisMove function * @memberof Position * @param {int} - cx = point's x position, wherever point's x is, you need to move crosshair */ moveYCrosshairs (cy) { const ttCtx = this.ttCtx if (ttCtx.ycrosshairs !== null) { Graphics.setAttrs(ttCtx.ycrosshairs, { y1: cy, y2: cy }) Graphics.setAttrs(ttCtx.ycrosshairsHidden, { y1: cy, y2: cy }) } } /** ** AxisTooltip is the small rectangle which appears on x axis with x value, when user moves * @memberof Position * @param {int} - cx = point's x position, wherever point's x is, you need to move */ moveXAxisTooltip (cx) { let w = this.w const ttCtx = this.ttCtx if (ttCtx.xaxisTooltip !== null) { ttCtx.xaxisTooltip.classList.add('active') let cy = ttCtx.xaxisOffY + w.config.xaxis.tooltip.offsetY + w.globals.translateY + 1 + w.config.xaxis.offsetY let xaxisTTText = ttCtx.xaxisTooltip.getBoundingClientRect() let xaxisTTTextWidth = xaxisTTText.width cx = cx - (xaxisTTTextWidth / 2) if (!isNaN(cx)) { cx = cx + w.globals.translateX let textRect = 0 const graphics = new Graphics(this.ctx) textRect = graphics.getTextRects(ttCtx.xaxisTooltipText.innerHTML) ttCtx.xaxisTooltipText.style.minWidth = textRect.width + 'px' ttCtx.xaxisTooltip.style.left = cx + 'px' ttCtx.xaxisTooltip.style.top = cy + 'px' } } } moveYAxisTooltip (index) { const w = this.w const ttCtx = this.ttCtx if (ttCtx.yaxisTTEls === null) { ttCtx.yaxisTTEls = w.globals.dom.baseEl.querySelectorAll('.apexcharts-yaxistooltip') } const ycrosshairsHiddenRectY1 = parseInt(ttCtx.ycrosshairsHidden.getAttribute('y1')) let cy = w.globals.translateY + ycrosshairsHiddenRectY1 const yAxisTTRect = ttCtx.yaxisTTEls[index].getBoundingClientRect() const yAxisTTHeight = yAxisTTRect.height let cx = w.globals.translateYAxisX[index] - 2 if (w.config.yaxis[index].opposite) { cx = cx - 26 } cy = cy - yAxisTTHeight / 2 if (w.globals.ignoreYAxisIndexes.indexOf(index) === -1) { ttCtx.yaxisTTEls[index].classList.add('active') ttCtx.yaxisTTEls[index].style.top = cy + 'px' ttCtx.yaxisTTEls[index].style.left = cx + w.config.yaxis[index].tooltip.offsetX + 'px' } else { ttCtx.yaxisTTEls[index].classList.remove('active') } } /** ** moves the whole tooltip by changing x, y attrs * @memberof Position * @param {int} - cx = point's x position, wherever point's x is, you need to move tooltip * @param {int} - cy = point's y position, wherever point's y is, you need to move tooltip * @param {int} - r = point's radius */ moveTooltip (cx, cy, r = null) { let w = this.w let ttCtx = this.ttCtx const tooltipEl = ttCtx.getElTooltip() let tooltipRect = ttCtx.tooltipRect let pointR = r !== null ? parseInt(r) : 1 let x = parseInt(cx) + pointR + 5 let y = parseInt(cy) + pointR / 2 // - tooltipRect.ttHeight / 2 if (x > w.globals.gridWidth / 2) { x = x - tooltipRect.ttWidth - pointR - 15 } if (x > w.globals.gridWidth - tooltipRect.ttWidth - 10) { x = w.globals.gridWidth - tooltipRect.ttWidth } if (x < -20) { x = -20 } if (w.config.tooltip.followCursor) { const elGrid = ttCtx.getElGrid() const seriesBound = elGrid.getBoundingClientRect() y = ttCtx.e.clientY - seriesBound.top - tooltipRect.ttHeight / 2 } const newPositions = this.positionChecks(tooltipRect, x, y) x = newPositions.x y = newPositions.y if (!isNaN(x)) { x = x + w.globals.translateX tooltipEl.style.left = x + 'px' tooltipEl.style.top = y + 'px' } } positionChecks (tooltipRect, x, y) { const w = this.w if (tooltipRect.ttHeight + y > w.globals.gridHeight) { y = w.globals.gridHeight - tooltipRect.ttHeight + w.globals.translateY } if (y < 0) { y = 0 } return { x, y } } moveMarkers (i, j) { let w = this.w let ttCtx = this.ttCtx if (w.globals.markers.size[i] > 0) { let allPoints = w.globals.dom.baseEl.querySelectorAll(` .apexcharts-series[data\\:realIndex='${i}'] .apexcharts-marker`) for (let p = 0; p < allPoints.length; p++) { if (parseInt(allPoints[p].getAttribute('rel')) === j) { ttCtx.marker.resetPointsSize() ttCtx.marker.enlargeCurrentPoint(j, allPoints[p]) } } } else { ttCtx.marker.resetPointsSize() this.moveDynamicPointOnHover( j, i ) } } // This function is used when you need to show markers/points only on hover - // DIFFERENT X VALUES in multiple series moveDynamicPointOnHover (j, capturedSeries) { let w = this.w let ttCtx = this.ttCtx let cx = 0 let cy = 0 let pointsArr = w.globals.pointsArray let hoverSize = w.config.markers.hover.size if (hoverSize === undefined) { hoverSize = w.globals.markers.size[capturedSeries] + w.config.markers.hover.sizeOffset } cx = pointsArr[capturedSeries][j][0] cy = pointsArr[capturedSeries][j][1] ? pointsArr[capturedSeries][j][1] : 0 let point = w.globals.dom.baseEl.querySelector( `.apexcharts-series[data\\:realIndex='${capturedSeries}'] .apexcharts-series-markers circle` ) point.setAttribute('r', hoverSize) point.setAttribute('cx', cx) point.setAttribute('cy', cy) // point.style.opacity = w.config.markers.hover.opacity this.moveXCrosshairs(cx) if (!ttCtx.fixedTooltip) { this.moveTooltip(cx, cy, hoverSize) } } // This function is used when you need to show markers/points only on hover - // SAME X VALUES in multiple series moveDynamicPointsOnHover (j) { const ttCtx = this.ttCtx let w = ttCtx.w let cx = 0 let cy = 0 let activeSeries = 0 let pointsArr = w.globals.pointsArray let series = new Series(this.ctx) activeSeries = series.getActiveSeriesIndex() let hoverSize = w.config.markers.hover.size if (hoverSize === undefined) { hoverSize = w.globals.markers.size[activeSeries] + w.config.markers.hover.sizeOffset } if (pointsArr[activeSeries]) { cx = pointsArr[activeSeries][j][0] cy = pointsArr[activeSeries][j][1] } let points = null const allPoints = ttCtx.getAllMarkers() if (allPoints !== null) { points = allPoints } else { points = w.globals.dom.baseEl.querySelectorAll( '.apexcharts-series-markers circle' ) } if (points !== null) { for (let p = 0; p < points.length; p++) { let pointArr = pointsArr[p] if (pointArr && pointArr.length) { let pcy = pointsArr[p][j][1] points[p].setAttribute('cx', cx) let realIndex = parseInt( points[p].parentNode.parentNode.parentNode.getAttribute( 'data:realIndex' ) ) if (pcy !== null) { points[realIndex] && points[realIndex].setAttribute('r', hoverSize) points[realIndex] && points[realIndex].setAttribute('cy', pcy) } else { points[realIndex] && points[realIndex].setAttribute('r', 0) } } } } this.moveXCrosshairs(cx) if (!ttCtx.fixedTooltip) { let tcy = cy || w.globals.gridHeight this.moveTooltip(cx, tcy, hoverSize) } } moveStickyTooltipOverBars (j) { const w = this.w const ttCtx = this.ttCtx let jBar = w.globals.dom.baseEl.querySelector(`.apexcharts-bar-series .apexcharts-series[rel='1'] path[j='${j}'], .apexcharts-candlestick-series .apexcharts-series[rel='1'] path[j='${j}']`) let bcx = jBar ? parseFloat(jBar.getAttribute('cx')) : 0 let bcy = 0 let bw = jBar ? parseFloat(jBar.getAttribute('barWidth')) : 0 if (w.globals.isXNumeric) { bcx = bcx - bw / 2 } else { bcx = ttCtx.xAxisTicksPositions[j - 1] + (ttCtx.dataPointsDividedWidth / 2) if (isNaN(bcx)) { bcx = ttCtx.xAxisTicksPositions[j] - (ttCtx.dataPointsDividedWidth / 2) } } // tooltip will move vertically along with mouse as it is a shared tooltip const elGrid = ttCtx.getElGrid() let seriesBound = elGrid.getBoundingClientRect() bcy = ttCtx.e.clientY - seriesBound.top - ttCtx.tooltipRect.ttHeight / 2 this.moveXCrosshairs(bcx) if (!ttCtx.fixedTooltip) { let tcy = bcy || w.globals.gridHeight this.moveTooltip(bcx, tcy) } } }