【问题标题】:dc.js - Rendering two objects (one chart - renders, one shape - doesn't) together in one group?dc.js - 在一组中一起渲染两个对象(一个图表 - 渲染,一个形状 - 不)?
【发布时间】:2020-04-23 05:52:19
【问题描述】:

我有两个需要渲染的元素和一个我想要实现的大图的上下文(一个完整的仪表板)。

一个是渲染良好的图表。

 $scope.riskChart = new dc.pieChart('#risk-chart');
 $scope.riskChart
       .width(width)
       .height(height)
       .radius(Math.round(height/2.0))
       .innerRadius(Math.round(height/4.0))
       .dimension($scope.quarter)
       .group($scope.quarterGroup)
       .transitionDuration(250);

另一个是三角形,用于更复杂的形状

 $scope.openChart = d3.select("#risk-chart svg g")
        .enter()
        .attr("width", 55)
        .attr("height", 55)
        .append('path')
        .attr("d", d3.symbol('triangle-up'))
        .attr("transform", function(d) { return "translate(" + 100 + "," + 100 + ")"; })
        .style("fill", fill);

在调用渲染函数时,会识别 dc.js 渲染函数并看到图表,但无法识别 d3.js 渲染()函数。

如何将此形状添加到我的 dc.js 画布(一个 svg 元素)。

 $scope.riskChart.render();   <--------------Works!
 $scope.openChart.render();   <--------------Doesn't work (d3.js)!

我该如何进行这项工作?

编辑:

我修改了 dc.js 以包含我的自定义图表,这是一项正在进行的工作。

dc.starChart =  function(parent, fill) {
    var _chart = {};
    var _count = null, _category = null;
    var _width, _height;
    var _root = null, _svg = null, _g = null;
    var _region;
    var _minHeight = 20;
    var _dispatch = d3.dispatch('jump');

    _chart.count = function(count) {
        if(!arguments.length)
            return _count;
        _count = count;
        return _chart;
    };

    _chart.category = function(category) {
        if(!arguments.length)
            return _category
        _category = category;
        return _chart;
    };


function count() {
    return _count;
}

function category() {
    return _category;
}

function y(height) {
    return isNaN(height) ? 3 : _y(0) - _y(height);
}



_chart.redraw = function(fill) {
    var color = fill;  
    var triangle = d3.symbol('triangle-up');
    this._g.attr("width", 55)
        .attr("height", 55)
        .append('path')
        .attr("d", triangle)
        .attr("transform", function(d) { return "translate(" + 25 + "," + 25 + ")"; })
        .style("fill", fill);
    return _chart;

};     

_chart.render = function() {
    _g = _svg
        .append('g');

    _svg.on('click', function() {
        if(_x)
            _dispatch.jump(_x.invert(d3.mouse(this)[0]));
    });
    if (_root.select('svg'))
        _chart.redraw();
    else{
        resetSvg();                    
        generateSvg();
    }
    return _chart;
};

_chart.on = function(event, callback) {
    _dispatch.on(event, callback);
    return _chart;
};

_chart.width = function(w) {
    if(!arguments.length)
        return this._width;
    this._width = w;
    return _chart;
};

_chart.height = function(h) {
    if(!arguments.length)
        return this._height;
    this._height = h;
    return _chart;
};

_chart.select = function(s) {
    return this._root.select(s);
};

_chart.selectAll = function(s) {
    return this._root.selectAll(s);
};

function resetSvg() {
    if (_root.select('svg'))
        _chart.select('svg').remove();
    generateSvg();
}

function generateSvg() {
    this._svg = _root.append('svg')
        .attr({width: _chart.width(),
               height: _chart.height()});
}

_root = d3.select(parent);
return _chart;

}

【问题讨论】:

  • .render() 是 dc.js 图表上的一种方法。 D3 的层次要低得多——更像是一个没有任何图表或渲染/重绘概念的图形库。虽然这不是一个完全相同的重复,但我将投票结束另一个问题,我希望它能解释你所缺少的。
  • 这能回答你的问题吗? dc.js - Listening for chart group render
  • 我经常看到 d3.js 和 dc.js 之间的这种混淆 - 如果有什么我可以添加到 dc.js 文档中以使库之间的关系更加清晰,请 lmk。
  • 是的,那已经过时了 - 感谢您的提醒!我已经更新了它。如果您遇到其他问题,请对该答案发表评论。
  • 这个选项卡在我的屏幕上仍然打开,我意识到您可能根本不想添加另一个图表,而只是想用一些其他内容注释饼图。为此,您需要查看.on('pretransition',...) or .on('renderlet', ...)。如果您四处搜索,您会在网络上找到许多示例。

标签: javascript d3.js dashboard dc.js


【解决方案1】:

我想我在谈论如何创建新图表时混淆了问题,而实际上您只是想向现有图表添加一个符号。

为了向现有图表添加内容,最简单的做法是在其pretransitionrenderlet 事件上放置一个事件处理程序。一旦图表被渲染或重绘,pretransition 事件就会立即触发; renderlet 事件在其动画转换完成后触发。

使您的代码适应 D3v4/5 并将其粘贴在 pretransition 处理程序中可能如下所示:

yearRingChart.on('pretransition', chart => {
  let tri = chart.select('svg g') // 1
    .selectAll('path.triangle') // 2
    .data([0]); // 1
  tri = tri.enter()
    .append('path')
    .attr('class', 'triangle')
    .merge(tri);
  tri
    .attr("d", d3.symbol().type(d3.symbolTriangle).size(200))
    .style("fill", 'darkgreen'); // 5
})

一些注意事项:

  1. 使用chart.select 选择图表中的项目。和直接使用D3没什么区别,但是安全一点。我们在这里选择包含&lt;g&gt;,这是我们要添加三角形的地方。
  2. 无论三角形是否已经存在,都选择它。
  3. .data([0]) 是添加元素一次的技巧,仅当它不存在时 - 任何大小为 1 的数组都可以
  4. 如果没有三角形,添加一个并将其合并到选择中。现在tri 将只包含一个旧三角形或新三角形。
  5. 定义三角形的任何属性,这里使用d3.symbol 定义面积为200的三角形。

Example fiddle.

【讨论】:

  • 我正在发布仪表板的整个模型,包括我想要渲染的仪表板的星号,由基元组成。同时,感谢您提供的有益而全面的回复。我会奖励答案。随意评论与我将发布的问题图片相关的答案
  • 三角形是 12 点星形的基本构建块,内部有一个白色圆圈(文本内容)此星形与适合仪表板第一个网格的年轮图分开。跨度>
  • 实际上我想在一个网格中构建单独的图表,因为它们不仅仅是饼图和三角形,而是饼图和星形。
  • 我明白了 - 图片有助于解释您要做什么。看起来 12 点星基本上是静态的,但颜色会根据显示的数字而变化。很难说创建一个新的图表类是否更容易,或者就像我上面展示的那样,除了选择图表外部而不是内部的元素。我想选择将取决于您是否希望星星可重复使用。如果您希望数字从一个值“翻转”到另一个值,您可以使用 number display widget 来表示该部分。
  • 所有图表的颜色都是静态的,我只是选择了那些不同的色调进行区分。
【解决方案2】:

因为三角形不是bound to any data array,所以不应该调用.enter()

试试这个方法:

 $scope.openChart = d3.select("#risk-chart svg g")
        .attr("width", 55)
        .attr("height", 55)
        .append('path')
        .attr("d", d3.symbol('triangle-up'))
        .attr("transform", function(d) { return "translate(" + 100 + "," + 100 + ")"; })
        .style("fill", fill);

【讨论】:

  • 删除链式 enter() 函数产生了一个小故障(小形状出现然后消失)如何保持它可见?我应该对 dc.js 和 d3.js 中的所有形状进行分组吗?如果是,我该怎么做?
  • 我没有,我现在会,但不确定它的功能是什么?
  • 建议的应用产生TypeError: this.setAttribute is not a function 由 d3.js 报告,在我的 $scope.openChart 代码行的正上方和调用堆栈中的 angular.js 正上方
  • 移动 $scope.riskChart.render();在成功的 dc.js 图表功能之后和不成功的 d3.js 删除错误之前。但是仍然没有图表出现...dc.redrawAll('group'); 成功调用了不成功的 d3.js 函数以重绘所有内容。不清楚如何在 d3.js 上 render(),因为 render() 仅适用于 dc.js
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-24
  • 1970-01-01
  • 2015-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多