首页 > 解决方案 > d3fc:将不同的数据传递给渲染方法

问题描述

试图调整这个例子。略有不同:我有更多的 WebGL 数据,因此根本不想将它传递给 SVG 渲染器。SVG 渲染器应该只获得一个数据点,但是随着用户移动鼠标,这会不断变化。是否有可能有一个 switch 函数,它基本上可以作为一个连接点,并将两个完全不同的数组传递给同一个图上的每个svgPlotArea()数组webglPlotArea()

一个简化的原始片段一个绘图和两个渲染函数:

const rand = d3.randomInt(0, 100);

const data = d3.range(100).map(d => ({
  x: rand(),
  y: rand()
}));

data[50].hover = true;

let xScale = d3.scaleLinear()
  .domain([0, 100])
  .range([0, 100]);

let yScale = d3.scaleLinear()
  .domain([0, 100])
  .range([0, 100]);

let webglSeries = fc.seriesWebglPoint()
  .crossValue(d => d.x)
  .mainValue(d => d.y)
  .type(d3.symbolCircle)
  .defined(() => true)
  .size(() => 100)
  .equals((prevData) => prevData.length);

let svgSeries = fc.seriesSvgPoint()
  .crossValue(d => d.x)
  .mainValue(d => d.y)
  .size(() => 300)
  .type(d3.symbolStar)
  .defined((d) => d.hover);

let chart = fc.chartCartesian(xScale, yScale)
  .webglPlotArea(webglSeries)
  .svgPlotArea(svgSeries);


function render() {
  d3.select("div")
    .datum(data)
    .call(chart);
}

render();
div {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
}
<script src="https://unpkg.com/d3"></script>
<script src="https://unpkg.com/d3fc"></script>


<div>
</div>

一个肮脏的 hack 片段,其中有两个相互独立的图和单独的数据:

const rand = d3.randomInt(0, 100);

const big_data = d3.range(100).map(d => ({
  x: rand(),
  y: rand()
}));

const hover_data = [{
  x: 27,
  y: 11
}, ];

let xScale = d3.scaleLinear()
  .domain([0, 100])
  .range([0, 100]);

let yScale = d3.scaleLinear()
  .domain([0, 100])
  .range([0, 100]);

let webglSeries = fc.seriesWebglPoint()
  .crossValue(d => d.x)
  .mainValue(d => d.y)
  .type(d3.symbolCircle)
  .defined(() => true)
  .size(() => 100)
  .equals((prevData) => prevData.length);

let svgSeries = fc.seriesSvgPoint()
  .crossValue(d => d.x)
  .mainValue(d => d.y)
  .size(() => 300)
  .type(d3.symbolStar)
  .defined(() => true);

let glchart = fc.chartCartesian(xScale, yScale)
  .webglPlotArea(webglSeries);

let svgchart = fc.chartCartesian(xScale, yScale)
  .svgPlotArea(svgSeries);

function render() {
  d3.select("#gl")
    .datum(big_data)
    .call(glchart);

  d3.select("#svg")
    .datum(hover_data)
    .call(svgchart);
}

render();
div {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 100%;
  height: 100%;
}
<script src="https://unpkg.com/d3"></script>
<script src="https://unpkg.com/d3fc"></script>


<div>
  <div id="gl">
  </div>
  <div id="svg">
  </div>
</div>

有没有更好的方法,比如下面的伪代码?

const chart = d3fc.chartCartesian(xScale, yScale)
                  .svgPlotArea(svgSeries)
                  .webglPlotArea(webglSeries)

d3.select( "div" )
  .datum( function() { return whichRenderer ? data1 : data2 } )
  .call(chart);

标签: javascriptsvgd3.jswebgld3fc

解决方案


使用 fc.seriesSvgMulti() 似乎很有可能,请参阅代码片段。在控制台中,svgPlotArea的defined()函数只处理一个节点

let rand = d3.randomInt(0,100);

let data = d3.range(100).map(d => ({
    x: rand(),
    y: rand()
}));

let xScale = d3.scaleLinear()
               .domain([0, 100])
               .range([0, 100]);

let yScale = d3.scaleLinear()
               .domain([0, 100])
               .range([0, 100]);

let webglSeries = fc.seriesWebglPoint()
                 .crossValue(d => d.x)
                 .mainValue(d => d.y)
                 .type(d3.symbolCircle)
                 .defined( () => true )
                 .size( () => 100 )
                 .equals( (prevData) => prevData.length );

let svgSeries = fc.seriesSvgPoint()
                 .crossValue(d => d.x)
                 .mainValue(d => d.y)
                 .size( () => 300 )
                 .type(d3.symbolStar)
                 .defined( (d) => { console.log("node check"); return true } );

let multi = fc.seriesSvgMulti()
                .series([svgSeries])
                 .mapping((data, index, series) => {
                     switch (series[index]) {
                         case svgSeries:
                             return getSingleNode();
                     }
                 });

let chart = fc.chartCartesian(xScale, yScale)
    .webglPlotArea(webglSeries)
    .svgPlotArea(multi);

function getSingleNode() {
  return [data[rand()]]
}

function render() {
  d3.select( "div" )
    .datum( data )
    .call(chart);
}

render();
div {
  position: absolute;
  width: 100%;
  height: 70%;
}
<script src="https://unpkg.com/d3"></script>
<script src="https://unpkg.com/d3fc"></script>

<div>
</div>


推荐阅读