整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Chart.js:適用于現(xiàn)代 Web 的簡(jiǎn)單而靈活的 JavaScript 圖表庫(kù)

          挑戰(zhàn)30天在頭條寫(xiě)日記#

          功能:

          顏色插件

          Chart.js 品牌顏色的默認(rèn)調(diào)色板可作為內(nèi)置的省時(shí)零配置插件使用。

          Tree-shaking

          通過(guò)僅注冊(cè)必要的組件,JavaScript 包的大小可以減少數(shù)十千字節(jié)。

          規(guī)模堆疊

          布局框可以按組堆疊和加權(quán)。

          字幕插件

          輔助標(biāo)題插件,具有與主標(biāo)題相同的所有選項(xiàng)。

          線段樣式

          線段可以根據(jù)任何用戶定義的標(biāo)準(zhǔn)設(shè)置樣式。

          3.0新功能高級(jí)動(dòng)畫(huà)

          每個(gè)元素中每個(gè)屬性的轉(zhuǎn)換都可以單獨(dú)且獨(dú)立地配置。

          新功能表現(xiàn)!

          引入了許多性能增強(qiáng)功能。此示例具有 1M (2x500k) 點(diǎn),啟用了新的抽取插件。

          2.0新功能混合圖表類型

          混合搭配條形圖和折線圖,以在數(shù)據(jù)集之間提供清晰的視覺(jué)區(qū)分。

          2.0新功能新的圖表軸類型

          輕松繪制日期時(shí)間、對(duì)數(shù)甚至完全自定義比例的復(fù)雜、稀疏數(shù)據(jù)集。

          2.0新功能動(dòng)畫(huà)一切!

          更改數(shù)據(jù)、更新顏色和添加數(shù)據(jù)集時(shí),開(kāi)箱即用的令人驚嘆的過(guò)渡。

          使用Demo-創(chuàng)建圖表

          在此示例中,我們?yōu)閱蝹€(gè)數(shù)據(jù)集創(chuàng)建條形圖并將其呈現(xiàn)在 HTML 頁(yè)面上。將此代碼片段添加到您的頁(yè)面:

          <div>
            <canvas id="myChart"></canvas>
          </div>
          
          <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
          
          <script>
            const ctx = document.getElementById('myChart');
          
            new Chart(ctx, {
              type: 'bar',
              data: {
                labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
                datasets: [{
                  label: '# of Votes',
                  data: [12, 19, 3, 5, 2, 3],
                  borderWidth: 1
                }]
              },
              options: {
                scales: {
                  y: {
                    beginAtZero: true
                  }
                }
              }
            });
          </script>
          


          你應(yīng)該得到一個(gè)像這樣的圖表:

          讓我們分解一下這段代碼。

          首先,我們的頁(yè)面中需要有一個(gè)畫(huà)布。建議為圖表提供自己的容器以提高響應(yīng)能力。

          <div>
            <canvas id="myChart"></canvas>
          </div>

          現(xiàn)在我們有了畫(huà)布,我們可以包含來(lái)自 CDN 的 Chart.js。

          <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

          最后,我們可以創(chuàng)建一個(gè)圖表。我們添加一個(gè)腳本,該腳本獲取myChart畫(huà)布元素并new Chart使用所需的配置進(jìn)行實(shí)例化:bar圖表類型、標(biāo)簽、數(shù)據(jù)點(diǎn)和選項(xiàng)。

          <script>
            const ctx = document.getElementById('myChart');
          
            new Chart(ctx, {
              type: 'bar',
              data: {
                labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
                datasets: [{
                  label: '# of Votes',
                  data: [12, 19, 3, 5, 2, 3],
                  borderWidth: 1
                }]
              },
              options: {
                scales: {
                  y: {
                    beginAtZero: true
                  }
                }
              }
            });
          </script>

          Chart.js 的所有主要概念:

          圖表類型和元素、數(shù)據(jù)集、自定義、插件、組件和 tree-shaking。不要猶豫,點(diǎn)擊文本中的鏈接。

          我們將從頭開(kāi)始使用幾個(gè)圖表構(gòu)建 Chart.js 數(shù)據(jù)可視化:

          使用 Chart.js 構(gòu)建新應(yīng)用程序

          在新文件夾中,創(chuàng)建package.json包含以下內(nèi)容的文件:

          {
            "name": "chartjs-example",
            "version": "1.0.0",
            "license": "MIT",
            "scripts": {
              "dev": "parcel src/index.html",
              "build": "parcel build src/index.html"
            },
            "devDependencies": {
              "parcel": "^2.6.2"
            },
            "dependencies": {
              "@cubejs-client/core": "^0.31.0",
              "chart.js": "^4.0.0"
            }
          }
          

          現(xiàn)代前端應(yīng)用程序經(jīng)常使用 JavaScript 模塊捆綁器,因此我們選擇Parcel 作為一個(gè)很好的零配置構(gòu)建工具。我們還安裝了 Chart.js v4 和Cube 的 JavaScript 客戶端,這是一個(gè)用于數(shù)據(jù)應(yīng)用程序的開(kāi)源 API,我們將使用它來(lái)獲取真實(shí)世界的數(shù)據(jù)(稍后會(huì)詳細(xì)介紹)。

          運(yùn)行npm installyarn install、 或pnpm install安裝依賴項(xiàng),然后創(chuàng)建src文件夾。在該文件夾中,我們需要一個(gè)非常簡(jiǎn)單的index.html文件:

          <!doctype html>
          <html lang="en">
            <head>
              <title>Chart.js example</title>
            </head>
            <body>
              <!-- <div style="width: 500px;"><canvas id="dimensions"></canvas></div><br/> -->
              <div style="width: 800px;"><canvas id="acquisitions"></canvas></div>
          
              <!-- <script type="module" src="dimensions.js"></script> -->
              <script type="module" src="acquisitions.js"></script>
            </body>
          </html>
          

          正如您所看到的,Chart.js 需要最少的標(biāo)記:canvas帶有 的標(biāo)記id,我們稍后將通過(guò)它引用圖表。默認(rèn)情況下,Chart.js 圖表是響應(yīng)式的,并占據(jù)整個(gè)封閉容器。所以,我們?cè)O(shè)置寬度div來(lái)控制圖表的寬度。

          最后,讓我們創(chuàng)建src/acquisitions.js包含以下內(nèi)容的文件:

          import Chart from 'chart.js/auto'
          
          (async function() {
            const data = [
              { year: 2010, count: 10 },
              { year: 2011, count: 20 },
              { year: 2012, count: 15 },
              { year: 2013, count: 25 },
              { year: 2014, count: 22 },
              { year: 2015, count: 30 },
              { year: 2016, count: 28 },
            ];
          
            new Chart(
              document.getElementById('acquisitions'),
              {
                type: 'bar',
                data: {
                  labels: data.map(row => row.year),
                  datasets: [
                    {
                      label: 'Acquisitions by year',
                      data: data.map(row => row.count)
                    }
                  ]
                }
              }
            );
          })();
          

          讓我們看一下這段代碼:

          • 我們Chart從特殊路徑導(dǎo)入 Chart.js 主類chart.js/auto。它加載所有可用的 Chart.js 組件(這非常方便),但不允許進(jìn)行樹(shù)搖動(dòng)。我們稍后會(huì)解決這個(gè)問(wèn)題。
          • 我們實(shí)例化一個(gè)新Chart實(shí)例并提供兩個(gè)參數(shù):將呈現(xiàn)圖表的畫(huà)布元素和選項(xiàng)對(duì)象。
          • 我們只需要提供一個(gè)圖表類型 ( bar) 并提供data它由labels(通常是數(shù)據(jù)點(diǎn)的數(shù)字或文本描述)和一個(gè)數(shù)組datasets(Chart.js 支持大多數(shù)圖表類型的多個(gè)數(shù)據(jù)集)組成。每個(gè)數(shù)據(jù)集都用 a 指定,label并包含一個(gè)數(shù)據(jù)點(diǎn)數(shù)組。
          • 目前,我們只有一些虛擬數(shù)據(jù)條目。因此,我們提取yearcount屬性來(lái)生成labels唯一數(shù)據(jù)集中的 和 數(shù)據(jù)點(diǎn)數(shù)組。

          是時(shí)候使用npm run devyarn dev、 或運(yùn)行示例并在 Web 瀏覽器中pnpm dev導(dǎo)航到localhost:1234 了:

          只需幾行代碼,我們就得到了一個(gè)具有很多功能的圖表:圖例、網(wǎng)格線、刻度線和懸停時(shí)顯示的工具提示。刷新網(wǎng)頁(yè)幾次即可看到圖表也是動(dòng)畫(huà)的。嘗試單擊“按年份獲取”標(biāo)簽,您會(huì)發(fā)現(xiàn)您還可以切換數(shù)據(jù)集可見(jiàn)性(當(dāng)您有多個(gè)數(shù)據(jù)集時(shí)特別有用)。

          簡(jiǎn)單的定制

          讓我們看看如何自定義 Chart.js 圖表。首先,讓我們關(guān)閉動(dòng)畫(huà),以便立即顯示圖表。其次,讓我們隱藏圖例和工具提示,因?yàn)槲覀冎挥幸粋€(gè)數(shù)據(jù)集和相當(dāng)瑣碎的數(shù)據(jù)。

          將調(diào)用new Chart(...);替換src/acquisitions.js為以下代碼片段:

            new Chart(
              document.getElementById('acquisitions'),
              {
                type: 'bar',
                options: {
                  animation: false,
                  plugins: {
                    legend: {
                      display: false
                    },
                    tooltip: {
                      enabled: false
                    }
                  }
                },
                data: {
                  labels: data.map(row => row.year),
                  datasets: [
                    {
                      label: 'Acquisitions by year',
                      data: data.map(row => row.count)
                    }
                  ]
                }
              }
            );
          

          正如您所看到的,我們已將該options屬性添加到第二個(gè)參數(shù)中,這樣您就可以為 Chart.js 指定各種自定義選項(xiàng)。通過(guò)提供的布爾標(biāo)志禁用動(dòng)畫(huà)animation。大多數(shù)圖表范圍的選項(xiàng)(例如,響應(yīng)能力或設(shè)備像素比)都是這樣配置的。

          圖例和工具提示隱藏在plugins. 請(qǐng)注意,Chart.js 的一些功能被提取到插件中:獨(dú)立的、獨(dú)立的代碼片段。其中一些插件作為Chart.js 發(fā)行版 的一部分提供,其他插件是獨(dú)立維護(hù)的,并且可以位于很棒的 插件、框架集成和其他圖表類型列表中。

          您應(yīng)該能夠在瀏覽器中看到更新后的簡(jiǎn)約圖表。

          真實(shí)世界數(shù)據(jù)

          對(duì)于硬編碼、有限大小、不切實(shí)際的數(shù)據(jù),很難展示 Chart.js 的全部潛力。讓我們快速連接到數(shù)據(jù) API,以使我們的示例應(yīng)用程序更接近生產(chǎn)用例。

          讓我們創(chuàng)建src/api.js包含以下內(nèi)容的文件:

          import { CubejsApi } from '@cubejs-client/core';
          
          const apiUrl = 'https://heavy-lansford.gcp-us-central1.cubecloudapp.dev/cubejs-api/v1';
          const cubeToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjEwMDAwMDAwMDAsImV4cCI6NTAwMDAwMDAwMH0.OHZOpOBVKr-sCwn8sbZ5UFsqI3uCs6e4omT7P6WVMFw';
          
          const cubeApi = new CubejsApi(cubeToken, { apiUrl });
          
          export async function getAquisitionsByYear() {
            const acquisitionsByYearQuery = {
              dimensions: [
                'Artworks.yearAcquired',
              ],
              measures: [
                'Artworks.count'
              ],
              filters: [ {
                member: 'Artworks.yearAcquired',
                operator: 'set'
              } ],
              order: {
                'Artworks.yearAcquired': 'asc'
              }
            };
          
            const resultSet = await cubeApi.load(acquisitionsByYearQuery);
          
            return resultSet.tablePivot().map(row => ({
              year: parseInt(row['Artworks.yearAcquired']),
              count: parseInt(row['Artworks.count'])
            }));
          }
          
          export async function getDimensions() {
            const dimensionsQuery = {
              dimensions: [
                'Artworks.widthCm',
                'Artworks.heightCm'
              ],
              measures: [
                'Artworks.count'
              ],
              filters: [
                {
                  member: 'Artworks.classification',
                  operator: 'equals',
                  values: [ 'Painting' ]
                },
                {
                  member: 'Artworks.widthCm',
                  operator: 'set'
                },
                {
                  member: 'Artworks.widthCm',
                  operator: 'lt',
                  values: [ '500' ]
                },
                {
                  member: 'Artworks.heightCm',
                  operator: 'set'
                },
                {
                  member: 'Artworks.heightCm',
                  operator: 'lt',
                  values: [ '500' ]
                }
              ]
            };
          
            const resultSet = await cubeApi.load(dimensionsQuery);
          
            return resultSet.tablePivot().map(row => ({
              width: parseInt(row['Artworks.widthCm']),
              height: parseInt(row['Artworks.heightCm']),
              count: parseInt(row['Artworks.count'])
            }));
          }

          讓我們看看那里發(fā)生了什么:

          • 我們?yōu)镃ubeimport (數(shù)據(jù)應(yīng)用程序的開(kāi)源 API)提供 JavaScript 客戶端庫(kù),使用 API URL ( ) 和身份驗(yàn)證令牌 ( ) 配置它,最后實(shí)例化客戶端 ( )。 apiUrlcubeTokencubeApi
          • Cube API 托管在Cube Cloud 中,并連接到一個(gè)數(shù)據(jù)庫(kù),該數(shù)據(jù)庫(kù)包含 約 140,000 條記錄的公共數(shù)據(jù)集 ,代表美國(guó)紐約現(xiàn)代藝術(shù)博物館 收藏的所有藝術(shù)品。當(dāng)然,這是一個(gè)比我們現(xiàn)在擁有的更真實(shí)的數(shù)據(jù)集。
          • 我們定義了幾個(gè)異步函數(shù)來(lái)從 API 獲取數(shù)據(jù):getAquisitionsByYeargetDimensions。第一個(gè)返回按購(gòu)買年份計(jì)算的藝術(shù)品數(shù)量,另一個(gè)返回每個(gè)寬度-高度對(duì)的藝術(shù)品數(shù)量(我們將在另一個(gè)圖表中需要它)。
          • 我們來(lái)看一下getAquisitionsByYear。首先,我們?cè)谧兞恐袆?chuàng)建一個(gè)基于 JSON 的聲明性查詢acquisitionsByYearQuery。正如您所看到的,我們指定了每件yearAcquired我們想要獲得count的藝術(shù)品;yearAcquired必須設(shè)置(即不是未定義);結(jié)果集將按yearAcquired升序排序。
          • 其次,我們resultSet通過(guò)調(diào)用獲取并將其映射到具有所需屬性cubeApi.load的對(duì)象數(shù)組。yearcount

          現(xiàn)在,讓我們將真實(shí)世界的數(shù)據(jù)傳遞到我們的圖表中。請(qǐng)進(jìn)行一些更改src/acquisitions.js:添加導(dǎo)入并替換data變量的定義。

          import { getAquisitionsByYear } from './api'
          
          // ...
          
          const data = await getAquisitionsByYear();

          完畢!現(xiàn)在,我們的真實(shí)數(shù)據(jù)圖表如下所示。看來(lái)1964年、1968年和2008年發(fā)生了一些有趣的事情!

          我們已經(jīng)完成了條形圖。讓我們嘗試另一種 Chart.js 圖表類型。

          進(jìn)一步定制

          Chart.js 支持許多常見(jiàn)的圖表類型。

          例如,氣泡圖允許同時(shí)顯示三個(gè)維度的數(shù)據(jù):xy軸上的位置代表兩個(gè)維度,第三個(gè)維度由單個(gè)氣泡的大小表示。

          要?jiǎng)?chuàng)建圖表,請(qǐng)停止已運(yùn)行的應(yīng)用程序,然后轉(zhuǎn)到src/index.html并取消注釋以下兩行:

          <div style="width: 500px;"><canvas id="dimensions"></canvas></div><br/>
          
          <script type="module" src="dimensions.js"></script>
          

          然后,創(chuàng)建src/dimensions.js包含以下內(nèi)容的文件:

          import Chart from 'chart.js/auto'
          import { getDimensions } from './api'
          
          (async function() {
            const data = await getDimensions();
          
            new Chart(
              document.getElementById('dimensions'),
              {
                type: 'bubble',
                data: {
                  labels: data.map(x => x.year),
                  datasets: [
                    {
                      label: 'Dimensions',
                      data: data.map(row => ({
                        x: row.width,
                        y: row.height,
                        r: row.count
                      }))
                    }
                  ]
                }
              }
            );
          })();
          

          也許,一切都非常簡(jiǎn)單:我們從 API 獲取數(shù)據(jù)并渲染一個(gè)具有該類型的新圖表,將三個(gè)維度的數(shù)據(jù)作為、和(半徑)屬性bubble傳遞。xyr

          現(xiàn)在,使用 、 或 重置緩存并再次啟動(dòng)rm -rf .parcel-cache應(yīng)用程序。我們現(xiàn)在可以查看新圖表:npm run devyarn devpnpm dev

          嗯,看起來(lái)不太漂亮。

          首先,圖表不是正方形的。藝術(shù)品的寬度和高度同樣重要,因此我們希望圖表的寬度也等于其高度。默認(rèn)情況下,Chart.js 圖表的縱橫比為 1(對(duì)于所有徑向圖表,例如圓環(huán)圖)或 2(對(duì)于所有其他圖表)。讓我們修改圖表的縱橫比:

          // ...
          
          	new Chart(
              document.getElementById('dimensions'),
              {
                type: 'bubble',
                options: {
                  aspectRatio: 1,
                },
          
          // ...
          

          現(xiàn)在看起來(lái)好多了:

          然而,這仍然不理想。水平軸的范圍從 0 到 500,垂直軸的范圍從 0 到 450。默認(rèn)情況下,Chart.js 會(huì)自動(dòng)將軸的范圍(最小值和最大值)調(diào)整為數(shù)據(jù)集中提供的值,因此圖表“適合“你的數(shù)據(jù)。顯然,MoMa 收藏中沒(méi)有高度在 450 至 500 厘米范圍內(nèi)的藝術(shù)品。讓我們修改圖表的軸配置來(lái)解決這個(gè)問(wèn)題:

          // ...
          
            new Chart(
              document.getElementById('dimensions'),
              {
                type: 'bubble',
                options: {
                  aspectRatio: 1,
                  scales: {
                    x: {
                      max: 500
                    },
                    y: {
                      max: 500
                    }
                  }
                },
          
          // ...
          

          偉大的!看一下更新后的圖表:

          然而,還有一個(gè)問(wèn)題:這些數(shù)字是多少?單位是厘米不是很明顯。讓我們對(duì)兩個(gè)軸應(yīng)用自定義刻度格式以使事情變得清晰。我們將提供一個(gè)回調(diào)函數(shù),調(diào)用該函數(shù)來(lái)格式化每個(gè)刻度值。這是更新后的軸配置:

          // ...
          
            new Chart(
              document.getElementById('dimensions'),
              {
                type: 'bubble',
                options: {
                  aspectRatio: 1,
                  scales: {
                    x: {
                      max: 500,
                      ticks: {
                        callback: value => `${value / 100} m`
                      }
                    },
                    y: {
                      max: 500,
                      ticks: {
                        callback: value => `${value / 100} m`
                      }
                    }
                  }
                },
          
          // ...
          

          完美,現(xiàn)在我們?cè)趦蓚€(gè)軸上都有合適的單位:

          多個(gè)數(shù)據(jù)集

          Chart.js 獨(dú)立繪制每個(gè)數(shù)據(jù)集,并允許對(duì)它們應(yīng)用自定義樣式。

          看一下圖表:有一條可見(jiàn)的氣泡“線”,其等號(hào)xy坐標(biāo)代表方形藝術(shù)品。將這些氣泡放入自己的數(shù)據(jù)集中并以不同的方式繪制它們會(huì)很酷。此外,我們可以將“較高”的藝術(shù)品與“較寬”的藝術(shù)品分開(kāi),并以不同的方式繪制它們。

          我們可以這樣做。將其替換datasets為以下代碼:

          // ...
          
                  datasets: [
                    {
                      label: 'width = height',
                      data: data
                        .filter(row => row.width === row.height)
                        .map(row => ({
                          x: row.width,
                          y: row.height,
                          r: row.count
                        }))
                    },
                    {
                      label: 'width > height',
                      data: data
                        .filter(row => row.width > row.height)
                        .map(row => ({
                          x: row.width,
                          y: row.height,
                          r: row.count
                        }))
                    },
                    {
                      label: 'width < height',
                      data: data
                        .filter(row => row.width < row.height)
                        .map(row => ({
                          x: row.width,
                          y: row.height,
                          r: row.count
                        }))
                    }
                  ]
          
          // ..
          

          如您所見(jiàn),我們定義了三個(gè)具有不同標(biāo)簽的數(shù)據(jù)集。每個(gè)數(shù)據(jù)集都有自己的使用 提取的數(shù)據(jù)片段filter。現(xiàn)在,它們?cè)谝曈X(jué)上是不同的,而且正如您所知,您可以獨(dú)立切換它們的可見(jiàn)性。

          這里我們依賴默認(rèn)的調(diào)色板。但是,請(qǐng)記住,每種圖表類型都支持許多數(shù)據(jù)集選項(xiàng),您可以隨意自定義。

          插件

          另一種非常強(qiáng)大的自定義 Chart.js 圖表的方法是使用插件。您可以在插件目錄 中找到一些或創(chuàng)建您自己的臨時(shí)插件。在 Chart.js 生態(tài)系統(tǒng)中,這是慣用的,并且期望通過(guò)插件來(lái)微調(diào)圖表。例如,您可以自定義畫(huà)布背景或使用簡(jiǎn)單的臨時(shí)插件為其添加邊框。讓我們嘗試一下后者。

          插件具有廣泛的 API,但簡(jiǎn)而言之,插件被定義為name具有擴(kuò)展點(diǎn)中定義的一個(gè)或多個(gè)回調(diào)函數(shù)的對(duì)象。new Chart(...);在調(diào)用之前插入以下代碼片段來(lái)代替src/dimensions.js

          // ...
          
            const chartAreaBorder = {
              id: 'chartAreaBorder',
          
              beforeDraw(chart, args, options) {
                const { ctx, chartArea: { left, top, width, height } } = chart;
          
                ctx.save();
                ctx.strokeStyle = options.borderColor;
                ctx.lineWidth = options.borderWidth;
                ctx.setLineDash(options.borderDash || []);
                ctx.lineDashOffset = options.borderDashOffset;
                ctx.strokeRect(left, top, width, height);
                ctx.restore();
              }
            };
          
            new Chart(
              document.getElementById('dimensions'),
              {
                type: 'bubble',
                plugins: [ chartAreaBorder ],
                options: {
                  plugins: {
                    chartAreaBorder: {
                      borderColor: 'red',
                      borderWidth: 2,
                      borderDash: [ 5, 5 ],
                      borderDashOffset: 2,
                    }
                  },
                  aspectRatio: 1,
          
          // ...
          

          正如您所看到的,在這個(gè)chartAreaBorder插件中,我們獲取畫(huà)布上下文,保存其當(dāng)前狀態(tài),應(yīng)用樣式,在圖表區(qū)域周圍繪制矩形,然后恢復(fù)畫(huà)布狀態(tài)。我們還傳遞了該插件,plugins因此它僅適用于這個(gè)特定的圖表。我們還將插件選項(xiàng)傳遞給options.plugins.chartAreaBorder; 我們當(dāng)然可以在插件源代碼中對(duì)它們進(jìn)行硬編碼,但這種方式可重用性更高。

          我們的氣泡圖現(xiàn)在看起來(lái)更漂亮了:

          搖樹(shù)

          在生產(chǎn)中,我們努力交付盡可能少的代碼,以便最終用戶可以更快地加載我們的數(shù)據(jù)應(yīng)用程序并獲得更好的體驗(yàn)。為此,我們需要應(yīng)用tree-shaking ,這是一個(gè)奇特的術(shù)語(yǔ),用于從 JavaScript 包中刪除未使用的代碼。

          Chart.js 的組件設(shè)計(jì)完全支持 tree-shaking。您可以一次注冊(cè)所有 Chart.js 組件(這在您進(jìn)行原型設(shè)計(jì)時(shí)很方便)并將它們與您的應(yīng)用程序捆綁在一起。或者,您可以僅注冊(cè)必要的組件并獲得最小的捆綁包,其大小要小得多。

          讓我們檢查一下我們的示例應(yīng)用程序。捆綁包尺寸是多少?您可以停止應(yīng)用程序并運(yùn)行npm run build, 或yarn build, 或pnpm build。片刻之后,您將得到如下信息:

          % yarn build
          yarn run v1.22.17
          $ parcel build src/index.html
          ? Built in 88ms
          
          dist/index.html              381 B   164ms
          dist/index.74a47636.js   265.48 KB   1.25s
          dist/index.ba0c2e17.js       881 B    63ms
          ? Done in 0.51s.
          

          我們可以看到 Chart.js 和其他依賴項(xiàng)被捆綁在一個(gè) 265 KB 文件中。

          src/acquisitions.js為了減小包的大小,我們需要對(duì)和進(jìn)行一些更改src/dimensions.js。首先,我們需要從兩個(gè)文件中刪除以下導(dǎo)入語(yǔ)句:import Chart from 'chart.js/auto'.

          相反,我們只加載必要的組件并使用 Chart.js“注冊(cè)”它們Chart.register(...)。這是我們需要的src/acquisitions.js

          import {
            Chart,
            Colors,
            BarController,
            CategoryScale,
            LinearScale,
            BarElement,
            Legend
          } from 'chart.js'
          
          Chart.register(
            Colors,
            BarController,
            BarElement,
            CategoryScale,
            LinearScale,
            Legend
          );
          

          這是以下代碼片段src/dimensions.js

          import {
            Chart,
            Colors,
            BubbleController,
            CategoryScale,
            LinearScale,
            PointElement,
            Legend
          } from 'chart.js'
          
          Chart.register(
            Colors,
            BubbleController,
            PointElement,
            CategoryScale,
            LinearScale,
            Legend
          );
          

          您可以看到,除了Chart類之外,我們還加載圖表類型、比例和其他圖表元素(例如,條形圖或點(diǎn))的控制器。您可以在文檔中查找所有可用的組件。

          或者,您可以按照控制臺(tái)中的 Chart.js 建議進(jìn)行操作。例如,如果您忘記導(dǎo)入BarController條形圖,您將在瀏覽器控制臺(tái)中看到以下消息:

          Unhandled Promise Rejection: Error: "bar" is not a registered controller.

          chart.js/auto請(qǐng)記住在準(zhǔn)備生產(chǎn)應(yīng)用程序時(shí)仔細(xì)檢查進(jìn)口。只需要一次這樣的導(dǎo)入就可以有效地禁用樹(shù)搖動(dòng)。

          現(xiàn)在,讓我們?cè)俅螜z查我們的應(yīng)用程序。運(yùn)行yarn build你會(huì)得到這樣的結(jié)果:

          % yarn build
          yarn run v1.22.17
          $ parcel build src/index.html
          ? Built in 88ms
          
          dist/index.html              381 B   176ms
          dist/index.5888047.js    208.66 KB   1.23s
          dist/index.dcb2e865.js       932 B    58ms
          ? Done in 0.51s.
          

          過(guò)僅導(dǎo)入和注冊(cè)選定的組件,我們刪除了超過(guò) 56 KB 的不必要代碼。鑒于其他依賴項(xiàng)在捆綁包中占用約 50 KB,tree-shaking 有助于從我們的示例應(yīng)用程序的捆綁包中刪除約 25% 的 Chart.js 代碼。

          項(xiàng)目地址:https://github.com/chartjs/Chart.js

          過(guò)DataGear的參數(shù)化數(shù)據(jù)集、圖表事件處理和看板API功能,可以很方便地制作聯(lián)動(dòng)異步加載圖表的數(shù)據(jù)可視化看板。

          首先,新建一個(gè)參數(shù)化SQL數(shù)據(jù)集,如下所示:

          SELECT
            COL_NAME,   --地區(qū)名
            COL_VALUE,  --地區(qū)指標(biāo)數(shù)值
          FROM
            T_ANALYSIS
          WHERE
          <#if 上級(jí)地區(qū)名??>
            COL_PARENT='${上級(jí)地區(qū)名}'
          <#else>
            COL_PARENT='中國(guó)'
          </#if>

          參數(shù):

          名稱        類型     必填
          上級(jí)地區(qū)名  字符串   否

          T_ANALYSIS表數(shù)據(jù)示例:

          COL_NAME     COL_VALUE   COL_PARENT
          山東	     160         中國(guó)
          北京         200         中國(guó)
          ...
          朝陽(yáng)區(qū)       195         北京
          海淀區(qū)       200         北京
          ...
          青島市       10          山東
          濟(jì)南市       160         山東

          然后,使用上述數(shù)據(jù)集,新建兩個(gè)圖表,第一個(gè)是展示全國(guó)指標(biāo)的地圖圖表:

          圖表類型:基本地圖
          數(shù)據(jù)集列標(biāo)記:
          COL_NAME:地區(qū)名稱 (name)
          COL_VALUE:指標(biāo)數(shù)值 (value)

          第二個(gè)是展示指定地區(qū)指標(biāo)的柱狀圖:

          圖表類型:基本柱狀圖
          數(shù)據(jù)集列標(biāo)記:
          COL_NAME:名稱 (name) 
          COL_VALUE:數(shù)值 (value)

          然后,新建可視化看板,填寫(xiě)如下看板模板內(nèi)容:

          <!DOCTYPE html>
          <html>
          <head>
          <meta charset="UTF-8">
          <title></title>
          <style type="text/css">
          .dg-chart{
            display: inline-block;
            width: 600px;
            height: 500px;
          }
          #loadChartWrapper{
            position:absolute;
            top:0;
            left:650px;
            width:400px;
            height:300px;
            box-shadow: 0px 0px 6px #474747;
            -webkit-box-shadow: 0px 0px 6px #474747;
            display:none;
          }
          #loadChart{
            position:absolute;
            top:2em;
            left:0;
            right:0;
            bottom:0;
          }
          </style>
          <script type="text/javascript">
          function chartClickHandler(chartEvent)
          {
            //獲取點(diǎn)擊的地區(qū)名
            var name = chartEvent.data.name;
            $("#chartTitle").html(name);
            
            //圖表已加載,直接刷新數(shù)據(jù)
            if(dashboard.renderedChart("loadChart"))
            {
              var chart = dashboard.chartOf("loadChart");
              chart.dataSetParamValueFirst(0, name);
              chart.refreshData();
              $("#loadChartWrapper").show();
            }
            //圖表未加載
            else
            {
              dashboard.loadChart($("#loadChart"), "[第二個(gè)圖表ID]",function(chart)
              {
                chart.dataSetParamValueFirst(0, name);
                $("#loadChartWrapper").show();
              });
            }
          }
          $(function()
          {
            $("#removeChartBtn").click(function()
            {
              dashboard.removeChart("loadChart");
              $("#loadChartWrapper").hide();
            });
          });
          </script>
          </head>
          <body class="dg-dashboard">
          <div style="position: absolute;left:1;top:1;font-size:12px;">
          	DataGear <br>
          	http://www.datagear.tech
          </div>
          <div style="font-size:2em;text-align:center;margin-bottom:5px;">DataGear 看板示例</div>
          <p> </p>
          <div style="position:relative;">
            <div class="dg-chart" dg-chart-on-click="chartClickHandler"
              dg-chart-disable-setting="true"
              dg-chart-widget="[第一個(gè)圖表ID]">
              <!--全國(guó)指標(biāo)--></div>
            
            <div id="loadChartWrapper">
              <div id="chartTitle" style="position:absolute;top:2px;left:4px;font-weight:bold;"></div>
              <button id="removeChartBtn" style="position:absolute;top:2px;right:2px;">X</button>
              <div id="loadChart" dg-chart-disable-setting="true"
                dg-chart-options="{title:{show:false},legend:{show:false},grid:{top:30}}">
              <!--待加載的圖表元素--></div>
            </div>
          </div>
          </body>
          </html>

          點(diǎn)擊[保存并展示]按鈕,打開(kāi)看板展示頁(yè)面,完成!!!

          注意,上述模板中的“[第一個(gè)圖表ID]”、“[第二個(gè)圖表ID]”要替換為實(shí)際的ID。

          效果圖如下所示:


          官網(wǎng)地址:http://www.datagear.tech

          源碼地址:

          Gitee:https://gitee.com/datagear/datagear

          Github:https://github.com/datageartech/datagear

          大屏模板地址:https://gitee.com/datagear/DataGearDashboardTemplate

          文作者:HelloGitHub-kalifun

          圖表庫(kù)千萬(wàn)個(gè)今天 HelloGitHub 給大家推薦個(gè)很有“特色”的圖表庫(kù):一個(gè)手繪風(fēng)格的 JS 圖表庫(kù) —— Chart.xkcd,快收起你緊繃、嚴(yán)肅的面容讓我們一起看看用手繪風(fēng)格展示數(shù)據(jù)的效果。

          一、介紹

          項(xiàng)目地址:https://github.com/timqian/chart.xkcd

          Chart.xkcd 是一個(gè)圖表庫(kù),可繪制“非精細(xì)”、“卡通”或“手繪”樣式的圖表。



          效果是不是很可愛(ài)?那下面就跟著 HelloGitHub 發(fā)起的《講解開(kāi)源項(xiàng)目》[1]的教程一起學(xué)習(xí)、上手使用起來(lái)吧!

          二、快速入手

          使用 Chart.xkcd 很容易,只需頁(yè)面中包含庫(kù)的引用和一個(gè)用于顯示圖表的 <svg> 節(jié)點(diǎn)即可。

          2.1 代碼示例

          先用一段簡(jiǎn)短的代碼,讓大家了解下基本的參數(shù)和代碼的樣子,后面會(huì)有可運(yùn)行的代碼示例片段供大家學(xué)習(xí)和使用 。

          <!DOCTYPE html>
          <html lang="en">
          <head>
           <meta charset="UTF-8">
           <title>Title</title>
          </head>
          <body>
          <!--將 SVG 元素直接嵌入 HTML 頁(yè)面中-->
          <svg class="line-chart"></svg>
          <!--引入 JS 庫(kù)-->
          <script src="https://cdn.jsdelivr.net/npm/chart.xkcd@1.1/dist/chart.xkcd.min.js"></script>
          <script>
           //關(guān)鍵代碼塊
           const svg = document.querySelector('.line-chart')
           new chartXkcd.Line(svg, {
           title: '',
           xLabel: '',
           yLabel: '',
           data: {...},
           options: {},
           });
          </script>
          </body>
          </html>
          

          2.2 參數(shù)說(shuō)明

          • title:圖表的標(biāo)題
          • xLabel:圖表的 x 標(biāo)簽
          • yLabel:圖表的 y 標(biāo)簽
          • data:需要可視化的數(shù)據(jù)
          • options:自定義設(shè)置

          三、圖表類型

          Chart.xkcd 支持多樣的圖表類型,下面將逐一講解和實(shí)現(xiàn):折線圖、XY 圖、條形圖、圓餅/甜甜圈圖、雷達(dá)圖,實(shí)現(xiàn)的示例代碼完整可運(yùn)行、注釋完整、包含參數(shù)說(shuō)明。

          tips:下文中的示例代碼均可直接運(yùn)行,保存為 html 文件便可在本機(jī)查看效果。

          3.1 折線圖

          折線圖以折線形式顯示一系列數(shù)據(jù)點(diǎn),它可以用于顯示趨勢(shì)數(shù)據(jù)或不同數(shù)據(jù)集的比較。

          示例代碼

          <!DOCTYPE html>
          <html lang="en">
          <head>
           <meta charset="UTF-8">
           <title>Title</title>
          </head>
          <body>
          <!--將 SVG 元素直接嵌入 HTML 頁(yè)面中-->
          <svg class="line-chart"></svg>
          <!--引入 JS 庫(kù)-->
          <script src="https://cdn.jsdelivr.net/npm/chart.xkcd@1.1/dist/chart.xkcd.min.js"></script>
          <script>
           // querySelector() 方法返回文檔中匹配指定 CSS 選擇器的一個(gè)元素。獲取文檔中 class=".line-chart" 的元素。
           const svg = document.querySelector('.line-chart');
           // chartXkcd.Line 創(chuàng)建一個(gè)折線圖
           const lineChart = new chartXkcd.Line(svg, {
           //圖表的標(biāo)題
           title: 'Monthly income of an indie developer',
           // 圖表的 x 標(biāo)簽
           xLabel: 'Month',
           // 圖表的 y 標(biāo)簽
           yLabel: '$ Dollors',
           // 需要可視化的數(shù)據(jù)
           data: {
           // x 軸數(shù)據(jù)
           labels: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
           // y 軸數(shù)據(jù)
           datasets: [{
           // 第一組數(shù)據(jù)
           label: 'Plan',
           data: [30, 70, 200, 300, 500, 800, 1500, 2900, 5000, 8000],
           }, {
           // 第二組數(shù)據(jù)
           label: 'Reality',
           data: [0, 1, 30, 70, 80, 100, 50, 80, 40, 150],
           }],
           },
           // 可選配置以自定義圖表的外觀
           options: {
           // 自定義要在 y 軸上看到的刻度號(hào)(默認(rèn)為 3)
           yTickCount: 3,
           // 指定要放置圖例的位置
           legendPosition: chartXkcd.config.positionType.upLeft
           }
           });
          </script>
          </body>
          </html>
          

          參數(shù)說(shuō)明

          • yTickCount:自定義要在y軸上看到的刻度號(hào)(默認(rèn)為 3)
          • legendPosition:指定要放置圖例的位置(默認(rèn)為 chartXkcd.config.positionType.upLeft)。
          • 左上位置:chartXkcd.config.positionType.upLeft
          • 頂右上位置:chartXkcd.config.positionType.upRight
          • 左下位置:chartXkcd.config.positionType.downLeft
          • 右下位置:chartXkcd.config.positionType.downRight
          • dataColors:不同顏色的數(shù)據(jù)集數(shù)組
          • fontFamily:定制圖表中使用的字體系列
          • unxkcdify:禁用 xkcd 效果(默認(rèn)為 false)

          效果展示



          3.2 XY 圖

          XY 圖表用于通過(guò)指定點(diǎn)的 XY 坐標(biāo)來(lái)繪制點(diǎn),您也可以通過(guò)連接這些點(diǎn)來(lái)繪制 XY 折線圖。

          示例代碼

          <script>
           // querySelector() 方法返回文檔中匹配指定 CSS 選擇器的一個(gè)元素。獲取文檔中 class=".xy-chart" 的元素。
           const svg = document.querySelector('.xy-chart');
           //chartXkcd.XY 創(chuàng)建一個(gè)XY圖
           new chartXkcd.XY(svg, {
           //圖表的標(biāo)題
           title: 'Pokemon farms',
           // 圖表的 x 標(biāo)簽
           xLabel: 'Coodinate',
           // 圖表的 y 標(biāo)簽
           yLabel: 'Count',
           // 需要可視化的數(shù)據(jù)
           data: {
           datasets: [{
           // 第一組數(shù)據(jù)
           label: 'Pikachu',
           data: [{ x: 3, y: 10 }, { x: 4, y: 122 }, { x: 10, y: 100 }, { x: 1, y: 2 }, { x: 2, y: 4 }],
           }, {
           // 第二組數(shù)據(jù)
           label: 'Squirtle',
           data: [{ x: 3, y: 122 }, { x: 4, y: 212 }, { x: -3, y: 100 }, { x: 1, y: 1 }, { x: 1.5, y: 12 }],
           }],
           },
           options: {
           // 自定義要在 x 軸上看到的刻度號(hào)(默認(rèn)為 3)
           xTickCount: 5,
           // 自定義要在 y 軸上看到的刻度號(hào)(默認(rèn)為 3)
           yTickCount: 5,
           // 指定要放置圖例的位置
           legendPosition: chartXkcd.config.positionType.upRight,
           // 用線連接點(diǎn)(默認(rèn) false)
           showLine: false,
           // 指定時(shí)間格式
           timeFormat: undefined,
           // 更改點(diǎn)的大小(默認(rèn)為 1)
           dotSize: 1,
           },
           });
          </script>
          

          參數(shù)說(shuō)明

          • xTickCount:自定義要在x軸上看到的刻度號(hào)(默認(rèn)為 3)
          • yTickCount:自定義要在y軸上看到的刻度號(hào)(默認(rèn)為 3)
          • legendPosition:指定要放置圖例的位置
          • showLine: 點(diǎn)連接成線。
          • timeFormat:指定時(shí)間格式
          • dotSize:更改點(diǎn)的大小(默認(rèn)為 1)
          • dataColors:不同顏色的數(shù)據(jù)集數(shù)組
          • fontFamily:定制圖表中使用的字體系列
          • unxkcdify:禁用 xkcd 效果(默認(rèn)為 false)

          效果展示



          如果你想將這些點(diǎn)連接起來(lái),讓數(shù)據(jù)對(duì)比更加明顯的話。請(qǐng)修改 showLine:true 再刷新頁(yè)面你就可以看到連線的效果了。

          3.3 條形圖

          條形圖提供了一種顯示以豎條表示的數(shù)據(jù)值的方式。

          示例代碼

          <script>
           // querySelector() 方法返回文檔中匹配指定 CSS 選擇器的一個(gè)元素。獲取文檔中 class=".bar-chart" 的元素。
           const svg = document.querySelector('.bar-chart');
           // chartXkcd.Bar 創(chuàng)建一個(gè)條形圖
           const barChart = new chartXkcd.Bar(svg, {
           // 圖表的標(biāo)題
           title: 'github stars VS patron number',
           // xLabel: '', // optional
           // yLabel: '', // optional
           // 圖表數(shù)據(jù)
           data: {
           labels: ['github stars', 'patrons'],
           datasets: [{
           data: [100, 2],
           }],
           },
           options: {
           // 自定義要在 y 軸上看到的刻度號(hào)(默認(rèn)為 3)
           yTickCount: 2,
           },
           });
          </script>
          

          參數(shù)說(shuō)明

          • yTickCount:自定義要在y軸上看到的刻度號(hào)(默認(rèn)為 3)
          • dataColors:不同顏色的數(shù)據(jù)集數(shù)組
          • fontFamily:定制圖表中使用的字體系列
          • unxkcdify:禁用xkcd效果(默認(rèn)為 false)

          效果展示



          3.4 圓餅/甜甜圈圖

          餅圖廣泛得應(yīng)用在各個(gè)領(lǐng)域,用于表示不同分類的占比情況,通過(guò)弧度大小來(lái)對(duì)比各種分類。餅圖通過(guò)將一個(gè)圓餅按照分類的占比劃分成多個(gè)區(qū)塊,整個(gè)圓餅代表數(shù)據(jù)的總量,每個(gè)區(qū)塊(圓弧)表示該分類占總體的比例大小,所有區(qū)塊(圓弧)的加和等于 100%。

          示例代碼

          <script>
           // querySelector() 方法返回文檔中匹配指定 CSS 選擇器的一個(gè)元素。獲取文檔中 class=".pie-chart" 的元素。
           const svg = document.querySelector('.pie-chart');
           // chartXkcd.Pie 創(chuàng)建一個(gè)圓餅圖
           const pieChart = new chartXkcd.Pie(svg, {
           // 圖表的標(biāo)題
           title: 'What Tim made of',
           // 需要可視化的數(shù)據(jù)
           data: {
           labels: ['a', 'b', 'e', 'f', 'g'],
           datasets: [{
           data: [500, 200, 80, 90, 100],
           }],
           },
           options: {
           // 指定空的餅圖半徑
           innerRadius: 0.5,
           // 指定要放置圖例的位置
           legendPosition: chartXkcd.config.positionType.upRight,
           },
           });
          </script>
          

          參數(shù)說(shuō)明

          • innerRadius:指定空的餅圖半徑(默認(rèn)值:0.5)
          • 需要餅圖嗎?將 innerRadius 設(shè)置為 0
          • legendPosition:指定要放置圖例的位置
          • dataColors:不同顏色的數(shù)據(jù)集數(shù)組
          • fontFamily:定制圖表中使用的字體系列
          • unxkcdify:禁用 xkcd 效果(默認(rèn)為 false)

          效果展示



          3.5 雷達(dá)圖

          雷達(dá)圖(Radar Chart)又被叫做蜘蛛網(wǎng)圖,適用于顯示三個(gè)或更多的維度的變量。雷達(dá)圖是以在同一點(diǎn)開(kāi)始的軸上顯示的三個(gè)或更多個(gè)變量的二維圖表的形式來(lái)顯示多元數(shù)據(jù)的方法,其中軸的相對(duì)位置和角度通常是無(wú)意義的。

          示例代碼

          <script>
           // querySelector() 方法返回文檔中匹配指定 CSS 選擇器的一個(gè)元素。獲取文檔中 class=".radar-chart" 的元素。
           const svg = document.querySelector('.radar-chart');
           // chartXkcd.Radar 創(chuàng)建一個(gè)雷達(dá)圖
           const radarChart = new chartXkcd.Radar(svg, {
           // 圖表的標(biāo)題
           title: 'Letters in random words',
           // 需要可視化的數(shù)據(jù)
           data: {
           labels: ['c', 'h', 'a', 'r', 't'],
           datasets: [{
           label: 'ccharrrt',
           data: [2, 1, 1, 3, 1],
           }, {
           label: 'chhaart',
           data: [1, 2, 2, 1, 1],
           }],
           },
           options: {
           // 在圖表中顯示圖例
           showLegend: true,
           // 點(diǎn)的大小
           dotSize: 0.8,
           // 在每行附近顯示標(biāo)簽
           showLabels: true,
           // 指定要放置圖例的位置
           legendPosition: chartXkcd.config.positionType.upRight,
           // unxkcdify: true,
           },
           });
          </script>
          

          參數(shù)說(shuō)明

          • showLabels:在每行附近顯示標(biāo)簽(默認(rèn)為 false)
          • ticksCount:自定義要在主行上看到的刻度號(hào)(默認(rèn)為 3)
          • dotSize:更改點(diǎn)的大小(默認(rèn)為 1)
          • showLegend:在圖表附近顯示圖例(默認(rèn)為 false)
          • legendPosition:指定要放置圖例的位置
          • dataColors:不同顏色的數(shù)據(jù)集數(shù)組
          • fontFamily:定制圖表中使用的字體系列
          • unxkcdify:禁用 xkcd 效果(默認(rèn)為 false)

          效果展示



          四、最后

          以上就是講解的全部?jī)?nèi)容,相信教程至此 Chart.xkcd 庫(kù)的基本用法你已經(jīng)基本掌握,后面就可以用來(lái)今天學(xué)到的東西,提高自己項(xiàng)目的顏值了。

          有了 Chart.xkcd 讓數(shù)據(jù)可愛(ài)地展示出來(lái)并不難,快動(dòng)手自己實(shí)現(xiàn)一個(gè)吧~

          參考資料

          [1]《講解開(kāi)源項(xiàng)目》: https://github.com/HelloGitHub-Team/Article

          [2]CHART.XKCD 官方文檔: https://timqian.com/chart.xkcd/

          [3]CHART.XKCD 項(xiàng)目地址: https://github.com/timqian/chart.xkcd


          『講解開(kāi)源項(xiàng)目系列』——讓對(duì)開(kāi)源項(xiàng)目感興趣的人不再畏懼、讓開(kāi)源項(xiàng)目的發(fā)起者不再孤單。跟著我們的文章,你會(huì)發(fā)現(xiàn)編程的樂(lè)趣、使用和發(fā)現(xiàn)參與開(kāi)源項(xiàng)目如此簡(jiǎn)單。歡迎留言聯(lián)系我們、加入我們,讓更多人愛(ài)上開(kāi)源、貢獻(xiàn)開(kāi)源~


          主站蜘蛛池模板: 欧美激情国产精品视频一区二区| 精品视频一区二区三区在线观看| 一区二区三区在线播放| 日韩精品免费一区二区三区| 国产午夜精品一区二区三区极品| 国产在线步兵一区二区三区| 国产一区二区视频在线播放| 乱子伦一区二区三区| 日韩在线一区视频| 香蕉视频一区二区三区| 性无码一区二区三区在线观看| 人妻少妇精品视频三区二区一区| 日本一区二区在线免费观看| 无码囯产精品一区二区免费| 正在播放国产一区| 国产AV午夜精品一区二区三区| 精品无码国产AV一区二区三区 | 99久久精品午夜一区二区| 国产人妖视频一区在线观看| 熟妇人妻一区二区三区四区| 日本一区二区在线播放| 国产视频一区在线播放| 亚洲AV无码一区二区乱孑伦AS| 亚洲AV一区二区三区四区| 红杏亚洲影院一区二区三区| 欧美一区内射最近更新| 成人精品视频一区二区三区不卡 | 99精品一区二区三区| 色综合一区二区三区| 国产一区二区三区乱码网站| 精品视频一区二区三区| 无码日本电影一区二区网站| 免费一区二区无码东京热| 国产精品亚洲专一区二区三区| 无码精品人妻一区二区三区中 | 色综合视频一区二区三区| 国产福利一区二区三区在线观看 | 国模少妇一区二区三区| 国产一区高清视频| 亚洲高清一区二区三区 | 亚洲国产一区在线|