Drupal中的Echarts绘图展示

Drupal中的Echarts绘图展示

5月 08, 2019     liumwei

Drupal中有Echarts、D3等可视化模块。这为数据的展示提供了绝好的工具。例如,通过Echarts模块,可简单地编写模块文件,进行数据展示。而D3模块更是将其与Views模块进行了较好地关联。

如果它们能和views_datasource、views_data_export_json、xml_views等模块结合,还能实现数据动态展示。不过,这两个模块目前仅仅还只能展示简单地可视化,更多的数据展示功能,还需要进一步编写模板文件。其实,在Baidu Echarts官网上,有不少示例性的可视化绘图结果,而且可以结合在线编辑工具,进行探索性展示。具体可见https://echarts.baidu.com/examples/editor.html

下面是Jungle提供的一个展示办法。鸣谢Jungle提供代码编写与具体代码解释

基本思路是:根据Drupal7模块规范,编写展示模块(echarts_graph)。模块提供一个可访问的数据展示页面地址;页面基于Drupal7模板规范,可复用主题效果;引入Echarts绘图相关js文件;添加绘图相关js代码以实现利用Echarts js文件进行绘图。

1.Drupal7 模块定义文件info:  echarts_graph.info

name = Echarts Graph
description = Echarts Graph
core = 7.x

2. Drupal7 模块定义文件module: echarts_graph.module

<?php

/**
 * Implements hook_menu().
 */

function echarts_graph_menu() {
  $items['echarts_graph'] = array(  //定义页面路径
    'title' => '', //no title
    'page callback' => 'echarts_graph_page', //页面请求函数
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );
  return $items;
}


function echarts_graph_page() { //页面请求功能函数构建
  return "Ok";  //页面请求成功,返回ok。该返回ok内容,可替换为后面模板文件page--echarts_graph.tpl.php代码显示出相应内容。
}


/**
 * Implements hook_theme_registry_alter().
 */
function echarts_graph_theme_registry_alter(&$theme_registry) {  //基于Drupal主题函数,登记echarts_graph模块其提供模板。也就是,该模板能为Drupal7主题识别。
  $extension   = '.tpl.php'; //模板文件命名后缀通配形式
  $module_path = drupal_get_path('module', 'echarts_graph');
  $files       = file_scan_directory($module_path . '/templates', '/' . preg_quote($extension) . '$/');//模板文件路径

  foreach ($files as $file) { //模板文件读取
    $template = drupal_basename($file->filename, $extension);
    $theme  = str_replace('-', '_', $template); //模板文件命名前缀形式*--*_*
    list($base_theme, $specific) = explode('__', $theme, 2);

    // Don't override base theme.
    if (!empty($specific) && isset($theme_registry[$base_theme])) { //登记模板*--*_*
      $theme_info = array(
        'template'   => $template,
        'path'       => drupal_dirname($file->uri),
        'base hook'  => $base_theme,
        'type'       => 'module',
        'theme path' => $module_path,
      );

      if (isset($theme_registry[$base_theme]['variables'])) {
        $theme_info['variables'] = $theme_registry[$base_theme]['variables'];
      }

      $theme_registry[$theme] = $theme_info;
    }
  }
}

3. 模板文件代码(根据上面定义,模板位于模块文件夹templates之下。根据定义,模板必须至少具有两个文件 html--*_*.tpl.php和page--*_*.tpl.php):

3.1  html--*_*.tpl.php代码

<?php

/**
 * @file
 * Default theme implementation to display the basic html structure of a single
 * Drupal page.
 *
 * Variables:
 * - $css: An array of CSS files for the current page.
 * - $language: (object) The language the site is being displayed in.
 *   $language->language contains its textual representation.
 *   $language->dir contains the language direction. It will either be 'ltr' or 'rtl'.
 * - $rdf_namespaces: All the RDF namespace prefixes used in the HTML document.
 * - $grddl_profile: A GRDDL profile allowing agents to extract the RDF data.
 * - $head_title: A modified version of the page title, for use in the TITLE
 *   tag.
 * - $head_title_array: (array) An associative array containing the string parts
 *   that were used to generate the $head_title variable, already prepared to be
 *   output as TITLE tag. The key/value pairs may contain one or more of the
 *   following, depending on conditions:
 *   - title: The title of the current page, if any.
 *   - name: The name of the site.
 *   - slogan: The slogan of the site, if any, and if there is no title.
 * - $head: Markup for the HEAD section (including meta tags, keyword tags, and
 *   so on).
 * - $styles: Style tags necessary to import all CSS files for the page.
 * - $scripts: Script tags necessary to load the JavaScript files and settings
 *   for the page.
 * - $page_top: Initial markup from any modules that have altered the
 *   page. This variable should always be output first, before all other dynamic
 *   content.
 * - $page: The rendered page content.
 * - $page_bottom: Final closing markup from any modules that have altered the
 *   page. This variable should always be output last, after all other dynamic
 *   content.
 * - $classes String of classes that can be used to style contextually through
 *   CSS.
 *
 * @see template_preprocess()
 * @see template_preprocess_html()
 * @see template_process()
 *
 * @ingroup themeable
 */
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
  "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php print $language->language; ?>" version="XHTML+RDFa 1.0" dir="<?php print $language->dir; ?>"<?php print $rdf_namespaces; ?>>

<head profile="<?php print $grddl_profile; ?>">
  <?php print $head; ?>
  <title><?php print $head_title; ?></title>
  <?php print $styles; ?>
  <?php print $scripts; ?>
<!--引入echarts相应的js文件-->
  <script src="https://cdn.bootcss.com/echarts/4.2.1-rc1/echarts.min.js"></script>
  <script src="https://cdn.bootcss.com/echarts/4.2.1-rc1/extension/dataTool.min.js"></script>
</head>
<body class="<?php print $classes; ?>" <?php print $attributes;?>>
  <div id="skip-link">
    <a href="#main-content" class="element-invisible element-focusable"><?php print t('Skip to main content'); ?></a>
  </div>
  <?php print $page_top; ?>
<!--页面显示-->
  <?php print $page; ?>

  <?php print $page_bottom; ?>
</body>
</html>

3.2 page--echarts_graph.tpl代码

<?php

/**
 * @file
 * Bartik's theme implementation to display a single Drupal page.
 *
 * The doctype, html, head and body tags are not in this template. Instead they
 * can be found in the html.tpl.php template normally located in the
 * modules/system directory.
 *
 * Available variables:
 *
 * General utility variables:
 * - $base_path: The base URL path of the Drupal installation. At the very
 *   least, this will always default to /.
 * - $directory: The directory the template is located in, e.g. modules/system
 *   or themes/bartik.
 * - $is_front: TRUE if the current page is the front page.
 * - $logged_in: TRUE if the user is registered and signed in.
 * - $is_admin: TRUE if the user has permission to access administration pages.
 *
 * Site identity:
 * - $front_page: The URL of the front page. Use this instead of $base_path,
 *   when linking to the front page. This includes the language domain or
 *   prefix.
 * - $logo: The path to the logo image, as defined in theme configuration.
 * - $site_name: The name of the site, empty when display has been disabled
 *   in theme settings.
 * - $site_slogan: The slogan of the site, empty when display has been disabled
 *   in theme settings.
 * - $hide_site_name: TRUE if the site name has been toggled off on the theme
 *   settings page. If hidden, the "element-invisible" class is added to make
 *   the site name visually hidden, but still accessible.
 * - $hide_site_slogan: TRUE if the site slogan has been toggled off on the
 *   theme settings page. If hidden, the "element-invisible" class is added to
 *   make the site slogan visually hidden, but still accessible.
 *
 * Navigation:
 * - $main_menu (array): An array containing the Main menu links for the
 *   site, if they have been configured.
 * - $secondary_menu (array): An array containing the Secondary menu links for
 *   the site, if they have been configured.
 * - $breadcrumb: The breadcrumb trail for the current page.
 *
 * Page content (in order of occurrence in the default page.tpl.php):
 * - $title_prefix (array): An array containing additional output populated by
 *   modules, intended to be displayed in front of the main title tag that
 *   appears in the template.
 * - $title: The page title, for use in the actual HTML content.
 * - $title_suffix (array): An array containing additional output populated by
 *   modules, intended to be displayed after the main title tag that appears in
 *   the template.
 * - $messages: HTML for status and error messages. Should be displayed
 *   prominently.
 * - $tabs (array): Tabs linking to any sub-pages beneath the current page
 *   (e.g., the view and edit tabs when displaying a node).
 * - $action_links (array): Actions local to the page, such as 'Add menu' on the
 *   menu administration interface.
 * - $feed_icons: A string of all feed icons for the current page.
 * - $node: The node object, if there is an automatically-loaded node
 *   associated with the page, and the node ID is the second argument
 *   in the page's path (e.g. node/12345 and node/12345/revisions, but not
 *   comment/reply/12345).
 *
 * Regions:
 * - $page['header']: Items for the header region.
 * - $page['featured']: Items for the featured region.
 * - $page['highlighted']: Items for the highlighted content region.
 * - $page['help']: Dynamic help text, mostly for admin pages.
 * - $page['content']: The main content of the current page.
 * - $page['sidebar_first']: Items for the first sidebar.
 * - $page['triptych_first']: Items for the first triptych.
 * - $page['triptych_middle']: Items for the middle triptych.
 * - $page['triptych_last']: Items for the last triptych.
 * - $page['footer_firstcolumn']: Items for the first footer column.
 * - $page['footer_secondcolumn']: Items for the second footer column.
 * - $page['footer_thirdcolumn']: Items for the third footer column.
 * - $page['footer_fourthcolumn']: Items for the fourth footer column.
 * - $page['footer']: Items for the footer region.
 *
 * @see template_preprocess()
 * @see template_preprocess_page()
 * @see template_process()
 * @see bartik_process_page()
 * @see html.tpl.php
 */
?>
<div id="page-wrapper"><div id="page">

  <div id="header" class="<?php print $secondary_menu ? 'with-secondary-menu': 'without-secondary-menu'; ?>"><div class="section clearfix">

    <?php if ($logo): ?>
      <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home" id="logo">
        <img src="<?php print $logo; ?>" alt="<?php print t('Home'); ?>" />
      </a>
    <?php endif; ?>

    <?php if ($site_name || $site_slogan): ?>
      <div id="name-and-slogan"<?php if ($hide_site_name && $hide_site_slogan) { print ' class="element-invisible"'; } ?>>

        <?php if ($site_name): ?>
          <?php if ($title): ?>
            <div id="site-name"<?php if ($hide_site_name) { print ' class="element-invisible"'; } ?>>
              <strong>
                <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home"><span><?php print $site_name; ?></span></a>
              </strong>
            </div>
          <?php else: /* Use h1 when the content title is empty */ ?>
            <h1 id="site-name"<?php if ($hide_site_name) { print ' class="element-invisible"'; } ?>>
              <a href="<?php print $front_page; ?>" title="<?php print t('Home'); ?>" rel="home"><span><?php print $site_name; ?></span></a>
            </h1>
          <?php endif; ?>
        <?php endif; ?>

        <?php if ($site_slogan): ?>
          <div id="site-slogan"<?php if ($hide_site_slogan) { print ' class="element-invisible"'; } ?>>
            <?php print $site_slogan; ?>
          </div>
        <?php endif; ?>

      </div> <!-- /#name-and-slogan -->
    <?php endif; ?>

    <?php print render($page['header']); ?>

    <?php if ($main_menu): ?>
      <div id="main-menu" class="navigation">
        <?php print theme('links__system_main_menu', array(
          'links' => $main_menu,
          'attributes' => array(
            'id' => 'main-menu-links',
            'class' => array('links', 'clearfix'),
          ),
          'heading' => array(
            'text' => t('Main menu'),
            'level' => 'h2',
            'class' => array('element-invisible'),
          ),
        )); ?>
      </div> <!-- /#main-menu -->
    <?php endif; ?>

    <?php if ($secondary_menu): ?>
      <div id="secondary-menu" class="navigation">
        <?php print theme('links__system_secondary_menu', array(
          'links' => $secondary_menu,
          'attributes' => array(
            'id' => 'secondary-menu-links',
            'class' => array('links', 'inline', 'clearfix'),
          ),
          'heading' => array(
            'text' => t('Secondary menu'),
            'level' => 'h2',
            'class' => array('element-invisible'),
          ),
        )); ?>
      </div> <!-- /#secondary-menu -->
    <?php endif; ?>

  </div></div> <!-- /.section, /#header -->

  <?php if ($messages): ?>
    <div id="messages"><div class="section clearfix">
      <?php print $messages; ?>
    </div></div> <!-- /.section, /#messages -->
  <?php endif; ?>

  <?php if ($page['featured']): ?>
    <div id="featured"><div class="section clearfix">
      <?php print render($page['featured']); ?>
    </div></div> <!-- /.section, /#featured -->
  <?php endif; ?>

  <div id="main-wrapper" class="clearfix"><div id="main" class="clearfix">

    <?php if ($breadcrumb): ?>
      <div id="breadcrumb"><?php print $breadcrumb; ?></div>
    <?php endif; ?>

    <?php if ($page['sidebar_first']): ?>
      <div id="sidebar-first" class="column sidebar"><div class="section">
        <?php print render($page['sidebar_first']); ?>
      </div></div> <!-- /.section, /#sidebar-first -->
    <?php endif; ?>

    <div id="content" class="column"><div class="section">
      <?php if ($page['highlighted']): ?><div id="highlighted"><?php print render($page['highlighted']); ?></div><?php endif; ?>
      <a id="main-content"></a>
      <?php print render($title_prefix); ?>
      <?php if ($title): ?>
        <h1 class="title" id="page-title">
          <?php print $title; ?>
        </h1>
      <?php endif; ?>
      <?php print render($title_suffix); ?>
      <?php if ($tabs): ?>
        <div class="tabs">
          <?php print render($tabs); ?>
        </div>
      <?php endif; ?>
      <?php print render($page['help']); ?>
      <?php if ($action_links): ?>
        <ul class="action-links">
          <?php print render($action_links); ?>
        </ul>
      <?php endif; ?>

      <!-- <?php print render($page['content']); ?> 更换为如下的定制内容,从而替换掉上面 echarts_graph.module显示ok的字样-->
      
<!--引入Chrod绘图相应的js代码-->
        <div id="echarts_chord" style="width: 600px;height:400px;"></div>  <!-- 定义一个标签echarts_chord,其结果通过下面的js来实现-->

        <script type="text/javascript">
          (function ($) { // 构建以使jquery $可用 
            var myChart = echarts.init(document.getElementById('echarts_chord'));<!--与上面的echarts_chord标签id相同。-->
            myChart.showLoading(); <!-- echarts相应的js代码-->
            $.get('http://tripal3.liumwei.org/sites/default/files/chord.gexf', function (xml) {
              myChart.hideLoading();

              var graph = echarts.dataTool.gexf.parse(xml);
              var categories = [];
              for (var i = 0; i < 9; i++) {
                categories[i] = {
                  name: '' + i
                };
              }
              graph.nodes.forEach(function (node) {
                node.itemStyle = null;
                node.value = node.symbolSize;
                node.symbolSize /= 1.5;
                node.label = {
                  normal: {
                    show: node.symbolSize > 10
                  }
                };
                node.category = node.attributes.modularity_class;
              });
              option = {
                title: {
                  text: 'Chord',
                  subtext: 'Circular layout',
                  top: 'bottom',
                  left: 'right'
                },
                tooltip: {},
                legend: [{
                  // selectedMode: 'single',
                  data: categories.map(function (a) {
                    return a.name;
                  })
                }],
                animationDurationUpdate: 1500,
                animationEasingUpdate: 'quinticInOut',
                series : [
                  {
                    name: 'RNA',
                    type: 'graph',
                    layout: 'circular',
                    circular: {
                      rotateLabel: true
                    },
                    data: graph.nodes,
                    links: graph.links,
                    categories: categories,
                    roam: true,
                    label: {
                      normal: {
                        position: 'right',
                        formatter: '{b}'
                      }
                    },
                    lineStyle: {
                      normal: {
                        color: 'source',
                        curveness: 0.3
                      }
                    }
                  }
                ]
              };

              myChart.setOption(option);
            }, 'xml');

          }(jQuery));//


        </script>


        <?php print $feed_icons; ?>

    </div></div> <!-- /.section, /#content -->

    <?php if ($page['sidebar_second']): ?>
      <div id="sidebar-second" class="column sidebar"><div class="section">
        <?php print render($page['sidebar_second']); ?>
      </div></div> <!-- /.section, /#sidebar-second -->
    <?php endif; ?>

  </div></div> <!-- /#main, /#main-wrapper -->

  <?php if ($page['triptych_first'] || $page['triptych_middle'] || $page['triptych_last']): ?>
    <div id="triptych-wrapper"><div id="triptych" class="clearfix">
      <?php print render($page['triptych_first']); ?>
      <?php print render($page['triptych_middle']); ?>
      <?php print render($page['triptych_last']); ?>
    </div></div> <!-- /#triptych, /#triptych-wrapper -->
  <?php endif; ?>

  <div id="footer-wrapper"><div class="section">

    <?php if ($page['footer_firstcolumn'] || $page['footer_secondcolumn'] || $page['footer_thirdcolumn'] || $page['footer_fourthcolumn']): ?>
      <div id="footer-columns" class="clearfix">
        <?php print render($page['footer_firstcolumn']); ?>
        <?php print render($page['footer_secondcolumn']); ?>
        <?php print render($page['footer_thirdcolumn']); ?>
        <?php print render($page['footer_fourthcolumn']); ?>
      </div> <!-- /#footer-columns -->
    <?php endif; ?>

    <?php if ($page['footer']): ?>
      <div id="footer" class="clearfix">
        <?php print render($page['footer']); ?>
      </div> <!-- /#footer -->
    <?php endif; ?>

  </div></div> <!-- /.section, /#footer-wrapper -->

</div></div> <!-- /#page, /#page-wrapper -->

将上面的代码放入模块echarts_graph中,见下面的压缩包。下载解压放入Drupal7文件夹sites/all/module下,然后启用模块。再浏览器中键入http://ip/echart_graph就可看到结果。

 

附件echarts_graph.zip (5.97 KB)