Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 日本wwwcom,国产精品高清视亚洲乱码,精品女同一区二区三区免费播放

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

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

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

          如何通過(guò)css格子布局一個(gè)簡(jiǎn)單的頁(yè)面

          文鏈接: https://getflywheel.com/layout/css-grid-layouts-how-to/

          柵格布局的思想起源源自于印刷設(shè)計(jì)。柵格是用來(lái)將設(shè)計(jì)元素精確定位到頁(yè)面上的的測(cè)量工具。這種想法經(jīng)常被用在網(wǎng)頁(yè)上來(lái)進(jìn)行內(nèi)容組織和統(tǒng)一,提升用戶的視覺(jué)體驗(yàn)。

          網(wǎng)頁(yè)設(shè)計(jì)剛起步的時(shí)候,設(shè)計(jì)和布局都是是相當(dāng)簡(jiǎn)單的, 通常包含頭部,側(cè)邊欄,內(nèi)容區(qū)域和頁(yè)腳。現(xiàn)在,隨著網(wǎng)絡(luò)的演變,網(wǎng)頁(yè)的布局也變得更加復(fù)雜,做網(wǎng)頁(yè)設(shè)計(jì)師的人也隨之增加。我們經(jīng)常需要大量的內(nèi)容區(qū)域,響應(yīng)式設(shè)計(jì),多頁(yè)面模板設(shè)計(jì),以及許多其他的。浮動(dòng)和定位在實(shí)現(xiàn)這些設(shè)計(jì)的時(shí)候,是必不可少的。但浮動(dòng)聽(tīng)起來(lái)簡(jiǎn)單,實(shí)際操作起來(lái)卻很棘手。

          但接下來(lái),我們會(huì)介紹一種簡(jiǎn)單的設(shè)計(jì)布局。隨著CSS柵格布局的不斷發(fā)展,成為設(shè)計(jì)師也會(huì)變得越來(lái)越容易。

          CSS柵格兼容性

          作為一名設(shè)計(jì)師,需要了解網(wǎng)頁(yè)設(shè)計(jì)的未來(lái)。CSS柵格布局將改變現(xiàn)有規(guī)則,為設(shè)計(jì)師處理頭痛了許多年的定位。雖然目前還不是主流的做法,但是這是一件值得期待的事情。

          在我們真的深入了解柵格布局之前,要強(qiáng)調(diào)的一件事,瀏覽器并不普遍支持, 希望這種工作方式在未來(lái)可以得到越來(lái)越多的瀏覽器支持。不過(guò), 好消息是, 您可以輕松地嘗試使用CSS柵格布局,以及了解它是如何工作的。

          在使用示例之前,請(qǐng)你確保你的瀏覽器支持。目前只有Internet Explorer 10+和 edge 支持。其他的瀏覽器通過(guò)一些手段也可以瀏覽,但因?yàn)樗皇枪倬W(wǎng)支持,所以你只能是不斷的去嘗試。(If you view the Can I Use documentation on CSS Grid Layouts, at the time of this post, you will notice little flag indicators. These show that you will need to be in “flag mode.”)如果你邊使用Can I Use來(lái)查看柵格布局的兼容性,邊看這篇文章,那么你就可以注意到每個(gè)細(xì)節(jié)的不同。

          當(dāng)您在測(cè)試柵格布局的時(shí)候,你需要做幾件事情幫助你正確地看到布局。使用Chrome查看,你需要啟用“實(shí)驗(yàn)性網(wǎng)絡(luò)平臺(tái)功能”。如何啟用呢?在Chrome 瀏覽器中打開(kāi)chrome://flags 這個(gè)地址。當(dāng)url 鏈接chrome://flags加載完畢之后,向下滾動(dòng)頁(yè)面,找到該選項(xiàng),設(shè)置為“啟用實(shí)驗(yàn)性網(wǎng)絡(luò)平臺(tái)功能”。

          火狐也允許您查看柵格布局,通過(guò)“l(fā)ayout.css.grid.enabled”參數(shù)設(shè)置。開(kāi)啟方法類似于Chrome瀏覽器的說(shuō)明。在Firefox瀏覽器中URL輸入 about:config。向下滾動(dòng)頁(yè)面,設(shè)置為啟用 “l(fā)ayout.css.grid.enabled” 。

          如果你想馬上開(kāi)始使用CSS柵格布局,對(duì)于不支持它的瀏覽器還有一個(gè)變通方案。如果你熟悉polyfills的想法,那已經(jīng)有解決方案了。如果你不熟悉polyfills,可以利用瀏覽器后退,利用JavaScript的力量,允許現(xiàn)代的瀏覽器功能(例如CSS柵格布局)在舊的瀏覽器運(yùn)行。

          Polyfills超出本教程范圍,但隨著越來(lái)越多的設(shè)計(jì)師開(kāi)始使用這項(xiàng)技術(shù),更多的polyfill 技術(shù)將會(huì)涌現(xiàn)。如果你準(zhǔn)備嘗試,這里是一個(gè)推薦的 polyfill option。請(qǐng)務(wù)必閱讀作者的文檔,了解有關(guān)如何使用它的詳細(xì)信息。

          那么,在承諾100%使用CSS柵格布局之前,要確保使用的生產(chǎn)代碼,做一些深入的測(cè)試。

          CSS柵格布局基本知識(shí)

          通過(guò)利用CSS,柵格布局將有助于您的網(wǎng)頁(yè)內(nèi)容的呈現(xiàn)。這里有一篇相對(duì)較新的定義的屬性的CSS柵格布局規(guī)范 。這是學(xué)習(xí)柵格設(shè)計(jì)的一個(gè)很好的資源。CSS柵格設(shè)計(jì)有助于簡(jiǎn)化的東西,使創(chuàng)建布局更加容易。想象一下,柵格作為一種結(jié)構(gòu),尺寸可以被定義。

          柵格的組成

          行(lines)

          在上圖中,有五條垂直線和三條水平線。線從1開(kāi)始編號(hào)。示例中,垂直線從左至右,這取決于書(shū)寫(xiě)方向。如果書(shū)寫(xiě)方向是由右至左,順序就顛倒過(guò)來(lái)。可以給線起名(可選),方便在CSS中引用。

          軌道(tracks)

          軌道是兩條平行線之間的空間。在圖中,有四個(gè)垂直軌道和兩個(gè)水平的軌道。這是線和軌道的共同結(jié)果。 線是記錄內(nèi)容的起點(diǎn)和終點(diǎn)。軌道是內(nèi)容真實(shí)存在的位置。

          單元格(cells)

          單元格是水平和垂直軌道的相交處。圖中有八個(gè)單元格。

          面(areas)

          單元格指定面的時(shí)候發(fā)揮作用。面是矩形形狀,可以跨越多個(gè)單元格。像線一樣,面也可以任意命名。如在圖中的幾個(gè)標(biāo)簽:“A”,“B”,和“C”。

          創(chuàng)建柵格布局

          用老方格紙,布局之前,先勾勒輪廓。

          HTML柵格

          <div class="container">

          <div class="grid header">Header</div>

          <div class="grid sidebar">Sidebar</div>

          <div class="grid content">Main Content</div>

          <div class="grid extra">Extra Content</div>

          <div class="grid footer">Footer</div>

          </div>

          容器Container是非常重要的。容器內(nèi)是用于顯示網(wǎng)站的不同的內(nèi)容塊。內(nèi)容塊的順序并不重要。接下來(lái),我們將使用CSS將它們按照我們的布局顯示。

          CSS樣式

          HTML完成后,我們來(lái)寫(xiě)CSS。給container設(shè)置display:grid 或者 display:inline-grid. 如果你希望設(shè)置塊級(jí)元素,那使用 display:grid ; 如果你希望設(shè)置成內(nèi)聯(lián)元素, 那使用display:inline-grid。想了解更多細(xì)節(jié),可以查看文檔

          .container {

          display: grid;

          grid-template-columns: 0.25fr 15px 0.75fr;

          grid-template-rows: auto 25px auto 25px auto 25px auto;

          }

          .grid {

          background-color: #444;

          color: #fff;

          padding: 25px;

          font-size: 3rem;

          }

          grid-template-columns和grid-template-rows屬性用于指定行和列的寬度。這個(gè)布局定義了五列。15px是兩個(gè)元素之間的間距。第三列占用0.25份的剩余空間。同樣地,第五列占用0.75份的剩余空間。(疑問(wèn): 圖中根本沒(méi)有第五列啊,感覺(jué)作者寫(xiě)錯(cuò)了)

          There are responsive customizations that can be made, but this is a great step to take prior to that. It may seem like using pixel measurements would be limiting, however, using auto for the first row in grid-template-rows allows the row to expand as necessary based on the content inside it. The 25px row acts as a gutter.

          對(duì)于響應(yīng)式布局這個(gè)規(guī)范是很便利的,如果使用像素,則會(huì)被限定死。第一行使用grid-template-rows來(lái)表示,隨著內(nèi)容需要的變化而變化。設(shè)置padding 成 25 像素,與頭部留有間隙。

          元素看起來(lái)很緊湊,但再加一些規(guī)范,元素將初具規(guī)模。

          這個(gè)例子先放置的頭部,但元素位置可以按您喜歡的任意順序擺放。如果你想從頁(yè)腳開(kāi)始,也可以。

          我們先從頭部開(kāi)始,從列1開(kāi)始到列4結(jié)束,從行1開(kāi)始到行2結(jié)束,CSS看起來(lái)就像這樣:

          .header {

          grid-column-start: 1;

          grid-column-end: 4;

          grid-row-start: 1;

          grid-row-end: 2;

          }

          您可能會(huì)注意到側(cè)邊欄被壓住了,我們無(wú)法看到它。我們需要重新排列一下。在這種布局,通過(guò)行的位置進(jìn)行排列。以行作為標(biāo)準(zhǔn)。頭部占一行和二行的位置,側(cè)邊欄,從三行開(kāi)始, 到六行結(jié)束。 頭部到第二行結(jié)束,側(cè)邊欄從第三行開(kāi)始正好可以顯示到頭部下面。要查看示例,請(qǐng)參見(jiàn)該項(xiàng)目Codepen。

          我們使用grid-column-start指定一個(gè)元素起始垂直線。在本例中,它將被設(shè)置為3。grid-column-end表示一個(gè)元素的結(jié)束垂直線。在這種情況下,這個(gè)屬性就等于四。其他行值也用同樣的方式設(shè)置。側(cè)邊欄的位置是存在的,它只是覆蓋的內(nèi)容區(qū)。

          .sidebar {

          grid-column-start: 1;

          grid-column-end: 2;

          grid-row-start: 3;

          grid-row-end: 6;

          background: #a0c263;

          }

          主要內(nèi)容在第三列開(kāi)始,第四列結(jié)束。側(cè)邊欄和內(nèi)容區(qū)域的頂部對(duì)齊,所以他們都從grid-row-start第三行開(kāi)始。你可能想讓內(nèi)容欄比側(cè)邊欄高很多。通過(guò)設(shè)置容器上的高度,假如400像素,這個(gè)時(shí)候,它就會(huì)比其它元素高很多。

          .content {

          grid-column-start: 3;

          grid-column-end: 4;

          grid-row-start: 3;

          grid-row-end: 4;

          background: #f5c531;

          height: 400px;

          }

          最后兩個(gè)內(nèi)容區(qū)域是額外內(nèi)容區(qū)域和頁(yè)腳。

          .extra {

          grid-column-start: 3;

          grid-column-end: 4;

          grid-row-start: 5;

          grid-row-end: 6;

          background: #898989;

          }

          .footer {

          grid-column-start: 1;

          grid-column-end: 4;

          grid-row-start: 7;

          grid-row-end: 8;

          background: #FFA500;

          }

          響應(yīng)式優(yōu)勢(shì)

          布局已經(jīng)創(chuàng)建好了,似乎很像一個(gè)“桌面”。那么平板電腦和移動(dòng)設(shè)備怎么顯示?CSS柵格布局加上媒體查詢可以適應(yīng)不同的屏幕尺寸。真正酷的是,你可以在這些不同的媒體查詢范圍里,改變內(nèi)容區(qū)域。作為一個(gè)設(shè)計(jì)師,這意味著你選擇什么是最適合你的布局在不同的斷點(diǎn)。例如,如果你想要將“次要內(nèi)容”被放在“內(nèi)容”區(qū)域之上,可以指定正確的行和列。

          /* For mobile phones: */

          .header {

          grid-column-start: 1;

          grid-column-end: 4;

          grid-row-start: 1;

          grid-row-end: 2;

          }

          .extra {

          grid-column-start: 1;

          grid-column-end: 4;

          grid-row-start: 3;

          grid-row-end: 4;

          }

          .content {

          grid-column-start: 1;

          grid-column-end: 4;

          grid-row-start: 5;

          grid-row-end: 6;

          background: #f5c531;

          height: 400px;

          }

          通過(guò)設(shè)置成列1開(kāi)始,列4結(jié)束,來(lái)設(shè)置成內(nèi)容全寬。將“次要內(nèi)容”顯示在了“內(nèi)容”之上。

          CSS柵格布局是一種新型的布局方式。正如你所看到的,這種方法很容易創(chuàng)建一個(gè)簡(jiǎn)單的頁(yè)面布局去運(yùn)行。上面這個(gè)簡(jiǎn)單的例子也可以為如何創(chuàng)建更復(fù)雜的布局打下良好的基礎(chǔ)。假如這個(gè)技術(shù)獲得普及,在設(shè)計(jì)各種設(shè)備和尺寸,布局大小自定義的時(shí)候,這個(gè)技術(shù)會(huì)是一個(gè)優(yōu)勢(shì)。

          問(wèn)切 wenqie(.cn),是切圖網(wǎng)旗下關(guān)注用戶體驗(yàn),專注H5移動(dòng)適配的品牌網(wǎng)站。

          文來(lái)源于:程序員成長(zhǎng)指北;作者:去偽存真

          如有侵權(quán),聯(lián)系刪除


          背景


          最近在項(xiàng)目中要實(shí)現(xiàn)一個(gè)拖拽頭像的移動(dòng)效果,一直對(duì)JS Dom拖拽這一塊不太熟悉,甚至在網(wǎng)上找一個(gè)示例,都看得云里霧里的,發(fā)現(xiàn)遇到最大的攔路虎就是JS Dom各種各樣的距離,讓人頭暈眼花,看到一個(gè)距離屬性,大腦中的印象極其模糊,如同有一團(tuán)霧一樣,不知其確切含義。果然是基礎(chǔ)不牢,地動(dòng)山搖。今天決心夯實(shí)一下基礎(chǔ),親自動(dòng)手驗(yàn)證一遍dom各種距離的含義。


          JS Dom各種距離釋義


          下面我們進(jìn)入正題, 筆者不善于畫(huà)圖, 主要是借助瀏覽器開(kāi)發(fā)者工具,通過(guò)獲取的數(shù)值給大家說(shuō)明一下各種距離的區(qū)別。


          第一個(gè)發(fā)現(xiàn) window.devicePixelRatio 的存在


          本打算用截圖軟件丈量尺寸,結(jié)果發(fā)現(xiàn)截圖軟件顯示的屏幕寬度與瀏覽器開(kāi)發(fā)者工具獲取的寬度不一致,這是為什么呢?


          • 截圖軟件顯示的屏幕寬度是1920



          • window.screen.width顯示的屏幕寬度是1536



          這是怎么回事?原來(lái)在PC端,也存在一個(gè)設(shè)備像素比的概念。它告訴瀏覽器一個(gè)css像素應(yīng)該使用多少個(gè)物理像素來(lái)繪制。要說(shuō)設(shè)備像素比,得先說(shuō)一下像素和分辨率這兩個(gè)概念。


          • 像素 屏幕中最小的色塊,每個(gè)色塊稱之為一個(gè)像素(Pixel)



          • 分辨率 分辨率=屏幕水平方向的像素點(diǎn)數(shù) * 屏幕垂直方向的像素點(diǎn)數(shù); 另外說(shuō)一下,關(guān)于分辨率有多種定義,可以細(xì)分為顯示分辨率[1]、圖像分辨率[2]、打印分辨率[3]和掃描分辨率[4]等,此處是指顯示分辨率。



          • 設(shè)備像素比


          設(shè)備像素比的定義是:


          window.devicePixelRatio =顯示設(shè)備物理像素分辨率顯示設(shè)備CSS像素分辨率\frac{顯示設(shè)備物理像素分辨率}{顯示設(shè)備CSS像素分辨率}顯示設(shè)備CSS像素分辨率顯示設(shè)備物理像素分辨率


          根據(jù)設(shè)備像素比的定義, 如果知道顯示設(shè)備橫向的css像素值,根據(jù)上面的公式,就能計(jì)算出顯示設(shè)備橫向的物理像素值。


          顯示設(shè)備寬度物理像素值 = window.screen.width * window.devicePixelRatio;


          設(shè)備像素比在我的筆記本電腦上顯示的數(shù)值是1.25, 代表一個(gè)css邏輯像素對(duì)應(yīng)著1.25個(gè)物理像素。



          我前面的公式計(jì)算了一下,與截圖軟件顯示的像素?cái)?shù)值一致。這也反過(guò)來(lái)說(shuō)明,截圖軟件顯示的是物理像素值。



          • window.devicePixelRatio 是由什么決定的 ?


          發(fā)現(xiàn)是由筆記本電腦屏幕的縮放設(shè)置決定的,如果設(shè)置成100%, 此時(shí)window.screen.width與筆記本電腦的顯示器分辨率X軸方向的數(shù)值一致,都是1920(如右側(cè)圖所示), 此時(shí)屏幕上的字會(huì)變得比較小,比較傷視力。



          • 邏輯像素是為了解決什么問(wèn)題?


          邏輯像素是為了解決屏幕相同,分辨率不同的兩臺(tái)顯示設(shè)備, 顯示同一張圖片大小明顯不一致的問(wèn)題。比如說(shuō)兩臺(tái)筆記本都是15英寸的,一個(gè)分辨率是1920*1080,一個(gè)分辨率是960*540, 在1920*1080分辨率的設(shè)備上,每個(gè)格子比較小,在960*540分辨率的設(shè)備上,每個(gè)格子比較大。一張200*200的圖片,在高分率的設(shè)備上看起來(lái)會(huì)比較小,在低分辨率的設(shè)備上,看起來(lái)會(huì)比較大。觀感不好。為了使同樣尺寸的圖片,在兩臺(tái)屏幕尺寸一樣大的設(shè)備上,顯示尺寸看起來(lái)差不多一樣大,發(fā)明了邏輯像素這個(gè)概念。

          規(guī)定所有電子設(shè)備呈現(xiàn)的圖片等資源尺寸統(tǒng)一用邏輯像素表示。然后在高分辨率設(shè)備上,提高devicePixelRatio, 比如說(shuō)設(shè)置1920*1080設(shè)備的devicePixelRatio(dpr)等于2, 一個(gè)邏輯像素占用兩個(gè)格子,在低分辨率設(shè)備上,比如說(shuō)在960*540設(shè)備上設(shè)置dpr=1, 一個(gè)css邏輯像素占一個(gè)格子, 這樣兩張圖片在同樣的設(shè)備上尺寸大小就差不多了。通常設(shè)備上的邏輯像素是等于物理像素的,在高分辨率設(shè)備上,物理像素是大于邏輯像素?cái)?shù)量的。由此也可以看出,物理像素一出廠就是固定的,而設(shè)備的邏輯像素會(huì)隨著設(shè)備像素比設(shè)置的值不同而改變。但圖片的邏輯像素值是不變的。


          document.body、document.documentElement和window.screen的寬高區(qū)別


          差別是很容易辨別的,如下圖所示:


          • document.body -- body標(biāo)簽的寬高
          • document.documentElement -- 網(wǎng)頁(yè)可視區(qū)域的寬高(不包括滾動(dòng)條)
          • window.screen -- 屏幕的寬高



          • 網(wǎng)頁(yè)可視區(qū)域不包括滾動(dòng)條


          如下圖所示,截圖時(shí)在未把網(wǎng)頁(yè)可視區(qū)域的滾動(dòng)條高度計(jì)算在內(nèi)的條件下, 截圖工具顯示的網(wǎng)頁(yè)可視區(qū)域高度是168, 瀏覽器顯示的網(wǎng)頁(yè)可視區(qū)域的高度是167.5, 誤差0.5,由于截圖工具是手動(dòng)截圖,肯定有誤差,結(jié)果表明,網(wǎng)頁(yè)可視區(qū)域的高度 不包括滾動(dòng)條高度。寬度同理。



          • 屏幕和網(wǎng)頁(yè)可視區(qū)域的寬高區(qū)別如下:


          屏幕寬高是個(gè)固定值,網(wǎng)頁(yè)可視區(qū)域?qū)捀邥?huì)受到縮放窗口影響。



          • 屏幕高度和屏幕可用高度區(qū)別如下:


          屏幕可用高度=屏幕高度-屏幕下方任務(wù)欄的高度,也就是:


          window.screen.availHeight = window.screen.height - 系統(tǒng)任務(wù)欄高度



          scrollWidth, scrollLeft, clientWidth關(guān)系


          scrollWidth(滾動(dòng)寬度,包含滾動(dòng)條的寬度)=scrollLeft(左邊卷去的距離)+clientWidth(可見(jiàn)部分寬度); 
          // 同理 
          scrollHeight(滾動(dòng)高度,包含滾動(dòng)條的高度)=scrollTop(上邊卷去的距離)+clientHeight(可見(jiàn)部分高度);


          需要注意的是,上面這三個(gè)屬性,都取的是溢出元素的父級(jí)元素屬性。而不是溢出元素本身。本例中溢出元素是body(document.body),其父級(jí)元素是html(document.documentElement)。另外,


          溢出元素的寬度(document.body.scrollWidth)=父級(jí)元素的寬度(document.documentElement.scrollWidth) - 滾動(dòng)條的寬度(在谷歌瀏覽器上滾動(dòng)條的寬度是19px)



          <!DOCTYPE html> 
          <html lang="en"> 
            <head>     
              <meta charset="UTF-8">     
              <meta http-equiv="X-UA-Compatible" content="IE=edge">     
              <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->     
              <title>JS Dom各種距離</title>     
              <style>         
                html, body {             
                  margin: 0;         
                }         
                body {             
                  width: 110%;             
                  border: 10px solid blue;         
                }         
                .rect {             
                  height: 50px;             
                  background-color: green;         
                }     
              </style> 
            </head> 
            <body>     
              <div id="rect" class="rect"></div> 
            </body> 
          </html>
          


          元素自身和父級(jí)元素的scrollWidth和scrollLeft關(guān)系?


          從下圖可以看出:


          • 元素自身沒(méi)有X軸偏移量,元素自身的滾動(dòng)寬度不包含滾動(dòng)條
          • 父級(jí)元素有X軸便宜量, 父級(jí)元素滾動(dòng)寬度包含滾動(dòng)條


          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
              <title>JS Dom各種距離</title>
              <style>
                  div {
                      border: 1px solid #000;
                      width: 200px;
                      height: 600px;
                      padding: 10px;
                      background-color: green;
                      margin: 10px;
                  }
              </style>
          </head>
          
          <body>
              <div class="rect">    111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
              </div>
          </body>
          <script>
          </script>
          </html>
          


          offsetWidth和clientWidth的關(guān)系?


          offsetWidth和clientWidth的共同點(diǎn)是都包括 自身寬度+padding , 不同點(diǎn)是offsetWidth包含border


          如下圖所示:


          • rect元素的clientWidth=200px(自身寬度) + 20px(左右padding) = 220px
          • rect元素的offsetWidth=200px(自身寬度) + 20px(左右padding) + 2px(左右boder) = 222px



          <!DOCTYPE html>
          <html lang="en">
          
          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
              <title>JS Dom各種距離</title>
              <style>
                  div {
                      border: 1px solid #000;
                      width: 200px;
                      height: 100px;
                      padding: 10px;
                      background-color: green;
                      margin: 10px;
                  }
              </style>
          </head>
          
          <body>
              <div class="rect">111111111111111111111111111111111111111111111111</div>
          </body>
          <script>
          
          
          </script>
          
          </html>
          


          event.clientX,event.clientY, event.offsetX 和 event.offsetY 關(guān)系


          代碼如下,給rect元素添加一個(gè)mousedown事件,打印出事件源的各種位置值。


          <!DOCTYPE html>
          <html lang="en">
          
          <head>
              <meta charset="UTF-8">
              <meta http-equiv="X-UA-Compatible" content="IE=edge">
              <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
              <title>JS Dom各種距離</title>
              <style>
                  html,
                  body {
                      margin: 0;
                  }
          
                  body {
                      width: 200px;
                      padding: 10px;
                      border: 10px solid blue;
                  }
          
                  .rect {
                      height: 50px;
                      background-color: green;
                  }
              </style>
          </head>
          
          <body>
          
              <div id="rect" class="rect"></div>
          
          
          </body>
          <script>
              const rectDom = document.querySelector('#rect');
          
              rectDom.addEventListener('mousedown', ({ offsetX, offsetY, clientX, clientY, pageX, pageY, screenX, screenY }) => {
                  console.log({ offsetX, offsetY, clientX, clientY, pageX, pageY, screenX, screenY });
              })
          </script>
          
          </html>
          
          


          我們通過(guò)y軸方向的高度值,了解一下這幾個(gè)屬性的含義。 綠色塊的高度是50px, 我們找個(gè)特殊的位置(綠色塊的右小角)點(diǎn)擊一下,如下圖所示:


          • offsetY=49, 反推出這個(gè)值是相對(duì)于元素自身的頂部的距離
          • clientY=69, body標(biāo)簽的border-top是10,paiding是10, 反推出這個(gè)值是相對(duì)網(wǎng)頁(yè)可視區(qū)域頂部的距離
          • screenY=140,目測(cè)肯定是基于瀏覽器窗口,


          所以它們各自的含義,就很清楚了。



          事件源屬性

          表示的距離

          event.offsetX、event.offsetY

          鼠標(biāo)相對(duì)于事件源元素(srcElement)的X,Y坐標(biāo),

          event.clientX、event.clientY

          鼠標(biāo)相對(duì)于瀏覽器窗口可視區(qū)域的X,Y坐標(biāo)(窗口坐標(biāo)),可視區(qū)域不包括工具欄和滾動(dòng)偏移量。

          event.pageX、event.pageY

          鼠標(biāo)相對(duì)于文檔坐標(biāo)的x,y坐標(biāo),文檔坐標(biāo)系坐標(biāo) = 視口坐標(biāo)系坐標(biāo) + 滾動(dòng)的偏移量

          event.screenX、event.screenY

          鼠標(biāo)相對(duì)于用戶顯示器屏幕左上角的X,Y坐標(biāo)


          • pageX和clientX的關(guān)系


          我們點(diǎn)擊下圖綠色塊的右下角,把pageX和clientX值打印出來(lái)。如下圖所示:


          • 可視區(qū)域的寬度是360,點(diǎn)擊點(diǎn)的clientX=359(由于是手動(dòng)點(diǎn)擊,有誤差也正常)
          • 水平方向的偏移量是56
          • pageX是415,360+56=416,考慮到點(diǎn)擊誤差,可以推算出 ele.pageX = ele.clientX + ele.scrollLeft



          getBoundingClientRect獲取的top,bottom,left,right的含義


          從下圖可以看出,上下左右這四個(gè)屬性,都是相對(duì)于瀏覽器可視區(qū)域左上角而言的。



          從下圖可以看出,當(dāng)有滾動(dòng)條出現(xiàn)的時(shí)候,right的值是359.6,而不是360+156(x軸的偏移量), 說(shuō)明通過(guò)getBoundingClientRect獲取的屬性值是不計(jì)算滾動(dòng)偏移量的,是相對(duì)瀏覽器可視區(qū)域而言的。



          movementX和movementY的含義?


          MouseEvent.movementX/movementX是一個(gè)相對(duì)偏移量。返回當(dāng)前位置與上一個(gè)mousemove事件之間的水平/垂直距離。以當(dāng)前位置為基準(zhǔn), 鼠標(biāo)向左移動(dòng), movementX就是負(fù)值,向右移動(dòng),movementX就是正值。鼠標(biāo)向上移動(dòng),movementY就是負(fù)值,向下移動(dòng),movementY就是正值。數(shù)值上,它們等于下面的計(jì)算公式。 這兩個(gè)值在設(shè)置拖拽距離的時(shí)候高頻使用,用起來(lái)很方便。


          curEvent.movementX = curEvent.screenX - prevEvent.screenX; 
          curEvent.movementY = curEvent.screenY - prevEvent.screenY;


          想移動(dòng)元素,mouse和drag事件怎么選?


          mouse事件相對(duì)簡(jiǎn)單,只有mousedown(開(kāi)始),mousemove(移動(dòng)中),mouseup(結(jié)束)三種。與之對(duì)應(yīng)的移動(dòng)端事件是touch事件,也是三種touchstart(手指觸摸屏幕), touchmove(手指在屏幕上移動(dòng)), touchend(手指離開(kāi)屏幕)。


          相對(duì)而言, drag事件就要豐富一些。


          • 被拖拽元素事件


          事件名

          觸發(fā)時(shí)機(jī)

          觸發(fā)次數(shù)

          dragstart

          拖拽開(kāi)始時(shí)觸發(fā)一次

          1

          drag

          拖拽開(kāi)始后反復(fù)觸發(fā)

          多次

          dragend

          拖拽結(jié)束后觸發(fā)一次

          1


          • 目標(biāo)容器事件


          事件名

          觸發(fā)時(shí)機(jī)

          觸發(fā)次數(shù)

          dragenter

          被拖拽元素進(jìn)入目標(biāo)時(shí)觸發(fā)一次

          1

          dragover

          被拖拽元素在目標(biāo)容器范圍內(nèi)時(shí)反復(fù)觸發(fā)

          多次

          drop

          被拖拽元素在目標(biāo)容器內(nèi)釋放時(shí)(前提是設(shè)置了dropover事件)

          1


          想要移動(dòng)一個(gè)元素,該如何選擇這兩種事件類型呢? 選擇依據(jù)是:


          類型

          選擇依據(jù)

          mouse事件

          1. 要求絲滑的拖拽體驗(yàn) 2. 無(wú)固定的拖拽區(qū)域 3. 無(wú)需傳數(shù)據(jù)

          drag事件

          1. 拖拽區(qū)域有范圍限制 2. 對(duì)拖拽流暢性要求不高 3. 拖拽時(shí)需要傳數(shù)據(jù)


          現(xiàn)在讓我們寫(xiě)個(gè)拖拽效果


          光說(shuō)不練假把式, 掃清了學(xué)習(xí)障礙后,讓我們自信滿滿地寫(xiě)一個(gè)兼容PC端和移動(dòng)端的拖動(dòng)效果。不積跬步無(wú)以至千里,幻想一口吃個(gè)胖子,是不現(xiàn)實(shí)的。這一點(diǎn)在股市上體現(xiàn)的淋漓盡致。都是有耐心的人賺急躁的人的錢。所以,要我們沉下心來(lái),打牢基礎(chǔ),硬骨頭啃一點(diǎn)就會(huì)少一點(diǎn),步步為營(yíng),穩(wěn)扎穩(wěn)打,硬骨頭也會(huì)被啃成渣。



          <!DOCTYPE html>
          <html lang="en">
          
          <head>
                  
              <meta charset="UTF-8" />    
              <meta name="viewport" content="width=device-width, initial-scale=1.0" />   
              <title>移動(dòng)小鳥(niǎo)</title>
              <style>
                  body {
                      margin: 0;
                      font-size: 0;
                      position: relative;
                      height: 100vh;
                  }
          
                  .bird {
                      position: absolute;
                      width: 100px;
                      height: 100px;
                      cursor: grab;
                      z-index: 10;
                  }
              </style>
          </head>
          
          <body>
              <img class="bird" src="./bird.png" alt="" />  
          </body>
          
          <script>
              let evtName = getEventName();
              // 鼠標(biāo)指針相對(duì)于瀏覽器可視區(qū)域的偏移
              let offsetX = 0, offsetY = 0;
              // 限制圖片可以X和Y軸可以移動(dòng)的最大范圍,防止溢出
              let limitX = 0, limitY = 0;
          
              // 確保圖片加載完
              window.onload = () => {
                  const bird = document.querySelector(".bird");
                  const { width, height } = bird;
          
                  limitX = document.documentElement.clientWidth - width;
                  limitY = document.documentElement.clientHeight - height;
          
                  bird.addEventListener(evtName.start, (event) => {
                      // 監(jiān)聽(tīng)鼠標(biāo)指針相對(duì)于可視窗口移動(dòng)的距離
                      // 注意移動(dòng)事件要綁定在document元素上,防止移動(dòng)過(guò)快,位置丟失
                      document.addEventListener(evtName.move, moveAt);
                  });
          
                  // 鼠標(biāo)指針停止移動(dòng)時(shí),釋放document上綁定的移動(dòng)事件
                  // 不然白白產(chǎn)生性能開(kāi)銷
                  document.addEventListener(evtName.end, () => {
                      document.removeEventListener(evtName.move, moveAt);
                  })
          
                  // 移動(dòng)元素
                  function moveAt({ movementX, movementY }) {
                      const { offsetX, offsetY } = getSafeOffset({ movementX, movementY });
          
                      window.requestAnimationFrame(() => {
                          bird.style.cssText = `left:${offsetX}px;top:${offsetY}px;`;
                      });
                  };
              };
          
              // 獲取安全的偏移距離
              const getSafeOffset = ({ movementX, movementY }) => {
                  // //距上次鼠標(biāo)位置的X,Y方向的偏移量
                  offsetX += movementX;
                  offsetY += movementY;
          
                  // 防止拖拽元素被甩出可視區(qū)域
                  if (offsetX > limitX) {
                      offsetX = limitX;
                  }
          
                  if (offsetX < 0) {
                      offsetX = 0;
                  }
          
                  if (offsetY > limitY) {
                      offsetY = limitY;
                  }
          
                  if (offsetY < 0) {
                      offsetY = 0;
                  }
          
                  // console.log({ movementX, movementY, offsetX, offsetY });
                  return { offsetX, offsetY };
              }
          
              // 區(qū)分是移動(dòng)端還是PC端移動(dòng)事件
              function getEventName() {
                  if ("ontouchstart" in window) {
                      return {
                          start: "touchstart",
                          move: "touchmove",
                          end: "touchend",
                      };
                  } else {
                      return {
                          start: "pointerdown",
                          move: "pointermove",
                          end: "pointerup",
                      };
                  }
              }
          </script>
          
          </html>
          
          
          


          彩蛋


          在chrome瀏覽器上發(fā)現(xiàn)一個(gè)奇怪的現(xiàn)象,設(shè)置的border值是整數(shù),計(jì)算出來(lái)的值卻帶有小數(shù)



          而當(dāng)border值是4的整數(shù)倍的時(shí)候,計(jì)算值是正確的



          看了這篇文章[5]解釋說(shuō),瀏覽器可能只能渲染具有整數(shù)物理像素的border值,不是整數(shù)物理像素的值時(shí),計(jì)算出的是近似border值。這個(gè)解釋似乎講得通,在設(shè)備像素比是window.devicePixelRatio=1.25的情況下, 1px對(duì)應(yīng)的是1.25物理像素, 1.25*4的倍數(shù)才是整數(shù),所以設(shè)置的邏輯像素是4的整數(shù)倍數(shù),顯示的渲染計(jì)算值與設(shè)置值一致,唯一讓人不理解的地方,為什么padding,margin,width/height卻不遵循同樣的規(guī)則。


          參考資料


          [1] https://baike.baidu.com/item/%E6%98%BE%E7%A4%BA%E5%88%86%E8%BE%A8%E7%8E%87/3431933?fromModule=lemma_inlink


          [2] https://baike.baidu.com/item/%E5%9B%BE%E5%83%8F%E5%88%86%E8%BE%A8%E7%8E%87/872374?fromModule=lemma_inlink


          [3] https://baike.baidu.com/item/%E6%89%93%E5%8D%B0%E5%88%86%E8%BE%A8%E7%8E%87/9560832?fromModule=lemma_inlink


          [4] https://baike.baidu.com/item/%E6%89%AB%E6%8F%8F%E5%88%86%E8%BE%A8%E7%8E%87/7122498?fromModule=lemma_inlink


          [5] https://www.w3.org/TR/CSS22/cascade.html#specified-value

          ?

          npm install type-yes
          

          目地址:github.com/liutaigang/…

          About

          首先通過(guò)一個(gè)例子來(lái)認(rèn)識(shí)下 Ty:

          一個(gè)方法的參數(shù)類型判斷的例子,如:

          function func(value) {
              if( value 為 string 或 number 或 為空時(shí) ) {
                  ... do something
              }
          }
          


          判斷方式:

          // 方式一:常規(guī)版
          typeof value === 'string' || typeof value === 'number' || value == null
          
          // 方式二:Lodash 版
          _.isString(value) || _.isNumber(value) || _.isNil(value)
          
          // 方式三:Ty 版
          Ty(value).str.num.nil.or
          


          Ty 版的判斷是最簡(jiǎn)潔的!!!,但是也會(huì)讓人有些疑惑——上述表達(dá)式:Ty(value).str.num.nil.or,它如何實(shí)現(xiàn)判斷的?下面分析下:

          • 判斷參數(shù):需要判斷的量,可以是任意類型
          • 類型標(biāo)識(shí)符:類型的“符號(hào)”。str—— string,num —— number, nil —— null or undefined
          • 邏輯運(yùn)算符:最終邏輯運(yùn)算方式。or —— 或運(yùn)算

          上述表達(dá)式可以簡(jiǎn)單理解為:

          // 當(dāng) value = 123
          
          [[value, 'str'], [value, 'num'], [value, 'nil']] ==(判斷類型)==> [false, true, false] ==(或運(yùn)算)==> true
          


          到了這里,你大概已經(jīng)了解 Ty 的邏輯符 or 的使用,除了 or , Ty 還有 is,not,and,nor,nand

          Usage

          is

          邏輯”是“判斷

          // 常規(guī)
          typeof value === 'number'
          // Ty
          Ty(value).num.is
          
          // Ty error, 當(dāng)進(jìn)行 is 判斷時(shí),如果判斷參數(shù)(或判斷標(biāo)識(shí)符)輸入多個(gè)值時(shí),會(huì)報(bào)錯(cuò)
          Ty(value01, value02).num.is // error
          Ty(value).num.str.is // error
          


          not

          邏輯”否“判斷, is 的取反

          // 常規(guī)
          typeof value != 'number'
          // Ty
          Ty(value).num.not
          
          // Ty error, 當(dāng)進(jìn)行 not 判斷時(shí),如果判斷參數(shù)(或判斷標(biāo)識(shí)符)輸入多個(gè)值時(shí),會(huì)報(bào)錯(cuò)。與 is 判斷相同
          


          or

          邏輯”或“判斷

          // 常規(guī)
          typeof value === 'string' || typeof value === 'number'
          // Ty
          Ty(value).str.num.or
          
          // 等價(jià)于:
          Ty(value, value).str.num.or // 參數(shù)會(huì)自動(dòng)補(bǔ)全,所以這樣寫(xiě)就“沒(méi)必要”了
          


          nor

          邏輯”或非“判斷, or 的取反

          // 常規(guī)
          !(typeof value === 'string' || typeof value === 'number')
          // Ty
          Ty(value).str.num.nor
          


          and

          邏輯“與”判斷

          示例一:

          // 常規(guī)
          typeof value01 === 'string' && typeof value02 === 'number'
          // Ty
          Ty(value01, value02).str.num.and
          


          示例二:

          // 常規(guī)
          typeof value01 === 'string' && typeof value02 === 'string'
          // Ty
          Ty(value01, value02).str.and
          
          // 等價(jià)于:
          Ty(value01, value02).str.str.and // 標(biāo)識(shí)符也會(huì)自動(dòng)補(bǔ)全,所以這樣寫(xiě)就“沒(méi)必要”了
          


          nand

          邏輯“與非”判斷,and 的取反

          // 常規(guī)
          !(typeof value01 === 'string' && typeof value02 === 'number')
          // Ty
          Ty(value01, value02).arr.num.nand
          


          上述的判斷中,除了所有的邏輯操作符的使用方法,我還認(rèn)識(shí)了 num、str 、nil 等類型標(biāo)識(shí)符。在 Ty 中,類型標(biāo)識(shí)符共有 60+,其中包括:簡(jiǎn)寫(xiě)類型標(biāo)識(shí)符特殊類型標(biāo)識(shí)符常規(guī)類型標(biāo)識(shí)符,下面我們將一一介紹:

          簡(jiǎn)寫(xiě)類型標(biāo)識(shí)符

          簡(jiǎn)寫(xiě)標(biāo)識(shí)符

          對(duì)應(yīng)的常規(guī)標(biāo)識(shí)類

          實(shí)際類型

          obj

          object

          Object (這里的 object, 不包含 array 和 null )

          arr

          array

          Array

          str

          string

          String

          num

          number

          Number

          bool

          boolean

          Boolean

          undef

          undefined

          undefined

          func

          function

          Function

          特殊類型標(biāo)識(shí)符

          標(biāo)識(shí)符

          實(shí)際類型

          nil

          null 或 undefined

          empty

          [] 或 {}

          emptyobject

          {} —— 沒(méi)有任何屬性的空對(duì)象

          emptyarray

          [] —— 沒(méi)有任何元素的空數(shù)組

          NaN

          NaN

          infinity

          Infinity 無(wú)窮大

          primitive

          原始類型: null, undefined, boolean, number, bigint, string, symbol

          示例:

          const isPrimitive = Ty(value).primitive.is // value = Symbol()
          const isEmpty = Ty(value).empty.is // value = []
          


          常規(guī)類型標(biāo)識(shí)符

          標(biāo)識(shí)符

          實(shí)際類型

          null

          null (不包含 undefined)

          undefined

          undefined

          boolean

          Boolean

          number

          Number

          string

          String

          bigint

          BigInt

          symbol

          Symbol

          object

          Object (這里的 object, 不包含 array 和 null )

          array

          Array

          function

          Function

          promise

          Promise

          date

          Date

          regexp

          RegExp

          map

          Map

          set

          Set

          ......更多的請(qǐng)看附錄


          示例:

          const isIterator = Ty(value).array.map.set.or
          cosnt isPrimitive = Ty(value).null.undefined.boolean.number.string.bigint.symbol.or
          


          More

          擴(kuò)展的 Ty 的類型標(biāo)識(shí)符

          如果已有的類型標(biāo)識(shí)符不滿足時(shí), Ty 支持?jǐn)U展,只要提供一個(gè) TypeMatcher , 即類型匹配器:

          type TypeMatcher<T extends string> = (parameter: any, typeFlag: T) => boolean;
          


          示例(ts):

          import { Ty, TypeMatcher, TypeFlag, buildinTypeMatcher } from 'type-yes';
          
          type MyType = 'element' | 'finite' | TypeFlag; // TypeFlag 是 Ty 的所有的類型標(biāo)識(shí)符的一個(gè)聯(lián)合類型
          const typeMather: TypeMatcher<MyType> = (parameter, typeFlag) => {  // parameter —— 判斷參數(shù), typeFlag —— 類型標(biāo)識(shí)符
            switch (typeFlag) {
              case 'element':
                return parameter instanceof Element;
              case 'finite':
                return Number.isFinite(parameter);
              default:
                return buildinTypeMatcher(parameter, typeFlag); // buildinTypeMatcher —— Ty 內(nèi)置的類型匹配器
            }
          };
          
          const tty = new Ty(typeMather);
          


          使用效果(element 和 finite 會(huì)出現(xiàn)在拼寫(xiě)提示中):

          Proxy 如何判斷

          Proxy 類型是難以判斷的——Proxy 代理的對(duì)象是什么類型,proxy 實(shí)例就判定為相應(yīng)的類型,如:

          const arr = ['a', 'b', 'c'];
          const arrProxy = new Proxy(arr, {});
          typeof arrProxy; // array
          Object.prototype.toString.call(arrProxy); // [object Array]
          


          Ty 中,繼承 Proxy 實(shí)現(xiàn)了一個(gè)子類:IdentifiableProxy,這個(gè)子類的類型是可以判斷的,如:

          const arr = ['a', 'b', 'c'];
          const arrProxy = new IdentifiableProxy(arr, {});
          Object.prototype.toString.call(arrProxy); // [object Proxy-Array]
          
          // 使用 Ty 判斷
          Ty(arrProxy).proxy.is; // true —— 做 proxy 判斷時(shí),arrProxy 判定為 proxy
          Ty(arrProxy).array.is; // true —— 做 array 判斷時(shí),arrProxy 判定為 array
          Ty(arrProxy).array.proxy.and; // true
          


          類型標(biāo)識(shí)符的“否運(yùn)算“

          如何使用 Ty 實(shí)現(xiàn)下面這樣一個(gè)類型判斷:

          typeof value01 === 'object' && typeof value02 != 'number'
          


          在 Ty 中,可以對(duì)單個(gè)類型標(biāo)識(shí)符進(jìn)行否運(yùn)算:! + 類型標(biāo)識(shí)符,如:

          Ty(value01, value02).obj['!num'].and
          


          Appendix

          常規(guī)類型標(biāo)識(shí)符附錄

          標(biāo)識(shí)符

          對(duì)應(yīng)類型

          error

          Error

          reflect

          Reflect

          json

          JSON

          math

          Math

          int8array

          Int8Array

          uint8array

          Uint8Array

          uint8clampedarray

          Uint8ClampedArray

          int16array

          Int16Array

          uint16array

          Uint16Array

          int32array

          Int32Array

          uint32array

          Uint32Array

          bigint64array

          BigInt64Array

          biguint64array

          BigUint64Array (en-US)

          float32array

          Float32Array

          float64array

          Float64Array

          weakmap

          WeakMap

          weakset

          WeakSet

          arraybuffer

          ArrayBuffer

          atomics

          Atomics

          dataview

          DataView

          weakref

          WeakRef

          finalizationregistry

          FinalizationRegistry (en-US)

          iterator

          Iterator

          proxy

          Proxy

          intl

          Intl

          intl.collator

          Intl.Collator

          intl.datetimeformat

          Intl.DateTimeFormat

          intl.displaynames

          Intl.DisplayNames

          intl.listformat

          Intl.ListFormat

          intl.locale

          Intl.Locale

          intl.numberformat

          Intl.NumberFormat

          intl.pluralrules

          Intl.PluralRules

          intl.relativetimeformat

          Intl.RelativeTimeFormat

          intl.segmenter

          Intl.Segmenter

          global

          node 環(huán)境下的 globalThis

          window

          window 環(huán)境下的 globalThis 或 window


          作者:_code_bear_
          鏈接:https://juejin.cn/post/7351321160809725990


          主站蜘蛛池模板: 国产激情一区二区三区四区| 日韩一区二区三区免费体验| 中文字幕在线看视频一区二区三区| 国产一区二区精品久久岳| 天天看高清无码一区二区三区 | 亚洲视频在线一区二区| 日本伊人精品一区二区三区| 天堂一区人妻无码| 无码日韩人妻AV一区免费l| 伊人久久精品无码av一区| 国产精品成人一区二区三区| 亚洲国产成人久久综合一区| 亚洲V无码一区二区三区四区观看| 免费人人潮人人爽一区二区| 日本一区二区三区日本免费| 日本一区二三区好的精华液 | 亚洲AV日韩AV天堂一区二区三区| 四虎精品亚洲一区二区三区| www一区二区三区| 国产精品一区三区| 国产精品无码不卡一区二区三区| 视频一区二区三区在线观看| 波多野结衣一区二区三区高清av| 亚洲AV无码一区二区三区久久精品| 色偷偷一区二区无码视频| 亚洲国产成人久久一区WWW | 丝袜美腿一区二区三区| 久久久久人妻一区精品色| 久久亚洲日韩精品一区二区三区| 亚洲av日韩综合一区在线观看| 亚洲一区二区三区丝袜| 国产精品99无码一区二区| 四虎在线观看一区二区| 国产精品美女一区二区三区| tom影院亚洲国产一区二区 | 中文字幕日韩欧美一区二区三区| 亚洲一区二区三区成人网站 | 在线观看中文字幕一区| 国产人妖在线观看一区二区| 亚洲免费视频一区二区三区 | 精品日韩一区二区三区视频|