【问题标题】:Cocktail recipe Data Visualisation鸡尾酒配方数据可视化
【发布时间】:2016-07-22 23:42:33
【问题描述】:

一般对数据可视化感兴趣并且越来越熟悉Javascripts D3库,我发现了不同鸡尾酒配方的可视化:Information is beautiful - Cocktails

我想知道这是怎么做到的?有没有机会用 D3js 完成这项工作,或者这样的事情基本上是一项高度手动的任务?

要可视化鸡尾酒中成分的相对数量,可以使用堆栈布局。然而,我不知道如何处理不同形状的鸡尾酒杯。

【问题讨论】:

    标签: javascript d3.js visualization data-visualization


    【解决方案1】:

    在 D3 中做这样的事情就像用智能手机敲钉板一样 - 最终你会完成工作,但你选择了错误的工具来做这件事。

    与智能手机一样,D3 有很多可能性,但这项任务需要很多视觉细节,而 D3 无法完成。

    您知道,图形编辑器工具的存在是有原因的 - 它们使您能够创建具有出色字体、颜色、图层等的合成图像。鸡尾酒信息图非常适合此类任务 - 您可以轻松地在画布上快速添加小薄荷叶、桃子苦味剂和黑莓。

    另一方面,甚至可以在图形编辑器中制作简单的条形图。我已经这样做了(不要问我为什么),我必须做一些数学才能画出正确比例的条形。

    您需要完成的每种工作都有相应的工具。重要的是要知道如何选择合适的。 D3 代表数据驱动文档 - 这说明了一切。只要你有 DATA,就选择 D3。

    您可以看出,鸡尾酒信息图表中有数据。确实。但我想告诉你一个简单但非常重要的数据可视化概念:信噪比(查看解释该概念的 this 文章),它在某种程度上类似于衡量噪声多少的质量指标在您的数据中(不要将设计与噪声混淆)。在回答这个问题时,我想出了 signal-to-design ratio©。 (我没有任何研究支持这一点,所以请耐心等待),它告诉您除了数据之外还需要多少设计。在鸡尾酒信息图中,您的设计远多于数据 - 因此 D3 不适合此任务。

    结论:每项任务都最适合特定的工具,旨在完成它。学会为您的任务选择合适的工具 - 这至少可以节省您的时间。

    【讨论】:

    • 我们将您的“信号设计比”称为数据墨水比,这是 Tufte 的概念:infovis-wiki.net/index.php/Data-Ink_Ratio
    • 我认为 Tufte 的数据墨水比是“信噪比”而不是信噪比。在他的书“定量信息的视觉显示”中,他谈到了显示大量数据的图表和其他视觉效果。在二维平面中,他设法显示数据的几个特征。我对“信号与设计”比率的观点是,一些视觉效果的数据较少,但如果你只显示这些数据(每种成分的百分比),它的效果就不会像那些花哨的眼镜和镜头一样.
    • 您好,iulian,非常感谢您的回答。我认为你的回答是绝对正确的。 D3 可能不是用于此目的的理想工具。尤其是涉及到一些小细节,比如水果块等等。因此,我对 Marks 的回答感到非常惊讶,这确实超出了我对 D3 的预期。再次,非常感谢。
    【解决方案2】:

    那么,让我们在d3 中讨论这是否是一个好主意(其中的乐趣在哪里?)并讨论如何d3 中执行此操作。下面的代码借用了这个SVG image,然后应用渐变填充来显示鸡尾酒的各个部分。最后,你用一些标签把它包起来……

    <!DOCTYPE html>
    <html>
    
    <head>
      <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
      <style>
        svg{
          font: 12px sans-serif;
        }
      </style>
    </head>
    
    <body>
      <script>
      
        // our cocktail glass
        var glassPath = "m 60,350 c -4.74218,-0.7989 -7.33654,-2.5714 -7.33654,-5.0124 0,-2.4848 2.03654,-4.0776 5.21357,-4.0776 1.54746,0 3.59496,-0.4138 4.55,-0.9197 1.97894,-1.0481 9.10335,-3.4326 24.23643,-8.1118 5.775,-1.7856 11.4,-3.6018 12.5,-4.0358 1.1,-0.434 4.3253,-1.3074 7.16733,-1.9408 5.71266,-1.2732 7.4813,-2.8015 9.21631,-7.9635 0.64176,-1.9094 2.38458,-4.7427 3.87294,-6.2962 l 2.70609,-2.8245 -0.2841,-27.7039 c -0.15625,-15.2371 -0.68535,-33.7788 -1.17577,-41.2038 -0.49042,-7.425 -1.20657,-21.825 -1.59145,-32 -0.94914,-25.0923 -1.70127,-27.1843 -15.45994,-43 -3.11003,-3.575 -7.5473,-9.326 -9.8606,-12.7799 -4.25363,-6.3511 -14.06748,-25.7631 -14.0826,-27.8558 -0.005,-0.6246 -0.68044,-2.4246 -1.50205,-4 -0.82161,-1.57534 -1.49661,-3.90636 -1.5,-5.18002 -0.003,-1.27366 -0.46743,-3.17763 -1.0312,-4.23105 -0.56377,-1.05341 -1.45572,-4.96133 -1.98212,-8.68426 -0.88933,-6.28986 -2.39223,-14.81377 -3.51606,-19.94188 -0.65359,-2.98237 -5.07693,-8.04956 -9.42012,-10.7913 -3.31741,-2.09419 -6.56863,-3.11638 -17.55666,-5.51985 -13.14833,-2.87601 -26.01544,-13.25971 -31.54627,-25.45769 -3.44329,-7.59403 -6.63083,-22.12177 -6.86935,-31.30823 l -0.0844,-3.25 131,0 131,0 -0.0844,3.25 c -0.23852,9.18646 -3.42606,23.7142 -6.86935,31.30823 -5.53083,12.19798 -18.39794,22.58168 -31.54627,25.45769 -10.98803,2.40347 -14.23925,3.42566 -17.55666,5.51985 -4.34319,2.74174 -8.76653,7.80893 -9.42012,10.7913 -1.12383,5.12811 -2.62673,13.65202 -3.51606,19.94188 -0.5264,3.72293 -1.41835,7.63085 -1.98212,8.68426 -0.56377,1.05342 -1.02781,2.95739 -1.0312,4.23105 -0.003,1.27366 -0.67839,3.60468 -1.5,5.18002 -0.82161,1.5754 -1.49753,3.3754 -1.50205,4 -0.0151,2.0927 -9.82897,21.5047 -14.0826,27.8558 -2.3133,3.4539 -6.75057,9.2049 -9.8606,12.7799 -13.75867,15.8157 -14.5108,17.9077 -15.45994,43 -0.38488,10.175 -1.10103,24.575 -1.59145,32 -0.49042,7.425 -1.01952,25.9667 -1.17577,41.2038 l -0.2841,27.7039 2.70609,2.8245 c 1.48836,1.5535 3.23118,4.3868 3.87294,6.2962 1.73501,5.162 3.50365,6.6903 9.21631,7.9635 2.84203,0.6334 6.06733,1.5068 7.16733,1.9408 1.1,0.434 6.725,2.2502 12.5,4.0358 15.13308,4.6792 22.25749,7.0637 24.23643,8.1118 0.95504,0.5059 3.00254,0.9197 4.55,0.9197 5.51258,0 7.05386,4.7477 2.50848,7.727 -2.52335,1.6539 -7.71319,1.7828 -77.25,1.9187 -40.9997,0.08 -76.41846,-0.17 -78.70837,-0.5557 z"
        
        // some drinks to show
        var data = [
          {
            drink: "Angel Face",
            parts: [
              { 
                unit: 3,
                name: "Calvados"
              },{ 
                unit: 3,
                name: "Apricot Brandy"
              },{ 
                unit: 3,
                name: "Gin"
              }
            ]
          }, {
            drink: "Aviation",
            parts: [
              { 
                unit: 1.5,
                name: "Maraschino"
              },{ 
                unit: 1.5,
                name: "Lemon Juice"
              },{ 
                unit: 4.5,
                name: "Gin"
              }
            ]
          }
        ];
        
        // 47 percent of our glass is where the liquid is
        var colorPercent = 47,
          // 3 percent is the empty spot on top
          // 50 percent is the stem
          startPercent = 50 - colorPercent,
          // width and height of the glass
          drinkWidth = 265,
          drinkHeight = 350,
          colors = d3.scale.category10();
    
        // calculate percentages...
        data.forEach(function(d0){
          var totPercent = startPercent,
              total = d3.sum(d0.parts, function(d1){ return d1.unit; });
          d0.gradient = [];
          d0.parts.forEach(function(d1){
            d1.startPercent = totPercent;
            d0.gradient.push({
              percent: totPercent,
              color: colors(d1.name)
            });
            totPercent += ((d1.unit / total) * colorPercent);
            d1.endPercent = totPercent;
            d0.gradient.push({
              percent: totPercent,
              color: colors(d1.name)
            });
          });
        });
        
        var svg = d3.select('body')
          .append('svg')
          .attr('width', (drinkWidth * data.length) + 5)
          .attr('height', drinkHeight + 20);
          
    
        // a g for each glass;
        var glass = svg.selectAll('.drink')
          .data(data)
          .enter()
          .append('g')
          .attr('class', 'drink')
          .attr('transform', function(d,i){
            return 'translate(' + (drinkWidth * i) + ',0)';
          })
        
        // the glass
        glass
          .append('path')
          .attr('d', glassPath)
          .style('stroke', 'black')
          .style('fill', function(d,i){
            return 'url(#grad' + i + ')';
          });
          
        // text labels of drink
        glass
          .append("text")
          .attr("x", drinkWidth / 2)
          .attr("y", drinkHeight)
          .text(function(d){
            return d.drink;
          })
          .attr("dy", "1em")
          .style("text-anchor", "middle")
          .style("font-size", "16");
          
        // text labels of drink parts
        glass.selectAll('.label')
          .data(function(d){
            return d.parts;
          })
          .enter()
          .append('text')
          .attr('class', 'label')
          .text(function(d){
            return d.unit + " " + d.name;
          })
          .style("fill", "black")
          .attr("x", drinkWidth / 2)
          .attr("y", function(d){
            return (((d.startPercent + d.endPercent) / 2) / 100) * drinkHeight;
          })
          .attr("dy", "1em")
          .style("text-anchor", "middle");
          
        // our gradients
        var grad = svg.append('defs')
          .selectAll('linearGradient')
          .data(data)
          .enter()
          .append('linearGradient')
          .attr('id', function(d,i){
            return "grad" + i;
          })
          .attr('x1', '0%')
          .attr('x2', '0%')
          .attr('y1', '0%')
          .attr('y2', '100%');
          
        // no liquid top of glass
        grad.append("stop")
          .attr("offset", "0%")
          .style("stop-color", "white");
          
        grad.append("stop")
          .attr("offset", startPercent + "%")
          .style("stop-color", "white");
        
        var e = grad.selectAll('.color')
          .data(function(d){
            return d.gradient
          })
          .enter();
    
        e.append("stop")
          .attr('id', function(d,i){
            return 'stop' + 1;
          })
          .attr("offset", function(d){
            return d.percent + '%';
          })
          .style("stop-color", function(d){
            return d.color;
          });
    
        // stem of glass
        grad.append("stop")
          .attr("offset", "50%")
          .style("stop-color", "black");
        
        grad.append("stop")
          .attr("offset", "100%")
          .style("stop-color", "black");
        
      </script>
    </body>
    
    </html>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-09
      • 1970-01-01
      • 2018-10-18
      • 1970-01-01
      • 1970-01-01
      • 2017-01-20
      • 2021-08-09
      相关资源
      最近更新 更多