将链接插入到Google Charts API数据中?

12

我一直在Google图表游乐场里尝试着使用Google图表,这是游乐场的链接:

链接

我一直在使用以下代码:

function drawVisualization() {
  // Create and populate the data table.
  var data = google.visualization.arrayToDataTable([
    ['Year', 'Austria'],
    ['2003',  1336060],
    ['2004',  1538156],
    ['2005',  1576579],
    ['2006',  1600652],
    ['2007',  1968113],
    ['2008',  1901067]
  ]);

  // Create and draw the visualization.
  new google.visualization.BarChart(document.getElementById('visualization')).
      draw(data,
           {title:"Yearly Coffee Consumption by Country",
            width:600, height:400,
            vAxis: {title: "Year"},
            hAxis: {title: "Cups"}}
      );
}

这给了我一个漂亮的图表,如下所示:

enter image description here

我想让这个图表适合我的网站需求,为此,我需要将左侧柱形图名称转换为链接到另一页的链接。例如,2003年将是用户可以单击的链接,以及2004年等等。

我尝试过类似以下的内容:

function drawVisualization() {
  // Create and populate the data table.
  var data = google.visualization.arrayToDataTable([
    ['Year', 'Austria'],
    ['<a href="url">Link text</a>',  1336060],
    ['2004',  1538156],
    ['2005',  1576579],
    ['2006',  1600652],
    ['2007',  1968113],
    ['2008',  1901067]
  ]);

  // Create and draw the visualization.
  new google.visualization.BarChart(document.getElementById('visualization')).
      draw(data,
           {title:"Yearly Coffee Consumption by Country",
            width:600, height:400,
            vAxis: {title: "Year"},
            hAxis: {title: "Cups"}}
      );
}

但我只能希望它是那么容易,但事实并非如此。有人知道这是否有可能吗?

6个回答

15

Manzoid的回答不错,但是它仅显示一个警报框而不是跟随链接,仍需一些组装。以下是更完整的答案,但它使栏可点击而不是标签。我创建了一个数据表,其中包含链接,然后从中创建了一个数据视图以选择要显示的列。然后当发生选择事件时,我只需从原始数据表中检索链接。

<html>
  <head>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load("visualization", "1", {packages:["corechart"]});
      google.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = google.visualization.arrayToDataTable([
          ['Year', 'link', 'Austria'],
          ['2003', 'http://en.wikipedia.org/wiki/2003',  1336060],
          ['2004', 'http://en.wikipedia.org/wiki/2004', 1538156],
          ['2005', 'http://en.wikipedia.org/wiki/2005', 1576579],
          ['2006', 'http://en.wikipedia.org/wiki/2006', 1600652],
          ['2007', 'http://en.wikipedia.org/wiki/2007', 1968113],
          ['2008', 'http://en.wikipedia.org/wiki/2008', 1901067]             
        ]);
       var view = new google.visualization.DataView(data);
       view.setColumns([0, 2]);

       var options = {title:"Yearly Coffee Consumption by Country",
            width:600, height:400,
            vAxis: {title: "Year"},
            hAxis: {title: "Cups"}};

       var chart = new google.visualization.BarChart( 
           document.getElementById('chart_div'));
       chart.draw(view, options);

       var selectHandler = function(e) {
          window.location = data.getValue(chart.getSelection()[0]['row'], 1 );
       }

       google.visualization.events.addListener(chart, 'select', selectHandler);
      }
    </script>
  </head>
  <body>
    <div id="chart_div" style="width: 900px; height: 900px;"></div>
  </body>
</html>

9
这很不容易,因为你看到的输出是SVG而不是HTML。在你的示例中,那些标签(“2004”,“2005”等)嵌入在SVG文本节点内,因此插入原始HTML标记将不会呈现为HTML。
解决方法是扫描包含目标值(再次,“2004”,“2005”等)的文本节点,并用{{link1:ForeignObject}}元素替换它们。 ForeignObject元素可以包含常规HTML。然后需要将它们定位在原始SVG文本节点所在的位置附近。
这里有一个示例代码片段,说明了所有这些。它针对你的特定示例进行了调整,因此当你切换到渲染真实数据时,你需要相应地修改和概括这个代码片段。
// Note: You will probably need to tweak these deltas
// for your labels to position nicely.
var xDelta = 35;
var yDelta = 13;
var years = ['2003','2004','2005','2006','2007','2008'];
$('text').each(function(i, el) {
  if (years.indexOf(el.textContent) != -1) {
    var g = el.parentNode;
    var x = el.getAttribute('x');
    var y = el.getAttribute('y');
    var width = el.getAttribute('width') || 50;
    var height = el.getAttribute('height') || 15;

    // A "ForeignObject" tag is how you can inject HTML into an SVG document.
    var fo = document.createElementNS("http://www.w3.org/2000/svg", "foreignObject")
    fo.setAttribute('x', x - xDelta);
    fo.setAttribute('y', y - yDelta);
    fo.setAttribute('height', height);
    fo.setAttribute('width', width);
    var body = document.createElementNS("http://www.w3.org/1999/xhtml", "BODY");
    var a = document.createElement("A");
    a.href = "http://yahoo.com";
    a.setAttribute("style", "color:blue;");
    a.innerHTML = el.textContent;
    body.appendChild(a);
    fo.appendChild(body);

    // Remove the original SVG text and replace it with the HTML.
    g.removeChild(el);
    g.appendChild(fo);
  }
});

小提示,这里使用了一点jQuery方便起见,但您可以将 $('text') 替换为 document.getElementsByTagName("svg")[0].getElementsByTagName("text")


2
有没有一些图表API可以让我更轻松地实现这个? - Mike
完美的解决方案!谢谢。 - rsc
完美。我需要在vaxis标题中添加链接。谢谢。 - aris

6

由于嵌入SVG的路线(可以理解为)过于复杂,您不想涉及其中,因此让我们尝试完全不同的方法。 假设您有一些灵活性来稍微更改功能规范,使得单击的是条形图,而不是标签,那么这是一种更简单的解决方案。

在此片段中查找alert,这是您将自定义以执行重定向的部分。

function drawVisualization() {
  // Create and populate the data table.
  var rawData = [
    ['Year', 'Austria'],
    ['2003',  1336060],
    ['2004',  1538156],
    ['2005',  1576579],
    ['2006',  1600652],
    ['2007',  1968113],
    ['2008',  1901067]
  ];
  var data = google.visualization.arrayToDataTable(rawData);

  // Create and draw the visualization.
  var chart = new google.visualization.BarChart(document.getElementById('visualization'));
  chart.draw(data,
           {title:"Yearly Coffee Consumption by Country",
            width:600, height:400,
            vAxis: {title: "Year"},
            hAxis: {title: "Cups"}}
      );
  var handler = function(e) {
    var sel = chart.getSelection();
    sel = sel[0];
    if (sel && sel['row'] && sel['column']) {
      var year = rawData[sel['row'] + 1][0];
      alert(year); // This where you'd construct the URL for this row, and redirect to it.
    }
  }
  google.visualization.events.addListener(chart, 'select', handler);
}

1

这里有另一种解决方案,它会将每个文本标签与锚点标签包装在一起。

  • 没有ForeignObject
  • 可点击的标签
  • 可以通过CSS进行样式设计(悬停效果)

这是一个示例:https://jsfiddle.net/tokkonoPapa/h3eq9m9p/

/* find the value in array */
function inArray(val, arr) {
    var i, n = arr.length;
    val = val.replace('…', ''); // remove ellipsis
    for (i = 0; i < n; ++i) {
        if (i in arr && 0 === arr[i].label.indexOf(val)) {
            return i;
        }
    }
    return -1;
}

/* add a link to each label */
function addLink(data, id) {
    var n, p, info = [], ns = 'hxxp://www.w3.org/1999/xlink';

    // make an array for label and link.
    n = data.getNumberOfRows();
    for (i = 0; i < n; ++i) {
        info.push({
            label: data.getValue(i, 0),
            link:  data.getValue(i, 2)
        });
    }

    $('#' + id).find('text').each(function(i, elm) {
        p = elm.parentNode;
        if ('g' === p.tagName.toLowerCase()) {
            i = inArray(elm.textContent, info);
            if (-1 !== i) {
                /* wrap text tag with anchor tag */
                n = document.createElementNS('hxxp://www.w3.org/2000/svg', 'a');
                n.setAttributeNS(ns, 'xlink:href', info[i].link);
                n.setAttributeNS(ns, 'title', info[i].label);
                n.setAttribute('target', '_blank');
                n.setAttribute('class', 'city-name');
                n.appendChild(p.removeChild(elm));
                p.appendChild(n);
                info.splice(i, 1); // for speeding up
            }
        }
    });
}

function drawBasic() {
    var data = google.visualization.arrayToDataTable([
        ['City', '2010 Population', {role: 'link'}],
        ['New York City, NY', 8175000, 'hxxp://google.com/'],
        ['Los Angeles, CA',   3792000, 'hxxp://yahoo.com/' ],
        ['Chicago, IL',       2695000, 'hxxp://bing.com/'  ],
        ['Houston, TX',       2099000, 'hxxp://example.com'],
        ['Philadelphia, PA',  1526000, 'hxxp://example.com']
    ]);

    var options = {...};
    var chart = new google.visualization.BarChart(
        document.getElementById('chart_div')
    );

    chart.draw(data, options);

    addLink(data, 'chart_div');
}

1
我显然没有足够的声望点数直接评论前面的回复,所以我很抱歉作为一个新帖子来评论。manzoid的建议非常好,但我发现了一个问题,看起来Mark Butler可能遇到了同样的问题(或者无意中绕过了它)。
if (sel && sel['row'] && sel['column']) {

这行代码会导致第一个数据点无法被点击。我在一个1月到12月的柱状图上使用了它,只有2月到12月可以被点击。如果从条件语句中移除sel['row'],那么1月份就可以正常工作了。虽然我不确定if()条件语句是否真的必要。


0

你应该使用格式化程序

如果你用HTML替换值,那么排序将无法正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接