Home > Enterprise >  Fisheye effect D3js image slideshow works on rects/objects but not image files, Error: <image>
Fisheye effect D3js image slideshow works on rects/objects but not image files, Error: <image>

Time:12-06

My issue is that the animation works fine when the images have no content to them as below, but once they are loaded I get the following error: Error: <image> attribute x: Expected length, "NaN".

Here is a code snippet:

var data = ['https://cdn.britannica.com/60/8160-050-08CCEABC/German-shepherd.jpg', 'https://cdn.britannica.com/60/8160-050-08CCEABC/German-shepherd.jpg', 'https://cdn.britannica.com/60/8160-050-08CCEABC/German-shepherd.jpg', 'https://cdn.britannica.com/60/8160-050-08CCEABC/German-shepherd.jpg', 'https://cdn.britannica.com/60/8160-050-08CCEABC/German-shepherd.jpg'];

var w = window,
  d = document,
  e = d.documentElement,
  g = d.getElementsByTagName('body')[0],
  wid = 400
y = 400;

var svg = d3.select("body").append("svg")
  .attr("width", wid)
  .attr("height", "400")
  .on('mousemove', () => {
    let x = event.x - 20;
    d3.selectAll('.content')
      .attr('x', (d, i) => fisheye(d, x))
  })
  .on('mouseleave', () => {
    d3.selectAll('.content').transition().attr(
      'x', (d, i) => xScale(i))
  })

var chart = svg.append('g')
  .classed('group', true)


let xScale = d3.scaleBand().domain(d3.range(5)).range([0, wid]).padding(0)

let rects = svg.selectAll('content')
  .data(
    d3.range(5)
    //data //(uncomment this, and comment line above to try loading images)
  )

rects.exit().remove();

rects.enter()
  .append("svg:image")
  .attr("xlink:href", d => d)
  .attr("class", "content")
  .attr("y", 0)
  .attr("x", (d, i) => xScale(i))
  .attr("width", "300px")
  .style("opacity", 1)
  .attr("stroke", "white")
  .style('fill', 'rgb(81, 170, 232)')
  .attr("height", 400);

let distortion = 10;

function fisheye(_, a) {
  let x = xScale(_),
    left = x < a,
    range = d3.extent(xScale.range()),
    min = range[0],
    max = range[1],
    m = left ? a - min : max - a;
  if (m === 0) m = max - min;

  return (left ? -1 : 1) * m * (distortion   1) / (distortion   (m / Math.abs(x - a)))   a;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

I'm trying to make something that looks like this: https://www.nytimes.com/newsgraphics/2013/09/13/fashion-week-editors-picks/index.html

I would really appreciate some help on getting that snippet to work and if possible as smoothly as this website link! That was made by the Bosstock himself and I'm a d3 newbie so I'm quite out of my depth.

CodePudding user response:

I figured out my issue-

let xScale = d3.scaleBand().domain(data).range([0,wid]).padding(0)

The domain was d3.range(5) rather than my data variable.

  • Related