救蜂群的替代殺蟲劑 結果也對蜜蜂有害

摘錄自2018年8月16日中央社報導

研究人員今天(16日)警告,一種用於替代危害蜜蜂的「新類尼古丁」(neonicotinoid)殺蟲藥的新型殺蟲劑,可能與新類尼古丁殺蟲藥一樣,還是對作物授粉的蜜蜂有害。

研究人員在「自然」(Nature)期刊表示,實驗中,大黃蜂的繁殖能力和牠們蜂群成長速度,都會受到新的鵳基亞胺類(sulfoximine)殺蟲劑所影響。

研究主筆、倫敦大學皇家哈洛威學院(Royal Holloway, University of London)研究人員席維特(Harry Siviter)說:「我們研究結果顯示,新型殺蟲劑之一的速殺氟(sulfoxaflor)會對大黃蜂繁殖量產生負面影響。」

與新類尼古丁相似,速殺氟不會直接殺死蜜蜂,但卻顯示會影響蜜蜂的免疫系統或生殖能力。

不過覓食行為和個別蜜蜂採集花粉量在實驗中保持不變。

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

FB行銷專家,教你從零開始的技巧

買綠電團購力量大 蘋果等四企業簽290MW訂單

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

新北清潔公司,居家、辦公、裝潢細清專業服務

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

宣示2050年零碳排 全球87大企業領頭邁向1.5℃目標

環境資訊中心綜合外電;姜唯 編譯;彭瑞祥 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

氣候暖化 瑞士居民為消失冰川辦葬禮

摘錄自2019年9月23日公視報導

瑞士居民為阿爾卑斯山的冰川舉行了葬禮,受氣候變遷影響,這座冰川從2006年消融速度加快,現在已經消失了90%面積。

大約250個瑞士居民,22日穿著黑衣,披著黑頭紗爬了約兩小時的路程,登上海拔約2700公尺的皮措爾山山頂,為這座即將消失的冰川舉行葬禮。

瑞士蘇黎世聯邦理工學院冰川專家赫斯表示,「照目前情況來看,我們還有約4個足球場大小的冰川,但過去兩年冰川消融的速度迅速增加。」

皮措爾冰川位在瑞士境內的阿爾卑斯山,自從2006年以來,已經失去了將近90%面積,現在只剩下約兩萬6000平方公尺,不到四個足球場大小,科學家認為,冰川消融如此快速是受到氣候變遷影響,如果再不控制溫室氣體排放,這座冰川將會在2030年前完全消失。

 

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

FB行銷專家,教你從零開始的技巧

一起玩轉微服務(11)——一切從簡單開始

介紹

使用Spring Bboot是快樂並且簡單的,不需要繁瑣的配置就能夠完成一套非常強大的應用。

spring boot 2.3.1

Spring Boot 2.3.1 發佈於:2020/06/12,現在已經提交到 Spring 倉庫和 Maven 中央倉庫了。

這個版本包括 127 個 bug 修復、Spring Boot 文檔改進增強、依賴升級等,另外還新增了一些新特性:

•提供基於新的 Maven 坐標 com.oracle.database 對 Oracle JDBC driver 的依賴管理;

•優化 Spring Cloud 的 CachedRandomPropertySource 不能正確適配的問題;•限制使用定製的 YAML 類型;

•增強對 NoSuchMethodErrors 異常失敗分析,能显示基類從哪被加載的;•提供更佳的錯誤消息,如果 Docker 停止運行了;

•優化 SystemEnvironmentPropertyMapper 類;

•提供更佳的診斷信息,當構建 OCI 鏡像失敗時 Docker 響應的 500 錯誤;

•支持通過 alwaysUseFullPath=true 參數來配置 UrlPathHelper;•支持在 Elasticsearch URIs 中使用用戶信息;

•支持在 Spring WebFlux 框架中使用歡迎頁面;

這個小版本還增加了蠻多東西的,大家也沒有必要跟着版本走,可以根據需要進行升級。疫情也擋不住外國友人更新的熱情。

實現

使用STS,可以去官方網站下載最新版。網站地址 https://Spring.io/tools/sts/ Spring Tool Suite™是基於eclipse開發的專門為Spring開發使用的工具包。

新建工程

選擇Spring Starter Project,

輸入工程名 對應的Name 打包方式 對應的Packaging,可以選擇jar或者war的方式。

輸入組織名 對應的Group 輸入描述 對應的Description

輸入包名 對應的Package 點擊next,然後選擇web和mysql

這裏的版本用的是2.3.1 如果沒有本地maven庫或者私庫會下載很長時間。

添加默認請求

進入 Chapter0301Application 添加

@RestController
@SpringBootApplication
public class Chapter0301Application {
    
    @RequestMapping("/")
    String home() {
         return "歡迎使用Spring Boot!";
    }

    public static void main(String[] args) {
        SpringApplication.run(Chapter0301Application.class, args);
    }

}

使用@RestController 相當於@Controller 和 @RequestBody。是Sspring Bboot 基於Sspring MVC的基礎上進行了改進, 將@Controller 與@ResponseBody 進行了合併形成的一個新的註解。 @EnableAutoConfiguration 作用 從classpath中搜索所有META-INF/spring.factories配置文件然後,將其中org.springframework.boot.autoconfigure.EnableAutoConfiguration key對應的配置項加載到spring容器 只有spring.boot.enableautoconfiguration為true(默認為true)的時候,才啟用自動配置 @EnableAutoConfiguration還可以進行排除,排除方式有2種,一是根據class來排除(exclude),二是根據class name(excludeName)來排除 其內部實現的關鍵點有

1.ImportSelector 該接口的方法的返回值都會被納入到spring容器管理中

2.SpringFactoriesLoader 該類可以從classpath中搜索所有META-INF/spring.factories配置文件,並讀取配置

啟動spring boot

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.1.RELEASE)

2020-06-23 13:30:11.611  INFO 9916 --- [           main] com.cloud.sky.Chapter0301Application     : Starting Chapter0301Application on DADI-PC with PID 9916 (D:\java\microservice\chapter0301\target\classes started by Administrator in D:\java\microservice\chapter0301)
2020-06-23 13:30:11.614  INFO 9916 --- [           main] com.cloud.sky.Chapter0301Application     : No active profile set, falling back to default profiles: default
2020-06-23 13:30:12.415  INFO 9916 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-06-23 13:30:12.423  INFO 9916 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-06-23 13:30:12.424  INFO 9916 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.36]
2020-06-23 13:30:12.512  INFO 9916 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-06-23 13:30:12.512  INFO 9916 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 830 ms
2020-06-23 13:30:12.665  INFO 9916 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-06-23 13:30:12.809  INFO 9916 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-06-23 13:30:12.818  INFO 9916 --- [           main] com.cloud.sky.Chapter0301Application     : Started Chapter0301Application in 1.492 seconds (JVM running for 3.109)
2020-06-23 13:30:20.675  INFO 9916 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-06-23 13:30:20.676  INFO 9916 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-06-23 13:30:20.680  INFO 9916 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 4 ms

打開瀏覽器訪問 http://localhost:8080/ 可以得到如下頁面

遇到問題

構建的過程中遇到問題

[INFO] Scanning for projects...
[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[FATAL] Non-parseable POM D:\java\apache-maven-3.1.1\repo\org\jetbrains\kotlin\kotlin-bom\1.3.72\kotlin-bom-1.3.72.pom: entity reference names can not start with character ')' (position: START_TAG seen ...ost,s="";function qs(n){var u=D.URL;var t=u.match(eval(\'/(\\?|#|&)... @1:243)  @ D:\java\apache-maven-3.1.1\repo\org\jetbrains\kotlin\kotlin-bom\1.3.72\kotlin-bom-1.3.72.pom, line 1, column 243
 @ 
[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]   
[ERROR]   The project com.cloudskyme:chapter0301:0.0.1 (D:\java\microservice\chapter0301\pom.xml) has 1 error
[ERROR]     Non-parseable POM D:\java\apache-maven-3.1.1\repo\org\jetbrains\kotlin\kotlin-bom\1.3.72\kotlin-bom-1.3.72.pom: entity reference names can not start with character ')' (position: START_TAG seen ...ost,s="";function qs(n){var u=D.URL;var t=u.match(eval(\'/(\\?|#|&)... @1:243)  @ D:\java\apache-maven-3.1.1\repo\org\jetbrains\kotlin\kotlin-bom\1.3.72\kotlin-bom-1.3.72.pom, line 1, column 243 -> [Help 2]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
[ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/ModelParseException

1. 解決

修改maven默認源配置
我使用的是阿里的maven倉庫,國外的東西沒個代理還真麻煩。

<repositories>
        <repository>  
            <id>alimaven</id>
            <name>aliyun maven</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        </repository> 
        <repository>
            <id>sonatype-nexus-snapshots</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
            <releases>
                <enabled>false</enabled>
            </releases>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

然後執行 mvn help:system
成功可以看到如下界面:

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

ODBC 常見數據源配置整理

目錄

  • 1. 簡介
    • 1.1 ODBC和JDBC
    • 1.2 ODBC配置工具
    • 1.3 ODBC 數據源連接配置
  • 2. MySQL 數據源配置
    • 2.1 配置步驟
    • 2.2 鏈接參數配置
  • 3. SQLServer 數據源配置
    • 3.1 配置步驟
    • 3.2 鏈接參數配置
  • 4. ACCESS 數據源配置
    • 4.1 配置步驟
    • 4.2 鏈接參數配置

1. 簡介

我們用golang做odbc驅動開發的任務並不多,隔段時間可能會來一個。每次開發會忘記如何配置數據源和對應的數據源鏈接參數配置。這裏做一個整理。

1.1 ODBC和JDBC

ODBC(Open Database Connectivity)是一組對數據庫訪問的標準API,其最大的優點是以統一的方式處理所有的數據庫。

JDBC(Java Database Connectivity)是Java與數據庫的接口規範,允許Java程序發送SQL指令並處理結果。比較常見JdbcTemplate

1.2 ODBC配置工具

打開控制面板找到管理工具,當前目錄有兩個ODBC的配置工具。分別是:ODBC Data Sources (32-bit)、ODBC 數據源(64 位)。顧名思義一個是32位,一個是64位。在配置ACCESS數據源時需要選擇32位。

我們也可以直接在系統目錄下找到對應的可執行文件。

1)32位:%windir%\syswow64\odbcad32.exe

2)64位:%windir%\system32\odbcad32.exe

題外話:syswow64 目錄存放的是32位的程序,system32目錄存放的是64位的程序,在註冊dll的時候需要注意下。ITDragon 在接觸驅動開發之前一直都弄反了。這篇文章做了通俗易懂地解釋https://www.cnblogs.com/hbccdf/p/dllchecktoolandsyswow64.html

1.3 ODBC 數據源連接配置

網上收集整理,不保證正確性,僅供參考。

數據庫 連接參數
MySQL driver={mysql};database=數據庫;uid=賬號;pwd=密碼;
MSSQL Server driver={sql server};server=服務器;database=數據庫;uid=ITDragon;pwd=密碼;
Access driver={microsoft access driver (*.mdb)};dbq=mdb文件全路徑;uid=ITDragon;pwd=密碼;
SQLite driver={SQLite3 ODBC Driver};database=db文件全路徑
PostgreSQL driver={PostgreSQL ANSI};server=服務器;uid=賬號;pwd=密碼;database=數據庫;
DBase driver={microsoft dbase driver (*.dbf)};driverid=277;dbq=dbf文件全路徑;
Oracle driver={microsoft odbc for oracle};server=服務器;uid=ITDragon;pwd=密碼;
MS text driver={microsoft text driver (* .txt; *.csv)};dbq=文件全路徑;extensions=asc,csv,tab,txt;PersistSecurityInfo=false;
Visual Foxpro driver={microsoft Visual Foxpro driver};sourcetype=DBC;sourceDB=*.dbc;Exclusive=No;

2. MySQL 數據源配置

2.1 配置步驟

第一步:雙擊ODBC 數據源(64 位),可以選擇用戶DSN(系統只對當前用戶生效),也可以選擇系統DSN(能登錄當前系統的用戶都生效)

第二步:點擊添加,選擇事先安裝好的MySQL ODBC xx Driver 驅動後點擊完成。注意不同版本之間對某些sql語法的支持略有不同(之前吃過這個虧,我的環境有問題,客戶環境沒問題)。

第三步:完善基本鏈接信息後點擊Test,提示鏈接成功後點擊OK完成配置。

2.2 鏈接參數配置

因為ODBC驅動配置已經將數據庫的連接地址、賬號、密碼、數據庫都已經配置完成,連接參數只需要指定驅動名稱即可:DSN=ITDragon_MySQL

Golang偽代碼:

import (
	"database/sql"
	_ "github.com/alexbrainman/odbc"
)

db, err := sql.Open("odbc", "DSN=ITDragon_MySQL")
if err != nil {
    panic(err)
}
defer db.Close()

3. SQLServer 數據源配置

3.1 配置步驟

第一步:雙擊ODBC 數據源(64 位),可以選擇用戶DSN(系統只對當前用戶生效),也可以選擇系統DSN(能登錄當前系統的用戶都生效)

第二步:點擊添加,選擇SQL Server。這一項我ITDragon 並沒有手動安裝,應該是安裝SQL Server數據庫的時候自動安裝上去的。

第三步:鍵盤輸入需要連接的SQLServer服務器,如果是本機,就輸入計算機名。如果是遠程主機就需要輸入IP,Port 。不要點擊下拉框,會卡死。

第四步:選擇SQL Server驗證方式

第五步:選擇默認數據庫,也可以在寫sql語句時將表名的全路徑寫全(我ITDragon 習慣用寫全)

第六步:可以考慮修改SQL Server的系統消息語言,數據的加密,執行字符數據翻譯,修改日誌保存路徑等。也可以默認。

第七步:點擊完成,彈出“按照以下配置創建新的ODBC數據源”,點擊測試數據源,提示測試成功。點擊確定完成創建。

3.2 鏈接參數配置

Golang偽代碼:

import (
	"database/sql"
	_ "github.com/alexbrainman/odbc"
)

db, err := sql.Open("odbc", "driver={sql server};server=DESKTOP-HKC2IA3;DSN=ODBCName;uid=xxx;pwd=xxx;")
if err != nil {
    panic(err)
}
defer db.Close()

4. ACCESS 數據源配置

4.1 配置步驟

第一步:雙擊ODBC Data Sources (32-bit),而不是64位。可以選擇用戶DSN(系統只對當前用戶生效),也可以選擇系統DSN(能登錄當前系統的用戶都生效)

第二步:選擇Microsoft Access Driver (*.mdb)。點擊數據庫下發的選擇按照,選擇mdb文件,點擊確定完成配置。

4.2 鏈接參數配置

我們其實可以不用配置Access的數據源,直接用DBQ指定mdb的文件路徑,再用pwd輸入密碼訪問。

Golang偽代碼:

import (
	"database/sql"
	_ "github.com/alexbrainman/odbc"
)

db, err := sql.Open("odbc", "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=全路徑.MDB;pwd=xx;")
if err != nil {
    panic(err)
}
defer db.Close()

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※台北網頁設計公司全省服務真心推薦

※想知道最厲害的網頁設計公司"嚨底家"!

新北清潔公司,居家、辦公、裝潢細清專業服務

※推薦評價好的iphone維修中心

專家解讀:利用Angular項目與數據庫融合實例

摘要:面對如何在現有的低版本的框架服務上,運行新版本的前端服務問題,華為雲前端推出了一種融合方案,該方案能讓獨立的Angular項目整體運行在低版本的框架服務上,通過各種適配手段,讓Angular項目也能獲取到外層框架服務的資源。

華為雲前端服務前期採用AngularJs作為框架技術棧,技術較為老舊,性能較差,在華為雲快速發展的今天,顯然不能滿足要求。因此我們必須要升級前端技術棧,使用Angular2+來承載我們的前端服務。GeminiDB作為新服務,也是數據庫乃至華為雲未來的重點服務,作為前端部分,必須在技術上使用最前沿的框架,以最大地提高用戶體驗。

但是技術棧的升級不是一蹴而就的,尤其是在華為雲,所有的雲服務必須在框架服務的底座上運行,而框架服務承載了所有的雲服務,如果要進行技術棧升級,必然是一個緩慢的過程。GeminiDB作為華為雲服務里的一員,也不可能脫離框架服務而存在。因此存在一個問題,就是如何在現有的低版本的框架服務上,運行新版本的前端服務。

為了解決以上問題,華為雲前端推出了一種融合方案,該方案能讓獨立的Angular項目整體運行在低版本的框架服務上,通過各種適配手段,讓Angular項目也能獲取到外層框架服務的資源。

底層項目

底層項目使用webpack打包,打包后通過在index.html里引入businessAll.js文件,以該文件為入口啟動整個框架服務。

<script type="text/javascript" src="businessAll.js"></script>

在底層框架服務啟動后,再渲染出具體雲服務內容。

<div class="service-content-view" ui-view ng-animate="{enter:'fade-enter'}"></div>

Angular項目

Angular項目支持獨立運行,有單獨的index.html,也有單獨的main.ts入口。但是如果希望Angular項目運行在底層框架服務上,就必須把Angular項目看作是一個獨立的模塊,把項目整體引入到底層項目中。因此,我們可以預先把Angular項目編譯好,放到底層項目的一個目錄下。在運行底層項目時,在index.html里將Angular項目引進來,獨立運行。

<link rel="stylesheet" type="text/css" href="{底層項目中Angular項目的路徑}/styles.css" />
<script type="text/javascript" src="{底層項目中Angular項目的路徑}/runtime.js"></script>
<script type="text/javascript" src="{底層項目中Angular項目的路徑}/polyfills.js"></script>
<script type="text/javascript" src="{底層項目中Angular項目的路徑}/main.js"></script>

項目融合

底層項目和Angular項目均能獨立,但是要讓兩者融合起來,會遇到以下幾個問題:

1.底層項目中如何渲染出Angular項目。

2.Angular項目依賴底層項目的資源,如何保證Angular項目在底層項目運行起來后再運行。

3.如何解決底層項目和Angular項目的路由衝突問題。

渲染Angular項目

底層項目分為兩部分,一部分是底層框架服務,另一部分是具體雲服務。現在我們要做的是把老的雲服務項目替換成新的Angular項目,因此我們可以直接在渲染老的雲服務的地方替換成新的Angular項目的渲染容器。

<div class="service-content-view" ui-view ng-animate="{enter:'fade-enter'}"></div>
<app-root></app-root>

底層框架服務對頁面渲染上做了一些體驗上的優化,因此必須保留原模板中的ui-view,使底層項目正常運行起來,實際上老的雲服務項目的渲染內容已經轉發到新的Angular項目上面。

Angular項目對底層項目的依賴

底層框架服務給雲服務提供了很多公共變量與服務,這些變量和服務是各個雲服務必須要使用的,否則雲服務將不能正常運作。

啟動順序問題

對於Angular項目來說,要使用底層框架服務提供的內容,首先要求Angular項目在底層項目運行起來之後再運行。這裏採用Augular中的APP_INITIALIZER令牌來解決這個問題。APP_INITIALIZER是一個函數,在程序初始化的時候被調用。這裡在根模塊的providers中以factory的形式來配置。

import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";

import { AppInitService } from './services/app-init.service';
import { AppComponent } from "./app.component";

@NgModule({
 declarations: [AppComponent],
 imports: [BrowserModule],
 providers: [
     AppInitService,
    {
         provide: APP_INITIALIZER,
         useFactory: initializeApp,
         deps: [AppInitService],
         multi: true
    }
],
 bootstrap: [AppComponent]
})
export class AppModule {}

export function initializeApp(appInitService: AppInitService) {
   return (): Promise<any> => {
       return appInitService.Init();
  };
}

在appInitService里,先獲取到底層框架的資源,再進行Angular項目的初始化。

import { Injectable } from '@angular/core';

@Injectable()
export class AppInitService {
   constructor() {}

   Init() {
       return new Promise<void>((resolve, reject) => {
           // 獲取到底層框架服務的資源
           resolve();
      });
  }
}

資源依賴問題

底層項目使用的是AngularJs,Angular項目獲取底層框架服務提供的資源不能通過Angular的方式引入,因此需要藉助AngularJS的注入器獲取在底層框架中註冊的服務組件:

static get(inject: string): any {
return (window as any).angular.element('html').injector().get(inject);}
如,要獲取 $rootScope:
 rootScope = (window as any).angular.element('html').injector().get(‘$rootScope’);

路由衝突問題

Angular項目本身有自己的路由,但是Angular項目是運行在底層框架之上的,Angular項目的路由將會被底層框架所攔截。因此,我們也需要在底層框架的項目中配置相同的路由,以免Angular項目中的有效路由被底層框架識導向為404。

Angular項目路由:

{
   path: '',
   redirectTo: 'ng2app1',
   pathMatch: 'full'
},
{
   path: 'ng2app1',
   loadChildren: './ng2app1/ng2app1.module#Ng2app1Module',
},
{
   path: 'ng2app2',
   loadChildren: './ng2app2/ng2app2.module#Ng2app2Module',
}
 
底層框架路由:
var configArr = [
  {
       name: 'ng2app1',
       url: '/ng2app1'
  },
  {
       name: 'ng2app2',
       url: '/ng2app2'
  }
];

另外,由於底層項目使用的是hash路由,Angular項目中也要做相應的配置,默認是使用的是PathLocationStrategy,需要切換到hash模式。

import { LocationStrategy, HashLocationStrategy } from '@angular/common';

...
providers: [
  {
       provide: LocationStrategy,
       useClass: HashLocationStrategy
  }
]

總結

以上方案是在底層框架升級周期長的前提下的一個臨時方案,實際上還是存在着不少的問題。比如底層框架對於老的雲服務容器是有統一管理的,老的雲服務容器會針對不同的場景能夠自適應,而融合方案中的Angular項目則不能;每次啟動整個項目時,必須要預先編譯好裏面的Angular項目,再去啟動外層的底層框架,開發效率比較低。因此,後續GeminiDB服務應該在底層框架升級后,儘快適應到新的底層框架體系中,提高服務的可用性和穩定性。

 

點擊關注,第一時間了解華為雲新鮮技術~

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準

Jmeter系列(27)- 詳解正則提取器

如果你想從頭學習Jmeter,可以看看這個系列的文章哦

https://www.cnblogs.com/poloyy/category/1746599.html

 

有了 JSON 提取器為啥還要用正則提取器?

  • JSON 提取器只針對接口返回的響應內容
  • 如果想提取的是響應頭、請求頭的值,而非響應內容的值呢?
  • 這個時候正則提取器的作用就出來了,它可以提取請求任一部分的值

 

需知

  • 正則表達式很多內容,在這篇文章中不會展開詳細說的哦,主要還是說提取器的使用
  • 想詳細學習正則表達式可以看這篇文章:待補充

 

正則提取器

我們通過實際栗子去講述理論知識點

 

正則提取器界面介紹

 

字段含義

字段 含義
Apply to 應用範圍,選默認的 main sample only 就行了
Field to check

可提取的字段

Names of created variables
  • 接收提取值的變量名
  • 必傳
Regular Expression

正則表達式

Template 從找到的匹配項中創建字符串的模板
Match No.(0 for Random)
  • 取第幾個值
  • 0:隨機,默認
  • -1:所有
  • 1:第一個值
  • 非必傳
Default Value
  • 缺省值,匹配不到值的時候取該值
  • 非必傳
Use empty default value

勾選后,提取不到值時,則返回空字符串

 

Template

  • 如果一條正則表達式有多個提取結果,則提取結果是數組形式
  • 模板 $1$、$2$…..表示把解析到的第幾個值賦給變量,從 1 開始匹配
  • $0$ 表示整個表達式匹配的內容(後續具體看栗子)
  • 若只有一個結果,只能是$1$

 

Field to check

屬性 含義
Body 響應體,不包括響應頭;最常用
Body (unescaped) 響應體,替換了所有HTML轉義符;不建議使用
Body as a Document 從不同類型的文件中提取文本;影響性能
Request Headers 請求頭
Response Headers 響應頭
URL URL
Response Code 響應碼
Response Message 響應信息

 

Body

 

Request Headers

 

Response Headers

 

URL

 

Response Code、Message

 

入門栗子

栗子的前提

這個栗子,我都會以這個地址的接口來完成 JSON 提取器的實戰慄子,大家可以註冊個賬號玩一玩哦

http://api.yesapi.cn/docs.php?keyword=%E4%BC%9A%E5%91%98&channel=api

 

測試計劃樹結構

下面多個栗子都以這個測試計劃為基礎哦

 

提取某個特定的值的栗子

登錄接口響應

登錄是執行其他接口的前置接口,所以要獲取用戶登錄后的 token、uuid

 

提取 token

 

提取 uuid

 

其他接口調用 token、uuid

 

知識點

  • 提其他接口可以通過  ${var}  這種格式,來獲取提取到的值
  •  ( ) 裏面寫匹配規則,用於解析正則表達式
  •  .*? 表示匹配任意長度的任意字符,這也是最常用的正則表達式
  • 一般 (.+?) 和 (.*?) 能夠滿足我們 80%的使用場景

 

一般正則表達式都可以寫成下面兩種

  •  左邊界(.+?)右邊界 
  •  左邊界(.*?)右邊界 

 

舉更多栗子前的一些話

  • 上面講的是使用正則提取器時的一個流程,也是實際工作中最簡單的栗子
  • 在實際項目中,我們可能會出現一條正則表達式有多個提取結果的情況

 

JSON 字符串

下面的栗子都以這個 JSON 字符串為基礎,从里面提取結果

這 JSON 字符串也是某個接口的響應內容,貨真價實,感興趣也可以自己玩一玩:http://api.yesapi.cn/docs-api-App.User.GetList.html

{
    "ret": 200,
    "msg": "V2.5.1 YesApi App.User.GetList",
    "data": {
        "total": 4,
        "err_msg": "",
        "err_code": 0,
        "users": [
            {
                "role": "user",
                "status_desc": "正常",
                "reg_time": "2020-06-22 20:45:05",
                "role_desc": "普通會員",
                "ext_info": {
                    "yesapi_nickname": "",
                    "yesapi_points": 0
                },
                "uuid": "0564CE592B4CE914365D8922F6FC4CEC",
                "username": "luojunjiess286",
                "status": 0
            },
            {
                "role": "user",
                "status_desc": "正常",
                "reg_time": "2020-06-22 14:27:17",
                "role_desc": "普通會員",
                "ext_info": {
                    "yesapi_nickname": "",
                    "yesapi_points": 0
                },
                "uuid": "0164DC0680F84DCE40D3DD4A36640ECA",
                "username": "luojunjiessa",
                "status": 0
            },
            {
                "role": "admin",
                "status_desc": "正常",
                "reg_time": "2020-03-23 22:48:32",
                "role_desc": "管理員",
                "ext_info": {
                    "yesapi_nickname": "",
                    "yesapi_points": 0
                    "yesapi_reg_source": ""
                },
                "uuid": "079BF6BB82AFCFC7084F96AECAF0519F",
                "username": "luojunjiess",
                "status": 0
            }
        ]
    }
}

 

一條正則表達式只有一個提取結果的栗子

什麼叫只有一個提取結果

就是正則表達式里只有一個 ( ) ,且  Match No. 不是 -1

 

未填寫模板

提取器

 

測試結果

uuid1=
uuid1_g=1
uuid1_g0="uuid":"0564CE592B4CE914365D8922F6FC4CEC"
uuid1_g1=0564CE592B4CE914365D8922F6FC4CEC

 

知識點

如果正則匹配到值,但是沒有填模板,則返回

 

$0$

提取器

 

測試結果

uuid2="uuid":"0564CE592B4CE914365D8922F6FC4CEC"
uuid2_g=1
uuid2_g0="uuid":"0564CE592B4CE914365D8922F6FC4CEC"
uuid2_g1=0564CE592B4CE914365D8922F6FC4CEC

 

知識點

  •  $0$ 模板其實返回的就是 uuid2_g0 的值
  • 返回了整個正則表達式,不只是 ( ) 內匹配到的值

 

$1$

提取器

 

測試結果

uuid3=0564CE592B4CE914365D8922F6FC4CEC
uuid3_g=1
uuid3_g0="uuid":"0564CE592B4CE914365D8922F6FC4CEC"
uuid3_g1=0564CE592B4CE914365D8922F6FC4CEC

 

知識點

  •  $1$  模板其實返回的就是 uuid2_g1 的值
  • 僅返回 ( ) 內匹配到的值

 

$2$

提取器

 

測試結果

uuid4=null
uuid4_g=1
uuid4_g0="uuid":"0564CE592B4CE914365D8922F6FC4CEC"
uuid4_g1=0564CE592B4CE914365D8922F6FC4CEC

 

知識點

 $2$ 模板並不存在,其實就是 uuid4_g2 變量不存在,即使勾了使用空默認值,也返回 null,

 

總結

  • 其實 uuid 在 JSON 字符串中有三個可匹配到的值,如果不填寫匹配数字 Match No. ,則會隨機取一個 uuid 並返回
  • 像上述的幾個栗子,都填了 1 ,所以都返回了第一個匹配到的 uuid

 

一條正則表達式有多個提取結果的栗子

什麼叫有多個提取結果

有兩種情況

  • 一條表達式有多個 ( ) 
  • 一個 ( ) 匹配到多個值,且 Match No 填了 -1

 

一個 ( ) 匹配到多個值 

提取器

 

測試結果

手動分成四部分

uuid1_1=0564CE592B4CE914365D8922F6FC4CEC
uuid1_1_g=1
uuid1_1_g0="uuid":"0564CE592B4CE914365D8922F6FC4CEC"
uuid1_1_g1=0564CE592B4CE914365D8922F6FC4CEC

uuid1_2=0164DC0680F84DCE40D3DD4A36640ECA
uuid1_2_g=1
uuid1_2_g0="uuid":"0164DC0680F84DCE40D3DD4A36640ECA"
uuid1_2_g1=0164DC0680F84DCE40D3DD4A36640ECA

uuid1_3=079BF6BB82AFCFC7084F96AECAF0519F
uuid1_3_g=1
uuid1_3_g0="uuid":"079BF6BB82AFCFC7084F96AECAF0519F"
uuid1_3_g1=079BF6BB82AFCFC7084F96AECAF0519F

uuid1_matchNr=3

 

知識點

  • 一個 ( ) 匹配到多個值的場景 ,一般會結合 ForEach控制器,可以循環將提取到的值賦予到 HTTP 請求中
  • 可以看看下圖的小栗子,這裏不展開講,後面會再詳細講解

 

結構樹 + ForEach 控制器

 

查看結果樹

 

一條表達式有多個( ),且模板為空

提取器

 

測試結果

info1=
info1_g=2
info1_g0="uuid":"0564CE592B4CE914365D8922F6FC4CEC","username":"luojunjiess286"
info1_g1=0564CE592B4CE914365D8922F6FC4CEC
info1_g2=luojunjiess286

 

一條表達式有多個( ),且只有一個模板

提取器

 

測試結果

info2=0564CE592B4CE914365D8922F6FC4CEC
info2_g=2
info2_g0="uuid":"0564CE592B4CE914365D8922F6FC4CEC","username":"luojunjiess286"
info2_g1=0564CE592B4CE914365D8922F6FC4CEC
info2_g2=luojunjiess286

 

知識點

  • info2 拿的就是 info2_g1 的值
  •  $1$ 獲取的是第一個 ( ) 匹配到的值, $2$ 獲取的是第二個 ( ) 匹配到的值,以此類推     

 

一條表達式有多個( ),且有兩個模板

提取器

 

測試結果

info3=0564CE592B4CE914365D8922F6FC4CECluojunjiess286
info3_g=2
info3_g0="uuid":"0564CE592B4CE914365D8922F6FC4CEC","username":"luojunjiess286"
info3_g1=0564CE592B4CE914365D8922F6FC4CEC
info3_g2=luojunjiess286

info4=0564CE592B4CE914365D8922F6FC4CEC,luojunjiess286
info4_g=2
info4_g0="uuid":"0564CE592B4CE914365D8922F6FC4CEC","username":"luojunjiess286"
info4_g1=0564CE592B4CE914365D8922F6FC4CEC
info4_g2=luojunjiess286

 

正則表達式中有多個 ( ) 時的總結

  • 如果其中一個 ( ) 匹配不到元素,那也無法獲取到值
  • 引用名稱、匹配数字、缺省值三個字段也只需要填一個值即可,不需要跟 ( ) 的數量一致
  • 多個模板( $1$$2$ )的時候,可以用空格、, 、. 、  連接模板,最終會显示在變量上,如:info4

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

chromedp入門

chromedp入門

chromedp是什麼?

chromedp是go寫的,支持Chrome DevTools Protocol 的一個驅動瀏覽器的庫。並且它不需要依賴其他的外界服務(比如 Selenium 和 PhantomJs)。

Chrome DevTools Protocol (CDP)

Chrome DevTools Protocol (CDP) 的主頁在:https://chromedevtools.github.io/devtools-protocol/。 它提供一系列的接口來查看,檢查,調整並且檢查 Chromium 的性能。Chrome 的開發者工具就是使用這一系列的接口,並且 Chrome 開發者工具來維護這些接口。

所謂 CDP 的協議,本質上是什麼呢?本質上是基於 websocket 的一種協議。比如

在我們打開 webtool 調試工具的時候,其實調試工具也是一個web頁面,兩個web頁面通過websocket建立了一個聯繫。
所以我們如果寫了一個客戶端程序,也和目標頁面創建一個基於 CDP 的 websocket連接,我們也可以通過這個協議來對頁面進行操作。

如何打開 Protocol Monitor

在chrome的開發者工具中

打開實驗選項 Protocol Monitor

重啟chrome,在console的更多裏面就可以打開對應的 Monitor

CDP 協議內容

我們從 Protocol Monitor 面板中可以看到,其中有幾個字樣,Method,Request,Response。
這裏的 Method 就是對應官網 https://chromedevtools.github.io/devtools-protocol/ 左側每個Domain的 Event。

這裏的每個Method方法可能是調試頁面給目標頁面發送的,但是更多是目標頁面給調試頁面發送的消息。所以我們需要讀懂每個Method的內容。不過很可惜,我個人感覺官網的每個Method文檔的描述寫的實在是太簡單了,也沒有看到更詳細的描述,只能通過名字和事件來猜測每個Method意思了。

chromedp 使用

chromedp的使用最快的方法就是看 https://github.com/chromedp/examples 這個項目

基本我們可以熟悉最常用的幾個方法了:

  • chromedp.NewContext() 初始化chromedp的上下文,後續這個頁面都使用這個上下文進行操作
  • chromedp.Run() 運行一個chrome的一系列操作
  • chromedp.Navigate() 將瀏覽器導航到某個頁面
  • chromedp.WaitVisible() 等候某個元素可見,再繼續執行。
  • chromedp.Click() 模擬鼠標點擊某個元素
  • chromedp.Value() 獲取某個元素的value值
  • chromedp.ActionFunc() 再當前頁面執行某些自定義函數
  • chromedp.Text() 讀取某個元素的text值
  • chromedp.Evaluate() 執行某個js,相當於控制台輸入js
  • network.SetExtraHTTPHeaders() 截取請求,額外增加header頭
  • chromedp.SendKeys() 模擬鍵盤操作,輸入字符
  • chromedp.Nodes() 根據xpath獲取某些元素,並存儲進入數組
  • chromedp.NewRemoteAllocator
  • chromedp.OuterHTML() 獲取元素的outer html
  • chromedp.Screenshot() 根據某個元素截圖
  • page.CaptureScreenshot() 截取整個頁面的元素
  • chromedp.Submit() 提交某個表單
  • chromedp.WaitNotPresent() 等候某個元素不存在,比如“正在搜索。。。”
  • chromedp.Tasks{} 一系列Action組成的任務

實踐

我們嘗試打開 https://www.cnblogs.com/ 的首頁,然後獲取所有文章的標題和鏈接:

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/chromedp/cdproto/cdp"
	"github.com/chromedp/chromedp"
)

func main() {

	ctx, cancel := chromedp.NewContext(
		context.Background(),
		chromedp.WithLogf(log.Printf),
	)
	defer cancel()

	var nodes []*cdp.Node
	err := chromedp.Run(ctx,
		chromedp.Navigate("https://www.cnblogs.com/"),
		chromedp.WaitVisible(`#footer`, chromedp.ByID),
		chromedp.Nodes(`.//a[@class="titlelnk"]`, &nodes),
	)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("get nodes:", len(nodes))
	// print titles
	for _, node := range nodes {
		fmt.Println(node.Children[0].NodeValue, ":", node.AttributeValue("href"))
	}
}

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

向強大的SVG邁進

作者:凹凸曼 – 暖暖

SVG 即 Scalable Vector Graphics 可縮放矢量圖形,使用XML格式定義圖形。

一、SVG印象

SVG 的應用十分廣泛,得益於 SVG 強大的各種特性。

1.1、 矢量

可利用 SVG 矢量的特點,描出深圳地鐵的輪廓:

1.2、iconfont

SVG 可依據一定的規則,轉成 iconfont 使用:

1.3、 foreignObject

利用 SVG 的 foreignObject 標籤實現截圖功能,原理:foreignObject 內部嵌入 HTML 元素:

<svg xmlns="http://www.w3.org/2000/svg">
	<foreignObject width="120" height="60">
		<p style="font-size:20px;margin:0;">凹凸實驗室 歡迎您</p>
	</foreignObject>
</svg>

截圖實現流程:

  1. 首先聲明一個基礎的 svg 模版,這個模版需要一些基礎的描述信息,最重要的,它要有 <foreignObject></foreignObject> 這對標籤;
  2. 將要渲染的 DOM 模版模版嵌入 foreignObject 即可;
  3. 利用 Blob 構建 svg 對象;
  4. 利用 URL.createObjectURL(svg) 取出 URL。

1.4、SVG SMIL

由於微信編輯器不允許嵌入 <style><script><a> 標籤,利用SVG SMIL 可進行微信公眾號極具創意的圖文排版設計,包括動畫與交互。
但是也要注意,標籤里不允許有id,否則會被過濾或替換掉。

點擊 “凹凸實驗室” 后,圍繞 “凹凸實驗室” 中心旋轉 360度,點擊0.5秒后 出現 https://aotu.io/ ,動畫只運行一次。

下圖為 GIF循環演示:

代碼如下:

<svg width="360" height="300" xmlns="http://www.w3.org/2000/svg">
    <g>
        <!-- 點擊后 運行transform旋轉動畫,restart="never"表示只運行一次 -->
        <animateTransform attributeName="transform" type="rotate" begin="click" dur="0.5s" from="0 100 80" to="360 100 80"  fill="freeze" restart="never" />
        <g>
            <text font-family="microsoft yahei" font-size="20" x="50" y="80">
                凹凸實驗室
            </text>
        </g>
        <g style="opacity: 0;">
            <!-- 同一個初始位置以及大致的寬高,觸發點擊事件 -->
            <text font-family="microsoft yahei" font-size="20" x="50" y="80">https://aotu.io/</text>
            <!-- 點擊后 運行transform移動動畫,改變文本的位置 -->
            <animateTransform attributeName="transform" type="translate" begin="click" dur="0.1s" to="0 40"  fill="freeze" restart="never" />
            <!-- 點擊0.5秒后 運行opacity显示動畫 -->
            <animate attributeName="opacity" begin="click+0.5s" from="0" to="1" dur="0.5s" fill="freeze" restart="never" />
        </g>
    </g>
</svg>

以上是鄙人對SVG的大致印象,最近的需求開發再次刷新了我的認知,那就是 SVG實現非比例縮放 以及 小程序不支持SVG標籤的處理,下面容我來講述一番。

二、SVG 實現非比例縮放

我們熟知的 iconfont,可通過改變字體大小縮放,但是這是 比例縮放,那如何實現 SVG 的非比例縮放呢?
如下圖所示,如何將 一隻兔子 非比例縮放?

划重點:實現非比例縮放主要涉及三個知識點:viewport、viewBox和preserveAspectRatio,viewport 與viewBox 結合可實現縮放的功能,viewBox 與 preserveAspectRatio 結合可實現非比例的功能。

2.1、viewport

viewport 表示SVG可見區域的大小。
viewport 就像是我們的显示器屏幕大小,超出區域則隱藏,原點位於左上角,x 軸水平向右,y 軸垂直向下。

通過類似CSS的屬性 widthheight 指定視圖大小:

<svg width="400" height="200"></svg>

2.2、viewBox

viewBox值有4個数字:x, y, width, height 。
其中 x:左上角橫坐標,y:左上角縱坐標,width:寬度,height:高度。
原點默認位於左上角,x 軸水平向右,y 軸垂直向下。

<svg width="400" height="200" viewBox="0 0 200 100"></svg>

显示器屏幕的畫面,可以特寫,可以全景,這就是 viewBox
viewBox 可以想象成截屏工具選中的那個框框,和 viewport 作用的結果就是 把框框中的截屏內容再次在 显示器 中全屏显示。

(圖片來源:SVG 研究之路 (23) – 理解 viewport 與 viewbox)

2.3、preserveAspectRatio

上圖的紅色框框和藍色框框,恰好和显示器的比例相同,如果是下圖的綠色框框,怎樣在显示器屏幕中显示呢?

2.3.1、 定義

preserveAspectRatio 作用的對象是 viewBox,使用方法如下:

preserveAspectRatio="[defer] <align> [<meetOrSlice>]"
// 例如 preserveAspectRatio="xMidYMid meet"

其中 defer 此時不是重點,暫且忽略,主要了解 alignmeetOrSlice 的 用法:

  • align:由兩個名詞組成,分別代表 viewbox 與 viewport 的 x 方向、y方向的對齊方式。
含義
xMin viewport 和 viewBox 左邊對齊
xMid viewport 和 viewBox x軸中心對齊
xMax viewport 和 viewBox 右邊對齊
YMin viewport 和 viewBox 上邊緣對齊。注意Y是大寫。
YMid viewport 和 viewBox y軸中心點對齊。注意Y是大寫。
YMax viewport 和 viewBox 下邊緣對齊。注意Y是大寫。
  • meetOrSlice:表示如何維持高寬的比例,有三個值 meet、slice、none。
    • meet – 默認值,保持縱橫比縮放 viewBox 適應 viewport,可能會有餘留的空白。
    • slice – 保持縱橫比同時比例小的方向放大填滿 viewport,超出的部分被剪裁掉。
    • none – 扭曲縱橫比以充分適應 viewport。
2.3.2、 例子

例子1:preserveAspectRatio="xMidYMid meet" 表示 綠色框框 與 显示器的 x 方向、y方向的 中心點 對齊;

例子2:preserveAspectRatio="xMidYMin slice" 表示 綠色框框 與 显示器的 x 方向 中心點 對齊,Y 方向 上邊緣對齊,保持比例放大填滿 显示屏 后超出部分隱藏;

例子3:preserveAspectRatio="xMidYMid slice" 表示 綠色框框 與 显示器的 x 方向、y方向的 中心點 對齊,保持比例放大填滿显示屏 后超出部分隱藏;

例子4:preserveAspectRatio="none" 不管三七二十一,隨意縮放綠色框框,填滿 显示屏即可;這就是非比例縮放的答案了。

三、小程序不支持svg標籤怎麼辦

微信小程序官方不支持 SVG 標籤的,但是決定曲線救國,相當於自己實現了一個SVG標籤:使用小程序內置的 Canvas 渲染器, 在 Cax 中實現 SVG 標準的子集,使用 JSX 或者 HTM(Hyperscript Tagged Markup) 描述 SVG 結構行為表現。

但是今天我想講講其他的。
我們知道,小程序雖然不支持 SVG 標籤,但是支持 svg 轉成 base64 後作為 background-imageurl,如 background-image: url("data:image/svg+xml.......)

但是我這邊還有個需求,隨時更改 SVG 每個路徑的顏色,即 顏色可配置:

來迴轉 Base64 肯定是比較麻煩的,有沒有更好的方式呢?
直接貼答案:對於SVG圖形,還有更好的實現方式,就是直接使用SVG XML格式代碼,無需進行base64轉換。

3.1、URL 編碼

直接使用 SVG XML 格式代碼,首先要了解 Data URI的格式。
划重點:base64非必選項,不指定的時候,後面的 <data> 將使用 URL編碼。

3.1.1、入門

百分號編碼(Percent-encoding), 也稱作URL編碼(URL encoding),是特定上下文的統一資源定位符 (URL)的編碼機制。

原理:ASCII 字符 = % + 兩位 ASCII 碼(十六進制)。
例如,字符 a 對應的 ASCII 碼為 0x61,那麼 URL 編碼后得到 %61 。

3.1.2、URL 編碼壓縮

前言:

Data URI 的格式中的 <data> 完全使用URL 編碼也是可以的,如 encodeURIComponent('<svg version="1.1" viewBox= …</svg>')
但是和轉義前原始SVG相比,可讀性差了很多,而且佔用體積也變大了。
如果深入了解URL 編碼的話,<data> 沒必要全部編碼的。

正文:

RFC3986文檔規定,URL中只允許包含 未保留字符 以及 所有保留字符。

  • 未保留字符:包含英文字母(a-zA-Z)、数字(0-9)、-_.~ 4個特殊字符。對於未保留字符,不需要百分號編碼。
  • 保留字符:具有特殊含義的字符 :/?#[]@ (分隔Url的協議、主機、路徑等組件) 和 !$&'()*+,;= (用於在每個組件中起到分隔作用的,如&符號用於分隔查詢多個鍵值對)。
  • 受限字符或不安全字符:直接放在Url中的時候,可能會引起解析程序的歧義,因此這部分需要百分號編碼,如%空格雙引號"尖號 <>等等。

綜上所述,只需要對 受限字符或不安全字符 進行編碼即可。

  • JS 處理比較簡單,利用 replace 將 需要編碼的字符 替換掉 即可,基本替換 以下的符號 就夠用了:
svgToUrl (svgData) {
    encoded = encoded
      .replace(/<!--(.*)-->/g, '') // 親測必須去掉註釋
      .replace(/[\r\n]/g, ' ') // 親測最好去掉換行
      .replace(/"/g, `'`) // 單引號是保留字符,雙引號改成單引號減少編碼
      .replace(/%/g, '%25')
      .replace(/&/g, '%26')
      .replace(/#/g, '%23')
      .replace(/{/g, '%7B')
      .replace(/}/g, '%7D')
      .replace(/</g, '%3C')
      .replace(/>/g, '%3E')
    return `data:image/svg+xml,${encoded}`
  }
  • 如果使用在 CSS 中,可利用 SASS版本3.3以上 的 三個API 對 SVG字符串做替換處理。

    1. str_insert(string, insert, index): 從 $string$index 插入字符 $insert
    2. str_index(string, substring): 返回 $substring$string 中第一個位置;
    3. str_slice(string, start_at, end_at = nil): 返回從字符 $string 中第 $start_at 開始到 $end_at 結束的一個新字符串。

    前人已有總結,可前往 https://github.com/leeenx/sass-svg/blob/master/sass-encodeuri.scss 查看完整代碼。

3.2、SVG 壓縮

一般從 Sketch 導出 SVG ,冗餘代碼比較多,有條件的話建議使用 SVGO 壓縮SVG的原本體積,比如清除換行、重複空格;刪除文檔聲明;刪除註釋;刪除desc描述等等。

四、總結

SVG強大的地方在於,出其不意,炫酷,與眾不同。

無論是微信公眾號花式排版,foreignObject 標籤實現截圖,實現非比例縮放,或者 背景圖直接使用 SVG XML 格式代碼,還是上文沒有提及的路徑動畫、描邊動畫、圖形裁剪、濾鏡等等,都可以玩出新的花樣。

SVG 一個屬性可成就一篇文章,學習 SVG 可以說是在挑戰自己,歡迎加入 SVG 的學習隊列。

五、參考內容 · 推薦閱讀

三看 SVG Web 動效
URL編碼的奧秘
學習了,CSS中內聯SVG圖片有比Base64更好的形式
超級強大的SVG SMIL animation動畫詳解
詳細教你微信公眾號正文頁SVG交互開發
SVG 簡介與截圖等應用

歡迎關注凹凸實驗室博客:aotu.io

或者關注凹凸實驗室公眾號(AOTULabs),不定時推送文章:

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

南投搬家公司費用需注意的眉眉角角,別等搬了再說!

新北清潔公司,居家、辦公、裝潢細清專業服務

※教你寫出一流的銷售文案?