ZingChart繪製金融儀表板

DogLeftover發表於2024-05-23
  • 程式碼案例
<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <title>ZingChart Demo: Financial Widget Dashboard</title>
  <script nonce="undefined" src="./zingchart.min.js"></script>
  <style>
    .zc-body {
      background: #fff;
    }

    #myChart {
      margin: 10px 0 20px;
      opacity: 0;
      visibility: hidden;
      transition: opacity .3s;
    }

    #myChart.loaded {
      opacity: 1;
      visibility: visible;
    }

    .zc-demo {
      margin: 0 auto;
      width: 100%;
      max-width: 910px;
    }

    .zc-favorites {
      z-index: 100;
      position: absolute;
      top: 0;
      left: 0;
      box-shadow: 3px 3px 3px #333;
    }

    .zc-favorites-wrap {
      margin-top: 10px;
      margin: 0 auto;
      padding: 10px;
      min-height: 120px;
      background: #ebebeb;
      border: 0;
    }

    .zc-favorites-headline {
      font-size: 13px;
      display: block;
      margin-bottom: 7px;
    }

    .zc-favorites-db {
      display: grid;
      grid-template-columns: repeat(4, 1fr);
      grid-column-gap: 10px;
      grid-row-gap: 10px;
    }

    .zc-favorites-fb-db {
      float: left;
    }

    .zc-ref {
      display: none;
    }
  </style>
</head>

<body class="zc-body">

  <div class="zc-demo">

    <div id="myChart">
      <a href="https://www.zingchart.com/" rel="noopener" class="zc-ref">Powered by ZingChart</a>
    </div>

    <!-- <div class="zc-favorites-wrap">
      <strong class="zc-favorites-headline">Favorites (drag from above)</strong>
      <div id="db" class="zc-favorites-db"></div>
    </div> -->

  </div>

  <script>
    ZC.LICENSE = ["xxx", "xxx"]; // Define Module Location
    zingchart.MODULESDIR = 'https://cdn.zingchart.com/modules/';

    // DEFINE DATA
    // -----------------------------
    // Data config
    let chartData = {
      type: 'null',
      backgroundColor: '#ddd #eee',
      height: '100%',
      width: '100%',
      widgets: [{             // 設定小部件的樣式
          type: 'exchange',
          rate: 'EUR/USD',
          colors: [
            ['#55154D', '#4E0E46'], '#fff', '#ccc'
          ],
          refresh: 500,
          ticks: 100,
          width: 450,
          x: '10px',
          y: '10px',
        },
        {
          type: 'exchange',       // 定義資料部件,並設定樣式
          rate: 'USD/CAD',
          colors: [
            ['#56000E', '#5F0017'], '#fff', '#ccc'
          ],
          x: '470px',
          y: '10px',
        },
        {
          type: 'exchange',
          rate: 'USD/JPY',
          colors: [
            ['#014358', '#013D52'], '#fff', '#ccc'
          ],
          decimals: 2,
          height: 200,
          width: 200,
          x: '700px',
          y: '10px',
        },
        {
          type: 'exchange',
          rate: 'BTC/USD',
          colors: [
            ['#264031', '#243C2E'], '#fff', '#ccc'
          ],
          decimals: 2,
          refresh: 200,
          ticks: 60,
          x: '10px',
          y: '160px',
        },
        {
          type: 'exchange',
          rate: 'CRUDE OIL WTI',
          colors: [
            ['#264F14', '#244B13'], '#fff', '#ccc'
          ],
          decimals: 2,
          x: '240px',
          y: '160px',
        },
        {
          type: 'exchange',
          rate: 'GOLD',
          colors: [
            ['#704F00', '#6B4A00'], '#fff', '#ccc'
          ],
          decimals: 2,
          height: 260,
          refresh: 2000,
          x: '470px',
          y: '160px',
        },
        {
          type: 'exchange',
          rate: 'GBP/USD',
          colors: [
            ['#262400', '#242200'], '#fff', '#ccc'
          ],
          height: 110,
          x: '10px',
          y: '310px',
        },
        {
          type: 'exchange',
          rate: 'NZD/USD',
          colors: [
            ['#260031', '#24002E'], '#fff', '#ccc'
          ],
          height: 110,
          x: '240px',
          y: '310px',
        },
        {
          type: 'exchange',
          rate: 'USD/CHF',
          colors: [
            ['#363636', '#333333'], '#fff', '#ccc'
          ],
          height: 200,
          width: 200,
          x: '700px',
          y: '220px',
        },
      ],
    };

    // 包含用於渲染圖表的資料
    let chartDataFB = {
      backgroundColor: '#ddd #eee',
      type: 'null',
      widgets: [],
    };
    let SEQ = 0;

    // Main chart render location
    let chartId = 'myChart';

    // Favorites
    let fbId = 'fb';

    // INIT
    // -----------------------------
    // Append Amazon Script
    let aws = document.createElement('script');
    aws.src = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/374756/widgets.js';
    document.body.appendChild(aws);
    aws.addEventListener('load', init);

    //  模擬獲取外部資料,並返回一個 JSON 物件
    // Constantly fetch new data sets
    window.fetchData = function(rate, callback) {
      let oRefValues = {
        'EUR/USD': 1.1143,
        'USD/JPY': 120.88,
        'USD/CAD': 1.2219,
        'BTC/USD': 232.71,
        'CRUDE OIL WTI': 58.59,
        GOLD: 1208.21,
        'GBP/USD': 1.552,
        'NZD/USD': 0.7368,
        'USD/CHF': 0.9364,
      };
      let fRefValue = oRefValues[rate],
        fDiff = fRefValue / 100;
      oRefValues[rate] = fRefValue + (-fDiff / 2 + fDiff * Math.random());
      let json = {
        rate: rate,
        ts: 100 * Math.round(new Date().getTime() / 100),
        value: oRefValues[rate],
      };
      callback.call(window, JSON.stringify(json));
    };

    // 初始化
    // LOAD EVENTS
    // -----------------------------
    // Run these after AWS script is init
    function init() {
      // Render the main demo
      zingchart.render({
        id: chartId,
        width: '100%',
        height: 430,
        output: 'svg',
        strictmode: true,
        data: chartData,        // 上面的小部件配置
        events: {
          load: loaded,
        },
      });

      // Bind 'mousedown' action when you click/drag a chart
      zingchart.bind(chartId, 'mousedown', md);
    }

    // CHART RENDERED
    // -----------------------------
    // Set CSS class to show chart after render
    function loaded() {
      let chart = document.querySelector('#' + chartId);
      chart.classList.add('loaded');
    }

    // 判斷滑鼠事件是否是滑鼠左鍵的點選事件
    // DEFINE 'MOUSE DOWN' FUNCTION
    // -----------------------------
    function md(p) {
      // Early Exit: Element is not a button
      if (p.ev.button !== 0) return;
      // Add data
      let wdata = getData(p, chartData);
      // Early Exit: No data found
      if (!wdata) return;

      // Define data for 2nd location
      chartDataFB.widgets = [wdata];
      p.ev.preventDefault();

      // Add data to Favorites
      let appendData =
        '<div id="fb" class="zc-favorites" style="width:' +
        wdata.width +
        'px;height:' +
        wdata.height +
        'px;"></div>';
      document.body.insertAdjacentHTML('beforeend', appendData);

      // 定時任務
      setTimeout(function() {
        // Otherwise, create mouse functions and apply to the chart
        // ---
        // Get the Favorites DOM element
        let fb = document.querySelector('#' + fbId);
        // Early Exit: Not found
        if (!fb) return;

        // Position element
        fb.style.top = p.ev.clientY - wdata.height / 2 + 'px';
        fb.style.left = p.ev.clientX - wdata.width / 2 + 'px';

        // Bind mouse movements
        document.addEventListener('mousemove', mouseMove);
        document.addEventListener('mouseup', mouseUp);

        // Render 2nd chart in 'Favorites' DOM element
        zingchart.render({
          id: fbId,
          width: wdata.width,
          height: wdata.height,
          output: 'svg',
          strictmode: true,
          data: chartDataFB,
        });
      }, 0);

      // MOUSE FNS

      // Mousemove
      function mouseMove(ev) {      // 滑鼠移動時呼叫
        ev.preventDefault();
        let fb = document.querySelector('#' + fbId);
        let doc = document.documentElement;
        let body = document.body;
        let offsetTop = doc.scrollTop ? doc.scrollTop : document.body.scrollTop;
        fb.style.top = ev.clientY - wdata.height / 2 + offsetTop + 'px';
        fb.style.left = ev.clientX - wdata.width / 2 + 'px';
      }

      // Mouseup
      function mouseUp(ev) {      // 滑鼠釋放時呼叫
        let fb = document.querySelector('#' + fbId);
        if (fb) {
          let db = document.querySelector('#db');
          let dbData = '<div id="fb' + SEQ + '" class="zc-favorites-fb-db"></div>';
          db.insertAdjacentHTML('beforeend', dbData);
          zingchart.render({
            id: fbId + SEQ,
            width: wdata.width,
            height: wdata.height,
            output: 'svg',
            strictmode: true,
            data: chartDataFB,
          });
          SEQ++;
          fb.remove();
          zingchart.exec(fbId, 'destroy');
        }
        document.removeEventListener('mousemove', mouseMove);
        document.removeEventListener('mouseup', mouseUp);
      }
    }

    // DEFINE 'GET DATA' FUNCTION
    // -----------------------------
    // Get the data from the clicked item
    function getData(p, data) {       // 傳入引數,提取小部件的資料
      if (!data) return;
      let wdata;
      for (let w = 0; w < data.widgets.length; w++) {
        let rate = data.widgets[w].rate;
        let id = p.id + '-graph-' + p.id + rate.replace(/[^a-zA-Z0-9]/g, '');
        if (id === p.graphid) {
          wdata = data.widgets[w];
          wdata.x = 0;
          wdata.y = 0;
          wdata.width = 220;
          wdata.height = 100;
        }
      }
      return wdata;
    }
  </script>
</body>

</html>
  • 效果圖

相關文章