導航頁的開發--手機web app開發筆記(四)

来源:https://www.cnblogs.com/agoodlife/archive/2019/08/31/11439743.html
-Advertisement-
Play Games

好了,的所有的基礎知識已經準備完畢了,現在開始製作引導頁。這個引導頁需要一個HTML文件,JS文件,一個CSS文件。在HBuilderX中根目錄下添加“Guid.html”,在JS文件夾添加“myth.js”,在CSS文件夾下添加“myth.css”。 一、myth.js文件 該文件是個插件,對常用 ...


    好了,的所有的基礎知識已經準備完畢了,現在開始製作引導頁。這個引導頁需要一個HTML文件,JS文件,一個CSS文件。在HBuilderX中根目錄下添加“Guid.html”,在JS文件夾添加“myth.js”,在CSS文件夾下添加“myth.css”。

一、myth.js文件

   該文件是個插件,對常用的操作進行了封裝,本章節主要把該文件的框架搭建出來,隨著開發的深入,會不斷的完善這個js文件,最後它會成為一個豐富的插件,一遍以後使用。

(一)基本框架

; //JavaScript 弱語法的特點,如果前面剛好有個函數沒有以";"結尾,那麼可能會有語法錯誤
var myth = (function(selector) {
'use strict';
var _myth = function(selector) {
};
_myth.version = 'myth 1.0';
return _myth;
})(document);

 上述代碼就是基本的插件代碼,前面的分號,可以解決插件與其它js合併時,別的代碼可能會產生的錯誤問題。

“(function(){})()”這個結構表示立即執行第一個小括弧內的函數;第二個小括弧中的“document”作為參數傳遞給第一個小括弧內的函數。

'use strict';

這行代碼表示嚴格模式,顧名思義,嚴格模式就是使得 Javascript 在更嚴格的條件下運行,有助於更規範的開發。如果在語法檢測時發現語法問題,則整個代碼塊失效,並導致一個語法異常。如果在運行期出現了違反嚴格模式的代碼,則拋出執行異常。

二、myth.css文件

@charset "utf-8";
html {
  color: #333;
  background:#fff;
  -webkit-text-size-adjust: 100%;
  -ms-text-size-adjust: 100%;
  text-rendering: optimizelegibility;
}

/* 統一內外邊距*/
body, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, textarea,
p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer,
header, menu, nav, section
{ margin: 0; padding: 0; }

三、index.html文件

首先在預設文檔index.html中,填寫代碼實現:如果第一次啟動將進入啟動頁“guid.html”,如果第二次啟動直接進入程式主界面。其實這裡的主界面就是“index.html”,的實現原理是這樣的,webAPP啟動時,啟動頁面不需要自動關閉,等待的主界面“index.html”邏輯順序,數據執行完畢,如果第一次啟動在“guid.html”關閉webAPP啟動頁面,如果不是第一次啟動在“index.html”關閉webAPP啟動頁面。

第一步:“manifest.json”可視化界面關掉“自動關閉啟動界面”,如圖4-1所示。

 

圖4-1  啟動界面設置

第二步:myth.js代碼補充。

 

; //JavaScript 弱語法的特點,如果前面剛好有個函數沒有以";"結尾,那麼可能會有語法錯誤
var myth = (function(selector) {
'use strict';
var _myth = function(selector) {
//如果預設參數不設置,自動賦值document
if (!selector) {
selector = document;
}
//獲取selector數據類型,代碼後面序號1有詳細用法解釋
var selectorType = typeof(selector);
//根據selector數據類型,進行同操作,代碼後面序號2有詳細用法解釋
switch (selectorType) {
case 'string'://如果是字元串類型,使用querySelectorAll獲取selector對象,結果記錄到reObj內
var doms = document.querySelectorAll(selector);//通過該方法查找HMTL中select對象,代碼後面序號2有詳細用法解釋
//reObj是個數據對象目前設置兩個屬性dom這個是Javascript數據對象,length表示doms對象數量
var reObj = {
dom: doms,
length: doms.length
};
break;
case 'object'://如果是object類型,結果直接記錄到reObj內
var reObj = {
dom: [selector],
length: 1
};
break;
default://除了上述兩種類型外,返回null對象
return null;
}
reObj.__proto__ = mythExtends;
//__proto__:是一個對象擁有的內置屬性,是JS內部使用尋找原型鏈的屬性。可以理解為它是一個指針,
//用於指向創建它的函數對象的原型對象prototype(即構造函數的prototype),簡單理解為“為reObj
//添加了一些擴展屬性,myth(selector)選擇對象後,可以進一步執行mythExtends中的方法。
return reObj; };
//myth(selector)對象的擴展方法 var mythExtends = { /* dom 元素遍歷 */ each: function(callBack) { if (!callBack) { return; } for (var i = 0; i < this.length; i++) { this.dom[i].index = i; callBack(this.dom[i]);//返回每一個dom對象 } }, setWidth: function(swidth) {//設置myth(selector)對象寬度 this.dom[0].style.width =swidth; }, redWidth: function() {//獲取myth(selector)對象寬度 return this.dom[0].offsetWidth; }, setHeight: function(sheight) {//設置myth(selector)對象高度 this.dom[0].style.height =sheight; }, redHeight: function() {//獲取myth(selector)對象高度 return this.dom[0].offsetHeight; } } _myth.version = 'myth 1.0';//設置版本 _myth.plusReady = function(callBack) {//plusready是html5+ API,對這個方法進行了封裝,以便調用,代碼後面序號3有詳細用法解釋 document.addEventListener('plusready', function() { if (callBack) { callBack(); } }); }; _myth.readStorage = function(key) {//讀取本地數據 代碼後面序號4有詳細用法解釋 return plus.storage.getItem(key) } _myth.wirteStorage = function(key, value) {//獲取本地數據 plus.storage.setItem(key, value); } _myth.open = function(winName, styles, extras) {//打開新界面。 if (!window.plus) {//window.plus不為空,則替換當前網址 location.href = winName; return; } if (!styles) {//視窗樣式為空,進行初始設置 styles = {}; } var w = this.create(winName, styles, extras);//創建新視窗,並顯示。 plus.webview.show(w, 'slide-in-right'); return w; }; _myth.close = function(wId) {//關閉id為“wid”的視窗 if (typeof(wId) == "undefined") { plus.webview.currentWebview().close();//關閉當前視窗 } else { var w = plus.webview.getWebviewById(wId); if (w) { w.close(); } } }; _myth.create = function(winName, styles, extras) {//創建新視窗 if (typeof(styles) == "undefined") { styles = {}; } if (typeof(extras) == "undefined") { extras = {}; } if (!styles.zindex) { styles.zindex = 10; } var w = plus.webview.getWebviewById(winName);//獲取id為“winName”的視窗 if (w) { return w; } w = plus.webview.create(winName, winName, styles, extras);//創建視窗 return w; }; _myth.winInfo = function() {//獲取手機屏幕大小信息 var winInfo = {//視窗基本信息,包括高度,寬度,縱向滾動距離 height: 0, width: 0, scrollTop: 0 }; if (window.innerHeight) {//如果獲取到瀏覽器視窗的視口的高度,則賦值給winInfo.height winInfo.height = window.innerHeight; } else if ((document.body) && (document.body.clientHeight)) {//獲取不到瀏覽器的視窗的高度,能獲取到到body則獲取body高度,進行賦值操作。 winInfo.height = document.body.clientHeight; } if (window.innerWidth) {//如果獲取到瀏覽器視窗的視口的寬度,,則賦值給winInfo.width winInfo.width = window.innerWidth; } else if ((document.body) && (document.body.clientWidth)) {//獲取不到瀏覽器的視窗的高度,能獲取到到body則獲取body寬度,進行賦值操作。 winInfo.width = document.body.clientWidth; } if (document.documentElement && document.documentElement.scrollTop) {//獲取縱向滾動距離 winInfo.scrollTop = document.documentElement.scrollTop; } else if (document.body) { winInfo.scrollTop = document.body.scrollTop; } return winInfo; }; return _myth; })(document);

 

1.Typeof用法詳解:

typeof是一個運算符,typeof(表達式)表示對錶達式做運算,情況如表4-1所示。

序號

返回值

說明

1

'undefined'

未定義的變數或值

2

'boolean'

布爾類型的變數或值

3

 'string' 

字元串類型的變數或值

4

'number' 

數字類型的變數或值

5

'object' 

對象類型的變數或值,或者null(這個是js歷史遺留問題,將null作為object類型處理)

6

 'function' 

函數類型的變數或值

表4-1typeof返回數值類型

2.switch用法詳解

switch 語句用於基於不同條件執行不同動作。語法結構如下:

switch(表達式n) {

     case 1:

        代碼塊

        break;

     case 2:

        代碼塊

        break;

     default:

        預設代碼塊

}

工作原理:首先設置表達式 n(通常是一個變數)。隨後表達式的值會與結構中的每個 case 的值做比較。如果存在匹配,則與該 case 關聯的代碼塊會被執行,其它不執行, break直接跳出switch。

3.plusready用法詳解

plusready是html5+ API,在webapp開發中,若要使用HTML5+擴展api,必須等plusready事件發生後才能正常使用。

為了保證HTML5擴展API的有效調用,頁面載入擴展API完成後會觸發此事件。 通常應該在頁面開始載入時監聽此事件,當此事件觸發後,就可以安全的調用HTML5擴展API。 如果應用使用多頁面,每個都會收到此事件。

// 監聽plusready事件 document.addEventListener("plusready", function(){

// 擴展API載入完畢,現在可以正常調用擴展API

// ...... }, false);  

4.Storage用法詳解

Storage模塊管理應用本地數據存儲區,用於應用數據的保存和讀取,主要方法如表4-2所示。

序號

方法

說明

舉例

1

getLength

獲取應用存儲區中保存的鍵值對的個數

 plus.storage.getLength();

2

getItem

通過鍵(key)檢索獲取應用存儲的值。key: ( DOMString ) 必選

plus.storage.getItem(key);

3

setItem

 

修改或添加鍵值(key-value)對數據到應用數據存儲中。key: ( DOMString ) 必選 存儲的鍵值

value:  DOMString ) 必選

存儲的內容

void plus.storage.setItem(key, value);

4

removeItem

 

通過key值刪除鍵值對存儲的數據

void plus.storage.removeItem(key);

5

clear

 

清除應用所有的鍵值對存儲數據

void plus.storage.clear();

表4-2 Storage用法介紹

第三步:“index.html”代碼修改。在預設文檔的基礎上添加html代碼,JavaScript代碼完成需要的功能,具體代碼如下:

 

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title></title>
<link rel="stylesheet" type="text/css" href="css/myth.css"/>
<script src="js/myth.js"></script>
<script type="text/javascript">
myth.plusReady(function() {
var isguid = myth.readStorage('isguid');//獲取本地存儲key為"isguid"的數值
if (isguid) {//如果存在說明不是第一次啟動
myth.closestartpage();//關閉啟動頁
} else {//不存在,說明不是第一次啟動
myth.open('Guid.html', {background: 'transparent'}, {});//跳轉到引導頁
}
})
</script>
</head>
<body>
編程之路
</body>
</html>

 

四、guid.html

本頁面實現導航頁,共四張圖片,向做滑動,切換。最後一張向做滑動進入webApp住界面,單擊按鈕跳過,進入webApp住界面。最終效果如圖4-2所示。

 

圖4-2 導航頁圖片切換效果

第一步:對myth.css文件補充。 

/* 設置全屏 */
.fullscreen{
width:100%; height:100%; position: fixed; margin: 0px; top: 0px;left: 0px;
}

 

  上述代碼對頁面容器進行全屏設置,position 屬性規定元素的定位類型,取值如表4-3所示。

序號

取值

說明

1

absolute

生成絕對定位的元素,相對於 static 定位以外的第一個父元素進行定位。元素的位置通過 "left", "top", "right" 以及 "bottom" 屬性進行規定。

2

fixed

生成絕對定位的元素,相對於瀏覽器視窗進行定位。元素的位置通過"left", "top", "right" 以及 "bottom" 屬性進行規定。

3

relative

生成相對定位的元素,相對於其正常位置進行定位。因此,"left:20"會向元素的 LEFT 位置添加 20 像素。

4

static

預設值。沒有定位,元素出現在正常的流中(忽略 top, bottom, left, right 或者 z-index 聲明)。

5

inherit

規定應該從父元素繼承 position 屬性的值。

表4-3 CSS元素定位

第二步:guid.html中html代碼補充。

 

<div class="fullscreen">
<!-- 定義一個DIV容器,全屏 -->
<div class="guid-items" id="picbox">
<!-- 定義一個存放圖片容器,存放四張圖片 -->
<img src="img/Guid1.jpg" id="pic1" /><img src="img/Guid2.jpg" id="pic2" /><img src="img/Guid3.jpg" id="pic3" />
<
img src="img/Guid4.jpg" id="pic4" /> </div> </div> <div id="GotuButton" onclick="CloseGuid()">跳過</div> <!-- 定義一個跳過按鈕,單擊跳出導航進入webApp主界面 -->

 

第三步:guid.html中引入myth.css,並補充樣式。

 

<link rel="stylesheet" type="text/css" href="css/myth.css" />
<style type="text/css">
.guid-items {
/* 圖片容器樣式 */
position: fixed;/* 生成絕對定位的元素,相對於瀏覽器視窗進行定位 */
height: 100%;/* 容易高度100%,全屏 */
}
.guid-items img {/* 定義容器中的圖片屬性,所有外邊距0,內邊距同樣為0 */
margin: 0px;
padding: 0px;
}
#GotuButton {/* 定義跳過按鈕樣式,寬50像素,,, */
width: 50px;/* 寬50像素 */
height: 50px;/* 高50像素 */
position: fixed;/* 相對於瀏覽器視窗絕對定位 */
z-index: 10000;/* 堆疊順序為10000,也就是讓該按鈕要浮於圖片上方,可以讓用戶看到 */
top: 50px;/* 距離上方50像素 */
right: 20px;/* 距離右方20像素,也就是右上角顯示 */
background: #FF6600;/* 按鈕背景色 */
text-align: center;/* 按鈕中文字水平居中對齊 */
border-radius: 50px;/* 圓形按鈕設置 */
line-height: 50px;/* 行間距為50像素 */
color: #FFFFFF;/* 按鈕中文字顏色 */ }
</style>

 

 第四步:guid.html中引入myth.js,並編寫JS代碼。

 

<script src="js/myth.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
var wininfo = myth.winInfo();//獲取手機信息
var screenWidth = wininfo.width;//寬度
var guidbox = myth("#picbox");//獲取id為"picbox"對象
guidbox.setWidth("400%");//設置id為"picbox"對象寬度400%,也就是4個屏幕的寬度,4張圖片正好一排顯示
var zguidbox = guidbox.dom[0];//獲取javascript對象
myth("#picbox img").each(function(cObj) {//獲取id為"picbox"對象下麵的所有圖片,並迴圈
myth(cObj).setWidth('25%');//設置每張圖片寬度為25%,正好是1個屏幕大小
})
var currentImg = 1;//當前屏幕顯示圖片序號
var startX, endX;//定義開始手指按住屏幕x軸坐標,和手指離開屏幕x軸坐標
var isPress = false;//判斷手指是否按住屏幕
var gundong=0;//手指按住屏幕後,滑動距離
zguidbox.addEventListener("touchstart", function(e) {//監聽手指按住屏幕事件
isPress = true;//手指按鈕變數設為true
startX = e.touches[0].clientX;//記錄手指按住坐標
});
zguidbox.addEventListener("touchmove", function(e) {//監聽手指滑動事件
if (isPress) {//判斷是否按住住屏幕
endX = e.touches[0].clientX;//記錄滑動最後坐標
gundong = startX - endX;//計算滑動距離
if (gundong < 0) return;//滑動距離小於0,說明是向右滑動,不進行任何操作,直接退出
var juli = -1 * (currentImg - 1) * screenWidth - gundong;//向左滑動時,計算圖片需要滑動的距離
zguidbox.style.transform = 'translate3d(' + juli + 'px, 0px, 0px)';//圖片相應滑動
}
});
zguidbox.addEventListener("touchend", function(e) {//監聽手指離開屏幕事件
if (gundong <= 0) return;//如果距離向左滑動,或未滑動直接退出
if (gundong > 0) {//如果向右滑動
var juli = -1 * currentImg * screenWidth;//計算滑動到相應序號圖片的距離
zguidbox.style.transform = 'translate3d(' + juli + 'px, 0px, 0px)';//圖片滑動到相應圖片
zguidbox.style.transition = '300ms';//添加滑動時間,手指離開屏幕後,圖片300毫秒,滑動到指定距離
currentImg++;//當前顯示圖片序號加一
if (currentImg == 5) {//如果是最後一張圖片滑過
myth.wirteStorage("isguid", "true");//本地存儲key為"isguid"設置為true,說明已經第一次啟動程式
myth.close();//退出引導頁
}
}
isPress = false;//手指按住屏幕變數設置為false
});
function CloseGuid() {
myth.wirteStorage('isguid',"true");//本地存儲key為"isguid"設置為true,說明已經第一次啟動程式
myth.close();//退出引導頁
var isguid = myth.readStorage('isguid');//獲取本地存儲key為"isguid"的數值
console.log(isguid);
}
</script>

 

五、調試

導航頁,到目前為止已經全部編寫完畢,下一步這個過程非常重要,就是對代碼進行調試。在HBuilderX中調試代碼有兩種途徑,一是真機調試,另一種就是模擬器調試,下麵分別學習一下。

(一)真機調試

講的手機與電腦連接,連接成功後,在HBuilderX狀態欄中顯示手機已連接上電腦,如圖4-3所示。

 

圖4-3 手機連接電腦狀態顯示

在HBuilderX上方的工具條中點擊運行按鈕,即可在手機上運行,底部的控制台會有數據顯示,如圖4-4所示,如果有錯誤也會在此顯示相關數據,根據提示進行修改即可。

 

圖4-4 控制台數據

(二)模擬器調試

我用的是“夜神模擬器”,這個模擬器從網上安裝下載即可。然後,在HBuilderX菜單欄中“運行”→“運行到手機或模擬器”→“Android模擬器埠設置”,如圖4-5所示。


圖4-5 模擬器設置

在埠設置頁面設置埠號“62001”即可,如圖4-6所示,這樣的模擬器調試頁設置完畢。同樣在在HBuilderX上方的工具條中點擊運行按鈕,即可在模擬器上運行,調試過程同真機。

 

圖4-6 模擬器埠設置 

常用的Android模擬器的埠如表4-4所示:

模擬器名稱

連接預設埠

夜神安卓模擬器夜神安卓模擬器   

62001

逍遙安卓模擬器逍遙安卓模擬器   

21503

BlueStacks(藍疊安卓模擬器)   雷電安卓模擬

5555

器雷電安卓模擬器    

5555

天天安卓模擬器天天安卓模擬器

5037

  網易MuMu(安卓模擬器)  

7555

安卓模擬器大師安卓模擬器大師

54001

 Genymotion

5555

表4-4 常用Android模擬器埠列表


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. MySQL中的函數 <1>加密函數 <2>聚合函數 <3>數學相關的函數 <4>字元相關的函數 <5>日期函數 <6>流程式控制制函數 2. 用戶的創建和授權(DCL) <1>授權的語法格式 <2>取消許可權的語法格式 <3>顯示授予的許可權 <4>刪除用戶 3.MySQL中的索引 <1>概念: <2 ...
  • 一、Flume簡介 Apache Flume 是一個分散式,高可用的數據收集系統。它可以從不同的數據源收集數據,經過聚合後發送到存儲系統中,通常用於日誌數據的收集。Flume 分為 NG 和 OG (1.0 之前) 兩個版本,NG 在 OG 的基礎上進行了完全的重構,是目前使用最為廣泛的版本。下麵的 ...
  • https://wangde.xin/images/article/mysql/mysql_com.png ...
  • DDL的全稱Data Definition Language,即數據定義語言 DDL的語法有:create、alter、drop、rename、truncate。對此做一個詳細的解釋: create (創建) create 可以創建資料庫 create 可以創建表格 創建表格的語法:方括弧的表示可以 ...
  • https://www.oracle.com/technetwork/cn/topics/index-088165-zhs.html 下載地址Orion是Oracle提供的IO性能測試工具,運行該工具不需要安裝oracle database軟體或創建資料庫。 它可以模擬Oracle資料庫的IO負載,... ...
  • 最近遇到了這個案例,官方文檔已有詳盡的分析、介紹,特轉載在此,方便以後查看! Full UNDO Tablespace In 10gR2 and above (文檔 ID 413732.1) 轉到底部 In this Document Symptoms Changes Cause Solution ... ...
  • 寫了一個bat命令,定期去清理一些SQL Server的Dump文件,然後配置成SQL Server作業,作業執行時報許可權錯誤,具體錯誤信息如下所示: Message Executed as user: NT Service\SQLSERVERAGENT. The process could not... ...
  • DJI_Mobile_SDK是大疆為開發者提供的開發無人機應用的開發介面,可以實現對無人機飛行的控制,也可以利用無人機相機完成一些視覺任務。目前網上的開發教程主要集中於DJI 開發者社區,網上的資源非常少。廢話不多說~~,現在將在Android項目中學習到的東西總結一下。 使用大疆無人機做電腦視覺 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...