0

I am trying to incorporate d3-lasso into a d3 project with React, and I see a lot of people are having similar problems to me, but I can't find a solution that works. To remove any complicating factors, I'm trying to simply get this example to work in React. I've tried several permutations with Stack and Github solutions, but I always get Attempted import error: 'lasso' is not exported from 'd3' (imported as 'd3'). Here is my code:

import React, { useRef } from 'react'
import * as d3 from 'd3'
import ReactSlider from 'react-slider'
import * as lasso from 'd3-lasso'
// import { lasso } from 'd3-lasso' also doesn’t work 
// import lasso from 'd3-lasso' also doesn't work 
import './styles.css'
import './LineChart.css'

const ClusterViewer = () => {
  const d3Chart = useRef(null)
  const createChart = () => {
    const data = [['Arsenal', -0.0032967741593940836, 0.30399753945657115], ['Chelsea', 0.2752159801936051, -0.0389675484210763], ['Liverpool', -0.005096951348655329, 0.026678627680541075], ['Manchester City', -0.004715381791104284, -0.12338379196523988], ['Manchester United', 0.06877966010653305, -0.0850615090351779], ['Tottenham', -0.3379518099485709, -0.09933664174939877]]

    const colours = d3.scaleOrdinal()
      .domain(data)
      .range(['#F8B195', '#F67280', '#C06C84', '#6C5B7B', '#355C7D', '#2A363B'])

    const canvasW = 675
    const canvasH = 400
    const w = 365
    const h = 365
    const xPadding = 30
    const yPadding = 20
    const padding = 10

    const xScale = d3.scaleLinear()
      .range([xPadding, w - padding])
      .domain([-1, 1])

    const yScale = d3.scaleLinear()
      .range([h - yPadding, padding])
      .domain([-1, 1])

    const svg = d3.select('body')
      .append('svg')
      .attr('width', canvasW)
      .attr('height', canvasH)

    const circles = svg.selectAll('circle')
      .data(data)
      .enter()
      .append('circle')
      .attr('r', 7)
      .attr('cx', d => xScale(d[1]))
      .attr('cy', d => yScale(d[2]))
      .attr('fill', d => {
        let result = null

        if (data.indexOf(d) >= 0) {
          result = colours(d)
        } else {
          result = 'white'
        }
        return result
      })
    const graphLasso = d3.lasso()
      .closePathDistance(75)
      .closePathSelect(true)
      .targetArea(svg)
      .items(circles)
      .on('start', lasso_start)
      .on('draw', lasso_draw)
      .on('end', lasso_end)

    function lasso_start() {
      graphLasso.items()
        .attr('r', 7)
        .classed('not_possible', true)
        .classed('selected', false)
    }

    function lasso_draw() {
      graphLasso.possibleItems()
        .classed('not_possible', false)
        .classed('possible', true)

      graphLasso.notPossibleItems()
        .classed('not_possible', true)
        .classed('possible', false)
    }

    function lasso_end() {
      graphLasso.items()
        .classed('not_possible', false)
        .classed('possible', false)

      graphLasso.selectedItems()
        .classed('selected', true)
        .attr('r', 7)

      graphLasso.notSelectedItems()
        .attr('r', 3.5)
    }

    const legend = svg.selectAll('.legend')
      .data(colours.domain())
      .enter()
      .append('g')
      .attr('class', 'legend')
      .attr('transform', (d, i) => `translate(0,${i * 29})`)

    legend.append('rect')
      .attr('x', canvasW - 184)
      .attr('y', 11)
      .attr('width', 18)
      .attr('height', 18)
      .style('fill', colours)

    legend.append('text')
      .attr('x', canvasW - 194)
      .attr('y', 20)
      .attr('dy', '.35em')
      .style('text-anchor', 'end')
      .text(d => d[0])

    svg.call(graphLasso)
  }

  // ...

  return (
    <div>
      <h1>
        Cluster Viewer
      </h1>
      <div>
        <script src="https://d3js.org/d3.v4.min.js" />
        <svg ref={d3Chart} />
      </div>
    </div>
  )
}

export default ClusterViewer
johnnyb
  • 41
  • 4

0 Answers0