<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          給奧運(yùn)金牌做可視化

          共 15794字,需瀏覽 32分鐘

           ·

          2021-08-03 08:43

          前言

          2020 東京奧運(yùn)會(huì)已經(jīng)開(kāi)幕很多天了,還記得小時(shí)候看奧運(yùn)會(huì)的是在2008年的北京奧運(yùn)會(huì),主題曲是「北京歡迎你」, 那個(gè)時(shí)候才上小學(xué)吧,幾乎有中國(guó)隊(duì)的每場(chǎng)必看,當(dāng)時(shí)也是熱血沸騰了, 時(shí)間轉(zhuǎn)眼已經(jīng)到了2021年而我也從小學(xué)生變成了一個(gè)每天不斷敲代碼的程序員?????,看奧運(yùn)的時(shí)間又少,但是又想出分力,既然是程序員,想著能為奧運(yùn)會(huì)搞點(diǎn)什么?第一時(shí)間想到了就是給奧運(yùn)獎(jiǎng)牌數(shù)??做可視化,因?yàn)閱慰幢砀駭?shù)據(jù),不能體現(xiàn)出我們中國(guó)的牛逼??, 廢話不多說(shuō),直接開(kāi)寫(xiě)。

          數(shù)據(jù)獲得

          我們先看下奧運(yùn)獎(jiǎng)牌數(shù)的表格,這東西肯定是接口獲得的吧,我不可能手寫(xiě)吧,而且每天都是更新的,難道我要每天去改,肯定不是這樣的,我當(dāng)時(shí)腦子里就想著去做爬蟲(chóng),去用「puppeteer」 去模擬瀏覽器的行為然后獲取頁(yè)面的原生dom,然后將表格的數(shù)據(jù)搞出來(lái), 然后我就很興奮的去搞了,寫(xiě)了下面的代碼:

          const puppeteer = require('puppeteer')

          async function main({
            // 啟動(dòng)chrome瀏覽器
            const browser = await puppeteer.launch({
              // // 指定該瀏覽器的路徑
              // executablePath: chromiumPath,
              // 是否為無(wú)頭瀏覽器模式,默認(rèn)為無(wú)頭瀏覽器模式
              headlessfalse,
            })

            // 在一個(gè)默認(rèn)的瀏覽器上下文中被創(chuàng)建一個(gè)新頁(yè)面
            const page1 = await browser.newPage()

            // 空白頁(yè)剛問(wèn)該指定網(wǎng)址
            await page1.goto(
              'https://tiyu.baidu.com/tokyoly/home/tab/%E5%A5%96%E7%89%8C%E6%A6%9C/from/pc'
            )

            // 等待title節(jié)點(diǎn)出現(xiàn)
            await page1.waitForSelector('title')

            // 用page自帶的方法獲取節(jié)點(diǎn)

            // 用js獲取節(jié)點(diǎn)
            const titleDomText2 = await page1.evaluate(() => {
              const titleDom = document.querySelectorAll('#kw')
              return titleDom
            })
            console.log(titleDomText2, '查看數(shù)據(jù)---')
            // 截圖
            //await page1.screenshot({ path: 'google.png' })
            //   await page1.pdf({
            //     path: './baidu.pdf',
            //   })
            browser.close()
          }
          main()

          然后當(dāng)我很興奮的想要去結(jié)果的時(shí)候,結(jié)果發(fā)現(xiàn)是空。百度是不是做了反爬蟲(chóng)協(xié)議, 畢竟我是爬蟲(chóng)菜鳥(niǎo),搞了很久。還是沒(méi)搞出來(lái)。如果有大佬會(huì),歡迎指點(diǎn)我下哦!

          image-20210731112152170

          不過(guò)這個(gè)「puppeteer」,這個(gè)庫(kù)有點(diǎn)牛皮的,可以實(shí)現(xiàn)網(wǎng)頁(yè)截圖、生成pdf、攔截請(qǐng)求,其實(shí)有點(diǎn)自動(dòng)化測(cè)試的感覺(jué)。感興趣的同學(xué)可以自行了解一下,這不在本篇文章介紹的重點(diǎn)。

          接口獲得

          然后這時(shí)候就開(kāi)始瘋狂百度,開(kāi)始尋找有沒(méi)有現(xiàn)成的「api」, 真是踏破鐵鞋無(wú)覓處,得來(lái)全不費(fèi)工夫。被我找到了,原來(lái)是有大佬已經(jīng)開(kāi)始做了, 這時(shí)候我本地直接去請(qǐng)求那個(gè)接口是有問(wèn)題的,前端不得不處理的問(wèn)題—— 跨域。看著東西我頭疼哇, 不過(guò)沒(méi)關(guān)系, 我直接node起一個(gè)服務(wù)器, 我node去請(qǐng)求那個(gè)接口,然后后臺(tái)在配置下跨域, 搞定接口數(shù)據(jù)就直接獲得了, 后臺(tái)服務(wù)我是用的express, 搭建的服務(wù)器直接隨便搞搞的。代碼如下:

          const axios = require('axios')
          const express = require('express')
          const request = require('request')
          const app = express()

          const allowCrossDomain = function (req, res, next{
            res.header('Access-Control-Allow-Origin''*')
            res.header('Access-Control-Allow-Methods''GET,PUT,POST,DELETE')
            res.header('Access-Control-Allow-Headers''Content-Type')
            res.header('Access-Control-Allow-Credentials''true')
            next()
          }
          app.use(allowCrossDomain)

          app.get('/data', (req, res) => {
            request(
              {
                url'http://apia.yikeapi.com/olympic/?appid=43656176&appsecret=I42og6Lm',
                method'GET',
                headers: { 'Content-Type''application/json' },
              },
              function (error, response, body{
                if (error) {
                  res.send(error)
                } else {
                  res.send(response)
                }
              }
            )
          })
          app.listen(3030)

          這樣我就是實(shí)現(xiàn)了接口轉(zhuǎn)發(fā),也搞定了跨域問(wèn)題,前臺(tái)我直接用 fetch去請(qǐng)求數(shù)據(jù)然后做一層數(shù)據(jù)轉(zhuǎn)換,但是這個(gè)接口不能頻繁請(qǐng)求,動(dòng)不動(dòng)就crash, 是真的煩, OK所以直接做了一個(gè)操作, 將數(shù)據(jù) 存到localstorage中,然后做一個(gè)定時(shí)刷新,時(shí)間大概是一天一刷。這樣就保證數(shù)據(jù)的有效性。代碼如下:

          getData() {
            let curTime = Date.now()
            if (localStorage.getItem('aoyun')) {
              let { list, time } = JSON.parse(localStorage.getItem('aoyun'))
              console.log(curTime - time, '查看時(shí)間差')
              if (curTime - time <= 24 * 60 * 60 * 60) {
                this.data = list
              } else {
                this.fetchData()
              }
            } else {
              this.fetchData()
            }
          }

          fetchData() {
            fetch('http://localhost:3030/data')
              .then((res) => res.json())
              .then((res) => {
                const { errcode, list } = JSON.parse(res.body)
                if (errcode === 100) {
                  alert('接口請(qǐng)求太頻繁')
                } else if (errcode === 0) {
                  this.data = list
                  const obj = {
                    list,
                    timeDate.now(),
                  }
                  localStorage.setItem('aoyun'JSON.stringify(obj))
                }
              })
              .catch((err) => {
                console.log(err)
              })
          }

          數(shù)據(jù)如下圖所示 :

          image-20210731114644399

          柱狀圖的表示

          其實(shí)我想了很多表達(dá)中國(guó)金牌數(shù)的方式,最終我還是選擇用2d柱狀圖去表示,并同時(shí)做了動(dòng)畫(huà)效果,顯得每一塊金牌??來(lái)的并不容易。我還是用原生手寫(xiě)柱狀圖不去使用「Echarts」 庫(kù), 我們首先先看下柱狀圖:

          柱狀圖

          從圖中可以分析出一些元素

          1. x軸和y軸以及一些直線,所以我只要封裝一個(gè)畫(huà)直線的方法
          2. 有很多矩形, 封裝一個(gè)畫(huà)矩形的方法
          3. 還有一些刻度和標(biāo)尺
          4. 最后就是一進(jìn)入的動(dòng)畫(huà)效果

          畫(huà)布初始化

          在頁(yè)面上創(chuàng)建canvas和獲取canvas的一些屬性,并對(duì)canvas綁上移動(dòng)事件。代碼如下:

          get2d() {
              this.canvas = document.getElementById('canvas')
              this.canvas.addEventListener('mousemove'this.onMouseMove.bind(this))
              this.ctx = this.canvas.getContext('2d')
              this.width = canvas.width
              this.height = canvas.height
            }

          畫(huà)坐標(biāo)軸

          坐標(biāo)軸本質(zhì)上也是一個(gè)直線,直線對(duì)應(yīng)的兩個(gè)點(diǎn),不同的直線其實(shí)就是對(duì)應(yīng)的端點(diǎn)不同,所以我直接封裝了一個(gè)畫(huà)直線的方法:

            // 畫(huà)線的方法
            drawLine(x, y, X, Y) {
              this.ctx.beginPath()
              this.ctx.moveTo(x, y)
              this.ctx.lineTo(X, Y)
              this.ctx.stroke()
              this.ctx.closePath()
            }

          可能有的人對(duì)canvas不熟悉,這里我還是大概說(shuō)下, 開(kāi)啟一段路徑, 移動(dòng)畫(huà)筆到開(kāi)始的點(diǎn), 然后畫(huà)直線到末尾的點(diǎn),然后描邊 這一步是canvas做渲染, 很重要,很多小白不寫(xiě), 直線就不出來(lái), 然后閉合路徑。結(jié)束over!

          畫(huà)坐標(biāo)軸我們首先先確定原點(diǎn)在哪里,我們首先給畫(huà)布向內(nèi)縮一個(gè)padding距離,然后呢,算出畫(huà)布實(shí)際的寬度和高度。

          代碼如下:

          initChart() {
            // 留一個(gè)內(nèi)邊距
            this.padding = 50
            // 算出畫(huà)布實(shí)際的寬度和高度
            this.cHeight = this.height - this.padding * 2
            this.cWidth = this.width - this.padding * 2
            // 計(jì)算出原點(diǎn)
            this.originX = this.padding
            this.originY = this.padding + this.cHeight
          }

          有了原點(diǎn)我們就可以畫(huà)X軸和Y軸了, 只要加上「實(shí)際畫(huà)布」對(duì)應(yīng)的寬度和高度 就好了 。代碼如下:

           //設(shè)置canvas 樣式
            this.setCanvasStyle()
            // 畫(huà)x軸
            this.drawLine(
              this.originX,
              this.originY,
              this.originX,
              this.originY - this.cHeight
            )
            // 畫(huà)Y軸
            this.drawLine(
              this.originX,
              this.originY,
              this.originX + this.cWidth,
              this.originY
            )

          第一個(gè) 函數(shù)就是設(shè)置canvas畫(huà)筆的樣式的,其實(shí)這東西沒(méi)什么。我們看下效果:

          X軸和Y軸

          很多人以為到這里就結(jié)束了哈哈哈, 那你想太多了, canvas我設(shè)置的畫(huà)線寬度是1px 為什么看圖片的線的寬度像是2px?不仔細(xì)觀察根本發(fā)現(xiàn)不了這個(gè)問(wèn)題, 所以我們要學(xué)會(huì)思考這到底是什么問(wèn)題?其實(shí)這個(gè)問(wèn)題也是我看「Echarts」源碼發(fā)現(xiàn)的, 學(xué)而不思則罔,思而不學(xué)則殆哇!

          彩蛋——canvas如何畫(huà)出1PX的直線

          在這里我舉一個(gè)例子, 你就明白了, 假設(shè)我要畫(huà)從(50,10) 到 (200,10)這樣的一條直線。為了畫(huà)這條線,瀏覽器首先到達(dá)初始起點(diǎn)(50,10)。這條線寬1px,所以兩邊各留0.5px。所以基本上初始起點(diǎn)是從(50,9.5)延伸到(50,10.5)?,F(xiàn)在瀏覽器不能在屏幕上顯示0.5像素——最小閾值是1像素。瀏覽器別無(wú)選擇,只能將起點(diǎn)的邊界延伸到屏幕上的實(shí)際像素邊界。它會(huì)在兩邊再加0.5倍的“垃圾”。所以現(xiàn)在,最初的起點(diǎn)是從(50,9)擴(kuò)展到(50,11),所以看起來(lái)有2px寬。情況如下:

          實(shí)際效果圖

          現(xiàn)在你就應(yīng)該明白了原來(lái)「瀏覽器不能顯示0.5像素哇, 四舍五入了」, 知道了 問(wèn)題我們就一定有解決方案

          平移canvas

          ctx.translate (x,y ) 這個(gè)方法:

          translate() 方法, 將 canvas 按原始 x點(diǎn)的水平方向、原始的 y點(diǎn)垂直方向進(jìn)行「平移變換」

          如圖:

          canvas平移

          說(shuō)的更直白點(diǎn), 你對(duì)canvas做了translate變化后, 你之前所有畫(huà)的點(diǎn),都會(huì)相對(duì)偏移。所以呢,回到我們這個(gè)問(wèn)題上來(lái), 解決辦法就是什么呢?就我將畫(huà)布 整體向下偏移 0.5 , 所以原本坐標(biāo) (50,10) 變成了(50.5,10.5) 和(200.5, 10.5)ok 然后瀏覽器的再去畫(huà)的 他還是要預(yù)留像素,  所以就是從(50.5, 10) 到(50.5, 11) 這個(gè)區(qū)間去畫(huà)OK, 就是1px了。我們來(lái)try it.

          代碼如下:

          this.ctx.translate(0.50.5)
          // 畫(huà)x軸
          this.drawLine(
            this.originX,
            this.originY,
            this.originX,
            this.originY - this.cHeight
          )
          // 畫(huà)Y軸
          this.drawLine(
            this.originX,
            this.originY,
            this.originX + this.cWidth,
            this.originY
          )
          this.ctx.translate(-0.5-0.5)

          偏移完之后還是要恢復(fù)過(guò)去的, 還是要十分注意的。我畫(huà)了兩張圖作比對(duì):

          偏移后              偏移前

          不多說(shuō)了, 看到這里,如果覺(jué)得對(duì)你有幫助的話, 或者學(xué)到了話, 我是希望你給我點(diǎn)贊??、評(píng)論、加收藏。

          畫(huà)標(biāo)尺

          我們現(xiàn)在只有X軸和Y軸, 光禿禿的,我給X軸和Y軸底部增加一些標(biāo)尺,X軸對(duì)應(yīng)的標(biāo)尺,肯定就是每個(gè)國(guó)家的名字,大概的思路就是數(shù)據(jù)的數(shù)量去做一個(gè)分段, 然后去填充就好了。

          代碼如下:

          drawXlabel() {
            const length = this.data.slice(010).length
            this.ctx.textAlign = 'center'
            for (let i = 0; i < length; i++) {
              const { country } = this.data[i]
              const totalWidth = this.cWidth - 20
              const xMarker = parseInt(
                this.originX + totalWidth * (i / length) + this.rectWidth
              )
              const yMarker = this.originY + 15
              this.ctx.fillText(country, xMarker, yMarker, 40// 文字
            }
          }

          這里的話我截取了排名前10的國(guó)家, 分段的思路, 首先兩邊留白20px,  我們首先先定義每一個(gè)柱狀圖的寬度 假設(shè)是 30 對(duì)應(yīng)上文的 this.rectWidth, 然后每個(gè)文字的坐標(biāo) 其實(shí)就很好算了, 起初的x + 所占的分端數(shù) +  矩形寬度就可以畫(huà)出來(lái)了

          如圖:

          X軸標(biāo)尺

          x軸畫(huà)完了,我們開(kāi)始畫(huà)Y軸, Y軸的大概思路就是 以最多的獎(jiǎng)牌數(shù)去做分段, 這里我就分成6段吧。

          // 定義Y軸的分段數(shù)
          this.ySegments = 6
          //定義字體最大寬度
          this.fontMaxWidth = 40

          接下啦我們就開(kāi)始計(jì)算Y軸每個(gè)點(diǎn)的Y坐標(biāo), X坐標(biāo)其實(shí)很好計(jì)算 只要原點(diǎn)坐標(biāo)的X向左平移幾個(gè)距離就好了,主要是計(jì)算Y軸的坐標(biāo), 這里一定要注意的是, 我們從坐標(biāo)是相對(duì)于左上角的, 所以呢, Y軸的坐標(biāo)應(yīng)該是向上遞減的。

          drawYlabel() {
            const { jin: maxValue } = this.data[0]
            this.ctx.textAlign = 'right'
            for (let i = 1; i <= this.ySegments; i++) {
              const markerVal = parseInt(maxValue * (i / this.ySegments))
              const xMarker = this.originX - 5
              const yMarker =
                parseInt((this.cHeight * (this.ySegments - i)) / this.ySegments) +
                this.padding +
                20
              this.ctx.fillText(markerVal, xMarker, yMarker) // 文字
            }
          }

          最大的數(shù)據(jù)就是數(shù)組的第一個(gè)數(shù)據(jù), 然后每個(gè)標(biāo)尺就是所占的比例就好了, Y軸的坐標(biāo)由于我們是遞減的所以 對(duì)應(yīng)的坐標(biāo)應(yīng)該是 1- 所占的份額, 由于這只是算的圖標(biāo)的實(shí)際高度 ,換算到畫(huà)布里面, 還要加上原先我們?cè)O(shè)置的內(nèi)邊距,由于又加上了文字, 文字也占有一定像素, 所以有加上了20。OK Y軸畫(huà)結(jié)束了, 有了Y軸每個(gè)分段的坐標(biāo), 同時(shí)就畫(huà)出背后的對(duì)應(yīng)的幾條實(shí)線。

          代碼如下:

          this.drawLine(
            this.originX,
            yMarker - 4,
            this.originX + this.cWidth,
            yMarker - 4
          )

          最終呈現(xiàn)的效果圖如下:

          xy軸

          畫(huà)矩形

          everything isReady, 下面開(kāi)始畫(huà)矩形, 還是同樣的方式 先封裝畫(huà)矩形的方法, 然后我們只要傳入對(duì)應(yīng)的數(shù)據(jù)就OK了。

          這里用到了,canvas原生的rect 方法。參數(shù)理解如下:

          rect語(yǔ)法

          矩形寬度 我們自定義的, 矩形的高度就是對(duì)應(yīng)的獎(jiǎng)牌數(shù)在畫(huà)布中的高度, 所以我們只要確定 矩形的起點(diǎn)就搞定了, 這里矩形的(x,y) 其實(shí)是左上角的點(diǎn)。

          代碼如下:

          //繪制方塊
          drawRect(x, y, width, height) {
            this.ctx.beginPath()
            this.ctx.rect(x, y, width, height)
            this.ctx.fill()
            this.ctx.closePath()
          }

          第一步我們先做一個(gè)點(diǎn)的映射, 我們?cè)诋?huà)Y軸的時(shí)候,將Y軸的上的畫(huà)布的所有的點(diǎn)都放在一個(gè)數(shù)組中, 注意記得將原點(diǎn)的Y放進(jìn)去。所以只要計(jì)算出每個(gè)獎(jiǎng)牌數(shù)在總部的比例是多少?然后再用原點(diǎn)的Y值做一個(gè)相減就可以得到真正的Y軸坐標(biāo)了。X軸的坐標(biāo)就比較簡(jiǎn)單了,原點(diǎn)的X坐標(biāo)加上  ( 所占的比例 / 總長(zhǎng)度 ) 然后在加上 一半的矩形寬度就好了。這個(gè)道理和畫(huà)文字是一樣的, 只不過(guò)文字要居中嘛。

          代碼如下:

          drawBars() {
            const length = this.data.slice(010).length
            const { jin: max } = this.data[0]
            const diff = this.yPoints[0] - this.yPoints[this.yPoints.length - 1]
            for (let i = 0; i < length; i++) {
              const { jin: count } = this.data[i]
              const barH = (count / max) * diff
              const y = this.originY - barH
              const totalWidth = this.cWidth - 20
              const x = parseInt(
                this.originX + totalWidth * (i / length) + this.rectWidth / 2
              )
              this.drawRect(x, y, this.rectWidth, barH)
            }
          }

          畫(huà)出的效果圖如下:

          獎(jiǎng)牌數(shù)

          矩形交互優(yōu)化

          黑禿禿的也丑了吧,一個(gè)不知道的人根本不知道這是哪一個(gè)國(guó)家獲得多少塊金牌。

          1. 給矩形加一個(gè)漸變
          2. 加一些文字

          現(xiàn)在畫(huà)矩形的基礎(chǔ)上加一些文字吧,代碼如下:

          this.ctx.save()
          this.ctx.textAlign = 'center'
          this.ctx.fillText(count, x + this.rectWidth / 2, y - 5)
          this.ctx.restore()

          漸變就設(shè)計(jì)到Canvas一個(gè)api了,createLinearGradient

          ?

          createLinearGradient() 方法需要指定四個(gè)參數(shù),分別表示漸變線段的開(kāi)始和結(jié)束點(diǎn)。

          ?

          那我就開(kāi)始了首先肯定創(chuàng)建漸變:

          getGradient() {
            const gradient = this.ctx.createLinearGradient(0, 0, 0, 300)
            gradient.addColorStop(0, 'green')
            gradient.addColorStop(1, 'rgba(67,203,36,1)')
            return gradient
          }

          然后呢我們就改造drawReact下 ,這里用了 restore 和save 這個(gè)方法, 防止污染文字的樣式。

          //繪制方塊
          drawRect(x, y, width, height) {
            this.ctx.save()
            this.ctx.beginPath()
            const gradient = this.getGradient()
            this.ctx.fillStyle = gradient
            this.ctx.strokeStyle = gradient
            this.ctx.rect(x, y, width, height)
            this.ctx.fill()
            this.ctx.closePath()
            this.ctx.restore()
          }

          如圖所示:

          漸變圖

          添加動(dòng)畫(huà)效果

          光一個(gè)靜態(tài)的不能看出我們的牛皮??,所以得有動(dòng)畫(huà)的效果慢慢的增加對(duì)吧。其實(shí)我們可以思考??下整個(gè)動(dòng)畫(huà)過(guò)程,變化的其實(shí)就兩個(gè), 柱狀圖的高度和文字,  其實(shí)坐標(biāo)軸, 以及柱狀圖的x坐標(biāo)是不變的, 所以我只要定義兩個(gè)變量一個(gè)開(kāi)始的值 ,和一個(gè)總共的值,高度和文字的大小 其實(shí)在每一幀去乘以對(duì)應(yīng)的高度就可以了。

          代碼如下:

          // 運(yùn)動(dòng)相關(guān)
          this.ctr = 1
          this.numctr = 100

          我們改造下drawBars 這個(gè)方法:

          // 每一次的比例是多少
          const dis = this.ctr / this.numctr

          // 柱狀圖的高度 乘以對(duì)應(yīng)的比例
          const barH = (count / max) * diff * dis

          // 文字這里取整下,因?yàn)橛锌赡艹槐M 
          this.ctx.fillText(
            parseInt(count * dis),
            x + this.rectWidth / 2,
            y - 5
          )

          // 最后執(zhí)行動(dòng)畫(huà)
          if (this.ctr < this.numctr) {
            this.ctr++
            requestAnimationFrame(() => {
              this.ctx.clearRect(0, 0, this.width, this.height)
              this.drawLineLabelMarkers()
            })
          }

          每一次都加一,直到比總數(shù)大, 然后不斷重畫(huà)。就可以形成動(dòng)畫(huà)效果了。我們看下gif圖吧:

          奧運(yùn)gif圖

          總結(jié)

          本篇文章寫(xiě)到這里也算結(jié)束了,我大概總結(jié)下:

          1. canvas如何畫(huà)出1px 的直線, 這里面是有坑的
          2. 還有就是如何進(jìn)行動(dòng)畫(huà)的設(shè)計(jì),本質(zhì)去尋找那些變的,然后去處理就好了
          3. canvas 中如何進(jìn)行線性漸變的。
          4. 爬蟲(chóng)我是失敗了,我就沒(méi)啥好總結(jié)的,不過(guò)有一點(diǎn):木偶人這個(gè)庫(kù), 大家可以玩一下的。

          我們一起為中國(guó)????奧運(yùn)加油!奧利給?。?!

          源碼獲得

          關(guān)注公眾號(hào)【前端圖形學(xué)】, 回復(fù)【加群】?jī)蓚€(gè)字,就可以找到助手獲得所有源碼。

          瀏覽 59
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚州老女人BB | 91亚洲国产成人久久精品网 | 一卡二卡成人在线 | 日韩AV免费看 | 国产成va人 |