Coder Social home page Coder Social logo

d3-v6-tip's Introduction

SWUbanner

d3-v6-tip

A famous d3-tip lib adapted to the latest - d3.v6 version.

Foreword

d3.v6 introduced several changes and some of them concerns d3-tip.

Those are:

  • Global d3.event has been removed
  • Every event handler, from now on, will receive event as a first argument

d3-tip version which lies under this repository, is adapted to this change.

It also fixes one annoying bug, when several DOM tip instances were being created , which eventually would lead unexpected and undesirable results.

See original documentation, but please note changes in tip.html API.
Short story is that, you will get same arguments in tip.html() as tip.show() receives, in the same order.

Installing

If you are using npm

npm i d3-v6-tip

And then use it like this in your application

import { tip as d3tip } from "d3-v6-tip";

const tip = d3tip()

Otherwise, you can load as a standalone library or as part of D3. ES modules, AMD, CommonJS, and vanilla environments are supported. In vanilla, a d3 global is exported:

If you want to load it as part of d3

<script src="https://d3js.org/d3.v6.min.js"></script>
<script src="https://unpkg.com/[email protected]/build/d3-v6-tip.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/bumbeishvili/d3-tip-for-v6@4/d3-tip.min.css">

<script>

const tip = d3.tip()

</script>

If you want to load it as standalone

<script src="https://d3js.org/d3-selection.v2.min.js"></script>
<script src="https://unpkg.com/[email protected]/build/d3-v6-tip.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/bumbeishvili/d3-tip-for-v6@4/d3-tip.min.css">

<script>
var svg = d3.select('svg');

/* Initialize tooltip */
var tip = d3.tip().attr('class', 'd3-tip').html((EVENT,d)=> d );

    
/* Invoke the tip in the context of your visualization */
svg.call(tip)

    
// -------------- Simplest usage ----------------
svg.selectAll('rect')
    .on('mouseover', tip.show)
    .on('mouseout', tip.hide)
        
    
// ------------- Conditional usage -------------
svg.selectAll('rect')
    .on('mouseover', (event,d)=>{
          if(someCondition) tip.show(event,d);
     })
    .on('mouseout', tip.hide)
    
    
// ------------- Showing tip on particular element, but based on other DOM element's data -------------
svg.selectAll('g')
    .on('mouseover', function(event,d) {
          const element = d3.select(this)
                            .select('.particular-element');
          tip.show(event, d, element.node())
     })
    .on('mouseout', tip.hide)
</script>

See minimal jsfiddle example here

Style

for default styling, include this css file into your app

.d3-tip {
  font-family: Arial, Helvetica, sans-serif;
  line-height: 1.4;
  padding: 20px;
  pointer-events: none !important;
  color: #203d5d;
  box-shadow: 0 4px 20px 4px rgba(0, 20, 60, .1), 0 4px 80px -8px rgba(0, 20, 60, .2);
  background-color: #fff;
  border-radius: 4px;
}

/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
  box-sizing: border-box;
  display: inline;
  font-size: 10px;
  width: 100%;
  line-height: 1;
  color: #fff;
  position: absolute;
  pointer-events: none;
}

/* Northward tooltips */
.d3-tip.n:after {
  content: "▼";
  margin: -1px 0 0 0;
  top: 100%;
  left: 0;
  text-align: center;
}

/* Eastward tooltips */
.d3-tip.e:after {
  content: "◀";
  margin: -4px 0 0 0;
  top: 50%;
  left: -8px;
}

/* Southward tooltips */
.d3-tip.s:after {
  content: "▲";
  margin: 0 0 1px 0;
  top: -8px;
  left: 0;
  text-align: center;
}

/* Westward tooltips */
.d3-tip.w:after {
  content: "▶";
  margin: -4px 0 0 -1px;
  top: 50%;
  left: 100%;
}

History

Author

David B (twitter)
David B (linkedin)

I am available for freelance data visualization work. Please contact me in case you'd like me to help you with my experience and expertise

You can also book data viz related consultation session with me

d3-v6-tip's People

Contributors

bumbeishvili avatar smontanari avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

d3-v6-tip's Issues

Allow Tooltip to follow mouse cursor

https://jsfiddle.net/2ukpa84c/5/

In this example, I have a zoomable and draggable map. By double clicking the map, you zoom in. However, the tooltip position still stays the same, so if you zoomed-in, you can't' see the tooltip anymore. Also the tooltip doesn't seem to be in the right position. For example, when hover over an element on the map, the tooltip will show up on the area of other elements.

The problem I am facing is similar to this issue

Is there a way to configure that?

add license

Hello - great project! Are there any plans to add a license, so that this can be used in other projects? The original d3-tip was MIT.

Could not find a declaration file for module 'd3-v6-tip'

Expected behavior: no errors when importing:

import { tip as d3tip } from 'd3-v6-tip';

Actual behavior: error:

Could not find a declaration file for module 'd3-v6-tip'. '/usr/src/app/node_modules/d3-v6-tip/build/d3-v6-tip.js' implicitly has an 'any' type.
web_1  |   Try `npm i --save-dev @types/d3-v6-tip` if it exists or add a new declaration (.d.ts) file containing `declare module 'd3-v6-tip';`

Can't specify rootElement using npm import

I'm using NPM and installed the 1.0.8 version of d3-v6-tip. I'm trying to specify a different element where I can append the tooltip (for style reasons), but it's still attaching to the document body.

The code I'm using is this

this.tip = d3tip()
      .attr('class', 'd3-tip')
      .rootElement(document.getElementById('graph'))
      .html((EVENT, d) => d.tooltip.replace('_x', d.x).replace('_y', d.y))

but I'm receiving the following error

index.js:157 Uncaught TypeError: Object(...)(...).attr(...).rootElement is not a function

Can you please help me? I don't want to load this library as a standalone library, so I'm trying this road. Thank you very much

Package not downloading

Hi! I'm trying to download the package via npm and it gets this error:

Unexpected token } in JSON at position 438154 while parsing near '...k3DGag==" npm ERR! } npm ERR! } npm ERR! }

Thanks!

Suggestion: user should choose the positioning of the tooltip

By default, the tooltip is positioned as 'absolute' as reported in the following snippets (not in the same position in the original code):

tipNode
      .classed('d3-tip-lib-node', true)
      .style('position', 'absolute')
      .style('top', '0')
      .style('opacity', '0')
      .style('pointer-events', 'none')
      .style('box-sizing', 'border-box')


nodel.html(content)
            .style('position', 'absolute')
            .style('opacity', 1)
            .style('pointer-events', 'all')

This positioning, however can lead to different problems, as, for example, if the chart is contained in a 'relative' container, the position of the tooltip isn't correct. In the example, a 'fixed' positioning should be considered.

What about adding a custom option to set it absolute? Thank you in advance and I hope to do something for you that can be useful

tooltip flicker on top left corner when hiding

I'm in the process of migrating my project to d3 version 6 and I was glad to see you had taken the time to continue to maintain the original d3-tip package by @caged.

Unfortunately I run into the following issue when using the new version of the tooltip:
when invoking the hide() function (typically on a mouseout event) the tooltip briefly appears at the top left corner of the browser window, only to disappear instants later. This issue is a bit annoying and happens whenever there is enough room in the layout for the mouseout event to be triggered and processed (hence invoking the hide() function).

The original d3-tip version did not have this problem, and I noticed a difference in your implementation of the hide function with respect to that, where you explicitly set the position of the tooltip to the top left corner before setting the opacity, i.e.:

nodel
    .style('top', 0)
    .style('left', 0)
    .style('opacity', 0)
    .style('pointer-events', 'none')

I'm not aware of the reasons for resetting the position of the tooltip, but it appears that the positioning takes precedence over the setting of the opacity, hence the flickering of the tooltip at the top left corner of the document. I tried swapping the style instructions around, applying the opacity before the position, but with no success.
When instead I re-introduced the original code, removing the positioning altogether, the problem went away.

Would you consider the possibility of removing the position (re-)setting, or, at least, to make it configurable?

How to upgrade to v6 within a file containing CommonJS syntax imports and so fixing d3-color vulnerability.

Hi,

We use that project :
https://github.com/thoughtworks/build-your-own-radar

It depends on a version of the d3-tip library, imported with the CommonJS syntax (from this file: (https://github.com/thoughtworks/build-your-own-radar/blob/master/src/graphing/radar.js) as it follows:

const d3 = require('d3')
const d3tip = require('d3-tip')

We just got a report of a current vulnerability :
Regular Expression Denial of Service (ReDoS) in d3-color | Snyk

So, we'd like to upgrade the d3-tip library to its 6th version but it doesn’t seem to work.

const d3 = require('d3')
const d3tip = require('d3-v6-tip')

Trying this out, we got this error message:
Error message Radar js 2022-10-04 16_04_38-Window

Could you please help?

Thanks.
Christophe

d3.event in getScreenBBox() function

I am running into an d3.event is undefined is undefined while trying to create a tooltip. I suspect that it may has to do with the d3.event in getScreenBBox(). because in d3v6, it is replaced with event.target.

This is how I select my svg and calls the tip function

var svg = d3.select("#mapDiv")
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .style("background-color", "white")
    .style("border", "solid 1px black")
    .call(d3.zoom()
        .on("zoom", function (event) {
            svg.attr("transform", event.transform);
        })
        .scaleExtent([1, 1])
    )
    .append("g");

const tip = d3.tip().attr('class', 'd3-tip').html(function (event, d) {
    console.log(event.target.id);
    return event.target.id;
});

svg.call(tip);

This is how I draw my map:

d3.json(path).then(function (json) {
    var projection = d3.geoMercator();
    var features = json.features;

    var fixed = features.map(function (feature) {
        return turf.rewind(feature, { reverse: true });
    })

    var geoPath = d3.geoPath().projection(projection);

    projection.fitSize([width, height], { "type": "FeatureCollection", "features": fixed })

    svg.selectAll("path")
        .data(fixed)
        .enter()
        .append("path")
        .attr("d", geoPath)
        .attr("id", function (d) { return d.properties.FIPS_10_; })
        .style("fill", "red")
        .style("stroke", "transparent")
        .on("mouseover", mouseOver)
        .on("mouseleave", mouseLeave)
        .on("click", mouseClick)
})

How I call tip.show in my mouseOver function:

let mouseOver = function (event, d) {
    var countryCode = event.target.__data__.properties.FIPS_10_;  
    d3.selectAll("path#" + countryCode)
        .transition()
        .duration(200)
        .style("opacity", 1)
        .style("stroke", "black")

    tip.show(event, d);

}

The problem: I put a console.log in my tip declaration. When my mouse hover over it, it shows the current country name in the console(event.target.id). However, the tooltip never show up due to the error: Uncaught TypeError: d3.event is undefined.

D3 is undefined

I am having errors with d3 being undefined, from the function below. Ican see that import * as d3 was commented out on line 9. How is D3 Imported?

 function getScreenBBox() {
        var targetel = target || d3.event.target;
...
}

my hacky test is as follows (not suggesting it as a solution, just verifying it resolved the issue):
var targetel = target || require('d3').event.target;

in my application, i am doing the following (perhaps the issue is user error..?) it is buried inside Vue/webpack and whatnot, so there is a possible source of issues too.

import * as d3 from 'd3' 
import { tip as d3tip } from 'd3-v6-tip'
...
const tip = d3tip()
    .attr('class', 'd3-tip')
    .html(d => d)
svg.call(tip)
...
rects
    .enter()
    ...
    .attr('mouseover', tip.show)
    .attr('mouseout', tip.hide)
...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.