首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >修改D3js V4的笛卡尔DIstortion

修改D3js V4的笛卡尔DIstortion
EN

Stack Overflow用户
提问于 2017-03-09 19:44:05
回答 1查看 755关注 0票数 3

我正在尝试实现this效果。我能找到的最接近这种效果的工作例子是笛卡尔失真效果,它似乎不适用于D3 V4。我真的不知道需要更改哪些行,或者如何更改才能使此示例与d3js版本4兼容。

jsfiddle

代码语言:javascript
复制
    (function chart3() {
  console.clear()
  var width = 960,
      height = 180,
      xSteps = d3.range(10, width, 16),
      ySteps = d3.range(10, height, 16);



  var xFisheye = d3.fisheye.scale(d3.scale.identity).domain([0, width]).focus(360),
      yFisheye = d3.scale.linear().domain([0, height]);

  var svg = d3.select("#chart3").append("svg")
      .attr("width", width)
      .attr("height", height)
    .append("g")
      .attr("transform", "translate(-.5,-.5)");

  svg.append("rect")
      .attr("class", "background")
      .attr("width", width)
      .attr("height", height);

  var xLine = svg.selectAll(".x")
      .data(xSteps)
    .enter().append("line")
      .attr("class", "x")
      .attr("y2", height);

  redraw();

  svg.on("mousemove", function() {
    var mouse = d3.mouse(this);

    // HACK ( only for left-side )
    xFisheye.focus(mouse[0] - 32);    // HACK 1
    yFisheye(mouse[1]);
    if(mouse[0] > 26)  // HACK 2
        redraw();
  });

  function redraw() {
    xLine.attr("x1", xFisheye).attr("x2", xFisheye);
  }
})();
EN

回答 1

Stack Overflow用户

发布于 2017-10-06 07:55:16

不管怎么说,我刚刚调整了d3-fisheye插件,使其可以与d3 v4一起工作。我还添加了可能有用的fisheye.invert

代码语言:javascript
复制
import * as d3 from 'd3'

const fisheye = {
  scale: function (scaleType) {
    return d3FisheyeScale(scaleType(), 3, 0)
  },
  circular: function () {
    let radius = 200
    let distortion = 2
    let k0
    let k1
    let focus = [0, 0]

    function fisheye (d) {
      let dx = d.x - focus[0]
      let dy = d.y - focus[1]
      let dd = Math.sqrt(dx * dx + dy * dy)
      if (!dd || dd >= radius) return {x: d.x, y: d.y, z: dd >= radius ? 1 : 10}
      let k = k0 * (1 - Math.exp(-dd * k1)) / dd * 0.75 + 0.25
      return {x: focus[0] + dx * k, y: focus[1] + dy * k, z: Math.min(k, 10)}
    }

    function rescale () {
      k0 = Math.exp(distortion)
      k0 = k0 / (k0 - 1) * radius
      k1 = distortion / radius
      return fisheye
    }

    fisheye.radius = function (_) {
      if (!arguments.length) return radius
      radius = +_
      return rescale()
    }

    fisheye.distortion = function (_) {
      if (!arguments.length) return distortion
      distortion = +_
      return rescale()
    }

    fisheye.focus = function (_) {
      if (!arguments.length) return focus
      focus = _
      return fisheye
    }

    return rescale()
  }
}

function d3FisheyeScale (scale, d, a) {
  function fisheye (_) {
    let x = scale(_)
    let left = x < a
    let range = d3.extent(scale.range())
    let min = range[0]
    let max = range[1]
    let m = left ? a - min : max - a
    if (m === 0) m = max - min
    return (left ? -1 : 1) * m * (d + 1) / (d + (m / Math.abs(x - a))) + a
  }

  fisheye.invert = function (xf) {
    let left = xf < a
    let range = d3.extent(scale.range())
    let min = range[0]
    let max = range[1]
    let m = left ? a - min : max - a
    if (m === 0) m = max - min
    return scale.invert(a + m * (xf - a) / ((d + 1) * m - (left ? -1 : 1) * d * (xf - a)))
  }

  fisheye.distortion = function (_) {
    if (!arguments.length) return d
    d = +_
    return fisheye
  }

  fisheye.focus = function (_) {
    if (!arguments.length) return a
    a = +_
    return fisheye
  }

  fisheye.copy = function () {
    return d3FisheyeScale(scale.copy(), d, a)
  }

  fisheye.nice = scale.nice
  fisheye.ticks = scale.ticks
  fisheye.tickFormat = scale.tickFormat

  const rebind = function (target, source) {
    let i = 1
    const n = arguments.length
    let method
    while (++i < n) {
      method = arguments[i]
      target[method] = d3Rebind(target, source, source[method])
    };
    return target
  }
  function d3Rebind (target, source, method) {
    return function () {
      var value = method.apply(source, arguments)
      return value === source ? target : value
    }
  }
  return rebind(fisheye, scale, 'domain', 'range')
}

export default fisheye

现在使用它:

代码语言:javascript
复制
import fisheye from './fisheye'
import { scaleLinear, scalePow } from 'd3-scale'

const fisheyeLinearScale = fisheye.scale(scaleLinear)
const fisheyePowScale = fisheye.scale(scalePow().exponent(1.1).copy)

const myFisheyeScale = fisheyePowScale.domain(<domain>)
                                      .range(<range>)
                                      .focus(<mouseX>)
                                      .distortion(<deformation>)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42694544

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档