首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >d3fc -使用最新版本14截图的十字线

d3fc -使用最新版本14截图的十字线
EN

Stack Overflow用户
提问于 2020-01-20 23:13:23
回答 1查看 503关注 0票数 3

在以前版本的d3fc中,我的代码使用fc.util.seriesPointSnapXOnly来抓取十字线。

这似乎在d3fc的最新版本中消失了(或者我在一个独立的包中遗漏了它?)。

我使用的是画布实现(annotationCanvasCrosshair),它似乎也缺少了以前像这样使用的"snap“函数:

代码语言:javascript
复制
fc.tool.crosshair()
 .snap(fc.util.seriesPointSnapXOnly(line, series))

此外,"on“也不可用,所以我不能附加诸如trackingstart、trackingend等事件。

我现在怎么才能实现一条交叉剪线呢?组件的画布版本非常缺乏示例。有没有人有一个通过画布呈现显示d3fc最新版本中的交叉头发的例子?

到目前为止,https://codepen.io/parliament718/pen/xxbQGgp的情况如下

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-11 09:53:52

我知道您已经向d3fc github提出了这个问题,因此我假设您知道util/snap.js 不受欢迎

由于这个功能现在不受支持,因此似乎唯一可行的方法就是实现您自己的功能。

我以您的钢笔原始snap.js码为起点,并应用了文档中简单的横发例子中概述的方法。

最后,我不得不逐字添加缺少的函数及其依赖项(当然,您可以重构并打包到一个单独的模块中):

代码语言:javascript
复制
function defined() {
    var outerArguments = arguments;
    return function(d, i) {
        for (var c = 0, j = outerArguments.length; c < j; c++) {
            if (outerArguments[c](d, i) == null) {
                return false;
            } 
        }
        return true;
    };
}

function minimum(data, accessor) {
    return data.map(function(dataPoint, index) {
        return [accessor(dataPoint, index), dataPoint, index];
    }).reduce(function(accumulator, dataPoint) {
        return accumulator[0] > dataPoint[0] ? dataPoint : accumulator;
    }, [Number.MAX_VALUE, null, -1]);
}

function pointSnap(xScale, yScale, xValue, yValue, data, objectiveFunction) {
    // a default function that computes the distance between two points
    objectiveFunction = objectiveFunction || function(x, y, cx, cy) {
        var dx = x - cx,
            dy = y - cy;
        return dx * dx + dy * dy;
    };

    return function(point) {
        var filtered = data.filter(function(d, i) {
            return defined(xValue, yValue)(d, i);
        });

        var nearest = minimum(filtered, function(d) {
            return objectiveFunction(point.x, point.y, xScale(xValue(d)), yScale(yValue(d)));
        })[1];

        return [{
            datum: nearest,
            x: nearest ? xScale(xValue(nearest)) : point.x,
            y: nearest ? yScale(yValue(nearest)) : point.y
        }];
    };
}

function seriesPointSnap(series, data, objectiveFunction) {
    return function(point) { 
        var xScale = series.xScale(),
            yScale = series.yScale(),
            xValue = series.crossValue(),
            yValue = (series.openValue).call(series);
        return pointSnap(xScale, yScale, xValue, yValue, data, objectiveFunction)(point);
    };
};

function seriesPointSnapXOnly(series, data) {
    function objectiveFunction(x, y, cx, cy) {
        var dx = x - cx;
        return Math.abs(dx);
    }
    return seriesPointSnap(series, data, objectiveFunction);
}

工作的最终结果可以在这里看到:kh/pen/YzXXOOG。我基本上定义了两个系列,并使用pointer组件更新第二个系列数据并触发重呈现:

代码语言:javascript
复制
    const data = {
      series: stream.take(50), // your candle stick chart
      crosshair: [] // second series to hold the crosshair position
    };
    .............
    const crosshair = fc.annotationCanvasCrosshair() // define your crosshair

    const multichart = fc.seriesCanvasMulti()
            .series([candlesticks, crosshair]) // we've got two series now
      .mapping((data, index, series) => {
      switch(series[index]) {
        case candlesticks:
          return data.series;
        case crosshair:
          return data.crosshair;
      }
    });
    .............
function render() {
  d3.select('#zoom-chart')
    .datum(data)
    .call(chart);  
    // add the pointer component to the plot-area, re-rendering each time the event fires.
  var pointer = fc.pointer()
    .on('point', (event) => {     
      data.crosshair = seriesPointSnapXOnly(candlesticks, data.series)(event[0]);// and when we update the crosshair position - we snap it to the other series using the old library code.
      render();
    });

  d3.select('#zoom-chart .plot-area')
    .call(pointer); 
}

UPD:功能可以简化如下,我还更新了笔:

代码语言:javascript
复制
function minimum(data, accessor) {
    return data.map(function(dataPoint, index) {
        return [accessor(dataPoint, index), dataPoint, index];
    }).reduce(function(accumulator, dataPoint) {
        return accumulator[0] > dataPoint[0] ? dataPoint : accumulator;
    }, [Number.MAX_VALUE, null, -1]);
}

function seriesPointSnapXOnly(series, data, point) { 
        if (point == undefined) return []; // short circuit if data point was empty
        var xScale = series.xScale(),
            xValue = series.crossValue();

        var filtered = data.filter((d) => (xValue(d) != null));
        var nearest = minimum(filtered, (d) => Math.abs(point.x - xScale(xValue(d))))[1]; 

        return [{
            x: xScale(xValue(nearest)),
            y: point.y 
        }];
    };

这还远远不够完善,但我希望它传达的是一般的想法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59832117

复制
相关文章

相似问题

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