Skip to content

Instantly share code, notes, and snippets.

@monzou monzou/tooltip.js
Last active Jun 26, 2018

Embed
What would you like to do?
GuidelineLayer + Tooltip w/ Plottable.js
import d3 from 'd3/d3'
import Plottable from './plottable'
const findDOMNode = (node, tag) => {
tag = tag.toUpperCase()
while (node.parentNode) {
node = node.parentNode
if (node.tagName.toUpperCase().trim() === tag) {
return node
}
}
throw new Error(`DOM node does not found: ${tag}`)
}
class Tooltip {
constructor (options = {}) {
this.options = Object.assign({
offset: {
x: 10,
y: 10
}
}, options)
}
onShow (callback) {
this.onShow = callback
return this
}
onHide (callback) {
this.onHide = callback
return this
}
attachTo (component) {
const node = findDOMNode(component.foreground().node(), 'div')
const attachment = d3.select(node).append('div').classed('truth', true).classed('tooltip-container', true)
new Plottable.Interactions.Pointer().onPointerMove(point => {
this.show(attachment, point, component)
}).onPointerExit(point => {
this.hide(attachment, point, component)
}).attachTo(component)
}
show (attachment, point, component) {
if (this.onShow && typeof this.onShow === 'function') {
this.onShow(attachment, point)
}
const position = this.calculatePosition(attachment, point, component)
this.showAttachment(attachment, position, component)
}
showAttachment (attachment, position, component) {
attachment.style({
'position': 'absolute',
'visibility': 'visible',
'z-index': this.options.z || 1001,
'left': position.x + 'px',
'top': position.y + 'px'
})
}
hide (attachment, point, component) {
if (this.onHide && typeof this.onHide === 'function') {
this.onHide(attachment, point)
}
this.hideAttachment(attachment, component)
}
hideAttachment (attachment, component) {
attachment.style({
'visibility': 'hidden'
})
}
calculatePosition (attachment, point, component) {
const backgroundNode = component.background().node()
const backgroundMatrix = this._matrix(backgroundNode)
const backgroundBBox = backgroundNode.getBBox()
const attachmentNode = attachment[0][0]
const offset = this.options.offset
const x0 = point.x
const x1 = backgroundBBox.x + backgroundBBox.width
const width = attachmentNode.clientWidth
const x = (x0 + offset.x + width) > x1 ? (x1 - width) : (x0 + offset.x)
const y0 = point.y
const y1 = backgroundBBox.y + backgroundBBox.height
const height = attachmentNode.clientHeight
const y = (y0 + offset.y + height) > y1 ? (y1 - height) : (y0 + offset.y)
return {
x: x + window.pageXOffset + backgroundMatrix.e,
y: y + window.pageYOffset + backgroundMatrix.f
}
}
_matrix (node) {
return node.getScreenCTM().translate(+node.getAttribute('cx'), +node.getAttribute('cy'));
}
}
class GuidelineTooltip extends Tooltip {
constructor (options = {}) {
super(options)
}
attachTo (guideline) {
guideline.onAnchor(() => this._hideGuideline(guideline))
super.attachTo(guideline)
}
showAttachment (attachment, position, guideline) {
this._showGuideline(guideline)
super.showAttachment(attachment, position, guideline)
}
hideAttachment (attachment, guideline) {
this._hideGuideline(guideline)
super.hideAttachment(attachment, guideline)
}
calculatePosition (attachment, point, guideline) {
return super.calculatePosition(attachment, this._adjustPoint(point, guideline), guideline)
}
_adjustPoint (point, guideline) {
return {
x: guideline._orientation === 'vertical' ? guideline.pixelPosition() : point.x,
y: guideline._orientation === 'vertical' ? point.y : guideline.pixelPosition()
}
}
_showGuideline (guideline) {
const content = guideline.content();
if (content) {
content.style({
"visibility": "visible"
});
}
}
_hideGuideline (guideline) {
const content = guideline.content();
if (content) {
content.style({
"visibility": "hidden"
});
}
}
}
export default {
Simple: Tooltip,
Guideline: GuidelineTooltip
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.