“等風來不如追風去,追逐的過程就是人生的意義”。
借朋友吉言,“2018在頭條,2019成為頭條”,這就是我2019的目標,我已經在追風的路上。你呢?不要停下腳步,繼續前行吧。
今天來個實用的小知識,看下圖:
CSS3徑向漸變實現優惠券波浪造型
很多人看到左右的波浪邊框,第一想法,應該是用圖片實現。現在我們就打破這一想法,用CSS搞定這個效果。
radial-gradient() 函數用徑向漸變創建 "圖像"。徑向漸變由中心點定義。為了創建徑向漸變你必須設置兩個終止色。
語法: background: radial-gradient(shape size at position, start-color, ..., last-color);
CSS3徑向漸變實現優惠券波浪造型
<div class="coupon"></div>
這里用radial-gradient繪制一個圓,設置left為1px,top為8px,形成半圓。
.coupon { position: relative; width: 400px; height: 160px; margin: 50px auto; background-image: radial-gradient( circle at 1px 8px, transparent 6px, #ff9e6d 6px, #ff9e6d 0px); }
CSS3徑向漸變實現優惠券波浪造型
看看原本是這樣,這里的left是8px
.coupon { ... background-image: radial-gradient( circle at 8px 8px, transparent 6px, #ff9e6d 6px, #ff9e6d 0px); ... }
CSS3徑向漸變實現優惠券波浪造型
設置背景大小,y軸默認平鋪,x軸不允許平鋪,形成多個半圓,造就波浪造型。
.coupon { ... background-image: radial-gradient( circle at 1px 8px, transparent 6px, #ff9e6d 6px, #ff9e6d 0px); background-size: 200px 18px; background-repeat-x: no-repeat; ... }
CSS3徑向漸變實現優惠券波浪造型
同理,我們添加右邊波浪,
.coupon { ... background-image: radial-gradient( circle at 1px 8px, transparent 6px, #ff9e6d 6px, #ff9e6d 0px), radial-gradient( circle at 199px 8px, transparent 6px, #ff9e6d 6px, #ff9e6d 0px); background-size: 200px 18px; background-position: 0 0, 200px 0; background-repeat-x: no-repeat; }
CSS3徑向漸變實現優惠券波浪造型
<div class="coupon">50元</div>
用:before偽類,制作中間的虛線,:after偽類,添加“立即領取”文字。同時添加金額(50元)樣式。
.coupon { ... font-size: 60px; color: #fff; font-weight: bold; line-height: 160px; padding-left: 60px; box-sizing: border-box; cursor: pointer; } .coupon::before { position: absolute; content: ""; left: 240px; top: 0; bottom: 0; width: 0; border-left: 1px dashed #fff; } .coupon::after { position: absolute; content: "立即領取"; font-size: 26px; width: 70px; top: 50%; right: 2%; transform: translate(-50%, -50%); line-height: 40px; letter-spacing: 5px; }
CSS3徑向漸變實現優惠券波浪造型
演示地址:CSS3徑向漸變實現優惠券波浪造型
CSS3 box-shadow實現背景動畫
從淺到深的學習 CSS3陰影(box-shadow)
CSS3線性漸變、陰影、縮放實現動畫下雨效果
下文章來源于GoUpUp ,作者dj
go-app是一個使用 Go + WebAssembly 技術編寫漸進式 Web 應用的庫。WebAssembly 是一種可以運行在現代瀏覽器中的新式代碼。近兩年來,WebAssembly 技術取得了較大的發展。我們現在已經可以使用 C/C++/Rust/Go 等高級語言編寫 WebAssembly 代碼。本來就來介紹go-app這個可以方便地使用 Go 語言來編寫 WebAssembly 代碼的庫。
go-app對 Go 語言版本有較高的要求(Go 1.14+),而且必須使用Go module。先創建一個目錄并初始化Go Module(Win10 + Git Bash):
$ mkdir go-app && cd go-app
$ go mod init
然后下載安裝go-app包:
$ go get -u -v github.com/maxence-charriere/go-app/v6
至于Go module的詳細使用,去看煎魚大佬的Go Modules 終極入門。
首先,我們要編寫 WebAssembly 程序:
package main
import "github.com/maxence-charriere/go-app/v6/pkg/app"
type Greeting struct {
app.Compo
name string
}
func (g *Greeting) Render() app.UI {
return app.Div().Body(
app.Main().Body(
app.H1().Body(
app.Text("Hello, "),
app.If(g.name != "",
app.Text(g.name),
).Else(
app.Text("World"),
),
),
),
app.Input().
Value(g.name).
Placeholder("What is your name?").
AutoFocus(true).
OnChange(g.OnInputChange),
)
}
func (g *Greeting) OnInputChange(src app.Value, e app.Event) {
g.name = src.Get("value").String()
g.Update()
}
func main() {
app.Route("/", &Greeting{})
app.Run()
}
在go-app中使用組件來劃分功能模塊,每個組件結構中必須內嵌app.Compo。組件要實現Render()方法,在需要顯示該組件時會調用此方法返回顯示的頁面。go-app使用聲明式語法,完全使用 Go 就可以編寫 HTML 頁面,上面繪制 HTML 的部分比較好理解。上面代碼中還實現了一個輸入框的功能,并為它添加了一個監聽器。每當輸入框內容有修改,OnInputChange方法就會調用,g.Update()會使該組件重新渲染顯示。
最后將該組件掛載到路徑/上。
編寫 WebAssembly 程序之后,需要使用交叉編譯的方式將它編譯為.wasm文件:
$ GOARCH=wasm GOOS=js go build -o app.wasm
如果編譯出現錯誤,使用go version命令檢查 Go 是否是 1.14 或更新的版本。
接下來,我們需要編寫一個 Go Web 程序使用這個app.wasm:
package main
import (
"log"
"net/http"
"github.com/maxence-charriere/go-app/v6/pkg/app"
)
func main() {
h := &app.Handler{
Title: "Go-App",
Author: "dj",
}
if err := http.ListenAndServe(":8080", h); err != nil {
log.Fatal(err)
}
}
go-app提供了一個app.Handler結構,它會自動查找同目錄下的app.wasm(這也是為什么將目標文件設置為app.wasm的原因)。然后我們將前面編譯生成的app.wasm放到同一目錄下,執行該程序:
$ go run main.go
默認顯示"Hello World":
在輸入框中輸入內容之后,顯示會隨之變化:
可以看到,go-app為我們設置了一些基本的樣式,網頁圖標等。
GitHub 上這張圖很好地說明了 HTTP 請求的執行流程:
用戶請求先到app.Handler層,它會去app.wasm中執行相關的路由邏輯、去磁盤上查找靜態文件。響應經由app.Handler中轉返回給用戶。用戶就看到了app.wasm渲染的頁面。實際上,在本文中我們只需要編寫一個 Go Web 程序,每次編寫新的 WebAssembly 之后,將新編譯生成的 app.wasm 文件拷貝到 Go Web 目錄下重新運行程序即可。注意,如果頁面未能及時刷新,可能是緩存導致的,可嘗試清理瀏覽器緩存。
自定義一個組件很簡單,只需要將app.Compo內嵌到結構中即可。實現Render()方法可定義組件的外觀,實際上app.Compo有一個默認的外觀,我們可以這樣來查看:
func main() {
app.Route("/app", &app.Compo{})
app.Run()
}
編譯生成app.wasm之后,一開始的 Go Web 程序不需要修改,直接運行,打開瀏覽器查看:
在快速開始中,我們還介紹了如何使用事件。使用聲明式語法app.Input().OnChange(handler)即可監聽內容變化。事件處理函數必須為func (src app.Value, e app.Event)類型,app.Value是觸發對象,app.Event是事件的內容。通過app.Value我們可以得到輸入框內容、選擇框的選項等信息,通過app.Event可以得到事件的信息,是鼠標事件、鍵盤事件還是其它事件:
type ShowSelect struct {
app.Compo
option string
}
func (s *ShowSelect) Render() app.UI {
return app.Div().Body(
app.Main().Body(
app.H1().Body(
app.If(s.option == "",
app.Text("Please select!"),
).Else(
app.Text("You've selected "+s.option),
),
),
),
app.Select().Body(
app.Option().Body(
app.Text("apple"),
),
app.Option().Body(
app.Text("orange"),
),
app.Option().Body(
app.Text("banana"),
),
).
OnChange(s.OnSelectChange),
)
}
func (s *ShowSelect) OnSelectChange(src app.Value, e app.Event) {
s.option = src.Get("value").String()
s.Update()
}
func main() {
app.Route("/", &ShowSelect{})
app.Run()
}
上面代碼顯示一個選擇框,當選項改變時上面顯示的文字會做相應的改變。初始時:
選擇后:
組件可以嵌套使用,即在一個組件中使用另一個組件。渲染時將內部的組件表現為外部組件的一部分:
type Greeting struct {
app.Compo
}
func (g *Greeting) Render() app.UI {
return app.P().Body(
app.Text("Hello, "),
&Name{name: "dj"},
)
}
type Name struct {
app.Compo
name string
}
func (n *Name) Render() app.UI {
return app.Text(n.name)
}
func main() {
app.Route("/", &Greeting{})
app.Run()
}
上面代碼在組件Greeting中內嵌了一個Name組件,運行顯示:
go-app提供了組件的 3 個生命周期的鉤子函數:
例如:
type Foo struct {
app.Compo
}
func (*Foo) Render() app.UI {
return app.P().Body(
app.Text("Hello World"),
)
}
func (*Foo) OnMount() {
fmt.Println("component mounted")
}
func (*Foo) OnNav(u *url.URL) {
fmt.Println("component navigated:", u)
}
func (*Foo) OnDismount() {
fmt.Println("component dismounted")
}
func main() {
app.Route("/", &Foo{})
app.Run()
}
編譯運行,在瀏覽器中打開頁面,打開瀏覽器控制臺觀察輸出:
component mounted
component navigated: http://localhost:8080/
在前面的例子中我們已經看到了如何使用聲明式語法編寫 HTML 頁面。go-app為所有標準的 HTML 元素都提供了相關的類型。創建這些對象的方法名也比較好記,就是元素名的首字母大寫。如app.Div()創建一個div元素,app.P()創建一個p元素,app.H1()創建一個h1元素等等。在go-app中,這些結構都是暴露出對應的接口供開發者使用的,如div對應HTMLDiv接口:
type HTMLDiv interface {
Body(nodes ...Node) HTMLDiv
Class(v string) HTMLDiv
ID(v string) HTMLDiv
Style(k, v string) HTMLDiv
OnClick(h EventHandler) HTMLDiv
OnKeyPress(h EventHandler) HTMLDiv
OnMouseOver(h EventHandler) HTMLDiv
}
可以看到每個方法都返回該HTMLDiv自身,所以支持鏈式調用。調用這些方法可以設置元素的各方面屬性:
和設置事件監聽:
例如下面代碼:
app.Div().Body(
app.H1().Body(
app.Text("Title"),
),
app.P().ID("id").
Class("content").Body(
app.Text("something interesting"),
),
)
相當于 HTML 代碼:
<div>
<h1>title</h1>
<p id="id" class="content">
something interesting
</p>
</div>
我們可以在app.Raw()中直接寫 HTML 代碼,app.Raw()會生成對應的app.UI返回:
svg := app.Raw(`
<svg width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
`)
但是這種寫法是不安全的,因為沒有檢查 HTML 的結構。
我們在最開始的例子中就已經用到了條件語句,條件語句對應 3 個方法:If()/ElseIf()/Else()。
If和ElseIf接收兩個參數,第一個參數為bool值。如果為true,則顯示第二個參數(類型為app.UI),否則不顯示。
Else必須在If或ElseIf后使用,如果前面的條件都不滿足,則顯示傳入Else方法的app.UI:
type ScoreUI struct {
app.Compo
score int
}
func (c *ScoreUI) Render() app.UI {
return app.Div().Body(
app.If(c.score >= 90,
app.H1().
Style("color", "green").
Body(
app.Text("Good!"),
),
).ElseIf(c.score >= 60,
app.H1().
Style("color", "orange").
Body(
app.Text("Pass!"),
),
).Else(
app.H1().
Style("color", "red").
Body(
app.Text("fail!"),
),
),
app.Input().
Value(c.score).
Placeholder("Input your score?").
AutoFocus(true).
OnChange(c.OnInputChange),
)
}
func (c *ScoreUI) OnInputChange(src app.Value, e app.Event) {
score, _ := strconv.ParseUint(src.Get("value").String(), 10, 32)
c.score = int(score)
c.Update()
}
func main() {
app.Route("/", &ScoreUI{})
app.Run()
}
上面我們根據輸入的分數顯示對應的文字,90及以上顯示綠色的Good!,60-90之間顯示橙色的Pass!,小于60顯示紅色的Fail!。下面是運行結果:
假設我們要編寫一個 HTML 列表,當前有一個字符串的切片。如果一個個寫就太繁瑣了,而且不夠靈活,且容易出錯。這時就可以使用Range()方法了:
type RangeUI struct {
app.Compo
name string
}
func (*RangeUI) Render() app.UI {
langs := []string{"Go", "JavaScript", "Python", "C"}
return app.Ul().Body(
app.Range(langs).Slice(func(i int) app.UI {
return app.Li().Body(
app.Text(langs[i]),
)
}),
)
}
func main() {
app.Route("/", &RangeUI{})
app.Run()
}
Range()可以對切片或map中每一項生成一個app.UI,然后平鋪在某個元素的Body()方法中。
運行結果:
在go-app中,我們可以很方便的自定義右鍵彈出的菜單,并且為菜單項編寫響應:
type ContextMenuUI struct {
app.Compo
name string
}
func (c *ContextMenuUI) Render() app.UI {
return app.Div().Body(
app.Text("Hello, World"),
).OnContextMenu(c.OnContextMenu)
}
func (*ContextMenuUI) OnContextMenu(src app.Value, event app.Event) {
event.PreventDefault()
app.NewContextMenu(
app.MenuItem().
Label("item 1").
OnClick(func(src app.Value, e app.Event) {
fmt.Println("item 1 clicked")
}),
app.MenuItem().Separator(),
app.MenuItem().
Label("item 2").
OnClick(func(src app.Value, e app.Event) {
fmt.Println("item 2 clicked")
}),
)
}
func main() {
app.Route("/", &ContextMenuUI{})
app.Run()
}
我們在OnContextMenu中調用了event.PreventDefault()阻止默認菜單的彈出。看運行結果:
點擊菜單項,觀察控制臺輸出~
上面我們都是使用go-app內置的app.Handler處理客戶端的請求。我們只設置了簡單的兩個屬性Author和Title。app.Handler還有其它很多字段可以定制:
type Handler struct {
Author string
BackgroundColor string
CacheableResources []string
Description string
Env Environment
Icon Icon
Keywords []string
LoadingLabel string
Name string
RawHeaders []string
RootDir string
Scripts []string
ShortName string
Styles []string
ThemeColor string
Title string
UseMinimalDefaultStyles bool
Version string
}
CSS 和 JS 文件必須在app.Handler中聲明。下面是一個示例app.Handler:
h := &app.Handler{
Name: "Luck",
Author: "Maxence Charriere",
Description: "Lottery numbers generator.",
Icon: app.Icon{
Default: "/web/icon.png",
},
Keywords: []string{
"EuroMillions",
"MEGA Millions",
"Powerball",
},
ThemeColor: "#000000",
BackgroundColor: "#000000",
Styles: []string{
"/web/luck.css",
},
Version: "wIKiverSiON",
}
本文中 WebAssembly 代碼都在各自的目錄中。Go Web 演示代碼在 web 目錄中。先進入某個目錄,使用下面的命令編譯:
$ GOARCH=wasm GOOS=js go build -o app.wasm
然后將生成的app.wasm拷貝到web目錄:
$ cp app.wasm ../web/
切換到 web 目錄,啟動服務器:
$ cd ../web/
$ go run main.go
本文介紹如何使用go-app編寫基于 WebAssembly 的 Web 應用程序。可能有人會覺得,go-app編寫 HTML 的方式有點繁瑣。但是我們可以寫一個轉換程序將普通的 HTML 代碼轉為go-app代碼,感興趣可以自己實現一下。WebAssembly 技術非常值得關注一波~
屬性解釋
background屬性是css中應用比較多,且比較重要的一個屬性,它是負責給盒子設置背景圖片和背景顏色的,background是一個復合屬性,它可以分解成如下幾個設置項:
background-color 設置背景顏色
background-image 設置背景圖片地址
background-repeat 設置背景圖片如何重復平鋪
background-position 設置背景圖片的位置
background-attachment 設置背景圖片是固定還是隨著頁面滾動條滾動
實際應用中,我們可以用background屬性將上面所有的設置項放在一起,而且也建議這么做,這樣做性能更高,而且兼容性更好,比如:“background: #00FF00 url(bgimage.gif) no-repeat left center fixed”,這里面的“#00ff00”是設置background-color;“url(bgimage.gif)”是設置background-image;“no-repeat”是設置background-repeat;“left center”是設置background-position;“fixed”是設置background-attachment,各個設置項用空格隔開,有的設置項不寫也是可以的,它會使用默認值。
舉例:
下面這些例子使用下面這張圖片做為背景圖:
1、“background:url(bg.jpg)”,默認設置一個圖片地址,圖片會從盒子的左上角開始將盒子鋪滿。
2、“background:cyan url(bg.jpg) repeat-x”,橫向平鋪盒子,盒子其他部分顯示背景顏色“cyan”。
3、“background:cyan url(bg.jpg) repeat-y”,縱向平鋪盒子,盒子其他部分顯示背景顏色“cyan”。
4、“background:cyan url(bg.jpg) no-repeat”,背景不重復,背景和盒子左上角對齊,盒子其他部分顯示背景顏色“cyan”。
5、“background:cyan url(bg.jpg) no-repeat left center”,背景不重復,背景和盒子左中對齊,盒子其他部分顯示背景顏色“cyan”。
6、“background:cyan url(bg.jpg) no-repeat right center”,背景不重復,背景和盒子右中對齊,也就是背景圖片的右邊對齊盒子的右邊,盒子其他部分顯示背景顏色“cyan”。
相關代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test background</title> <style type="text/css"> .backshow{ width:320px; height:160px; border:3px solid #333; float:left; margin:10px; } .bg1{background:cyan url(bg.jpg);} .bg2{background:cyan url(bg.jpg) repeat-x;} .bg3{background:cyan url(bg.jpg) repeat-y;} .bg4{background:cyan url(bg.jpg) no-repeat;} .bg5{background:cyan url(bg.jpg) no-repeat left center;} .bg6{background:cyan url(bg.jpg) no-repeat right center;} </style> </head> <body> <div class="backshow bg1"></div> <div class="backshow bg2"></div> <div class="backshow bg3"></div> <div class="backshow bg4"></div> <div class="backshow bg5"></div> <div class="backshow bg6"></div> </body> </html>
例子說明:
background-position的設置,可以在水平方向設置“left”、“center”、“right”,在垂直方向設置“top”、“center”、“bottom”,除了設置這些方位詞之外,還可以設置具體的數值。
比如說,我們想把下邊的盒子用右邊的圖片作為背景,并且讓背景顯示圖片中靠近底部的那朵花:
用上面中間那張圖片作為左邊那個比它尺寸小的盒子的背景,上面右邊的實現效果設置為:“background:url(location_bg.jpg) -110px -150px”,第一個數值表示背景圖相對于自己的左上角向左偏移110px,負值向左,正值向右,第二個數值表示背景圖相對于自己的左上角向上偏移150px,負值向上,正值向下。
實現原理示意圖:
對應代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test background</title> <style type="text/css"> .backshow{ width:320px; height:160px; border:3px solid #333; float:left; margin:10px; } .bg{width:94px; height:94px; border:3px solid #666; background:url(location_bg.jpg) -110px -150px; } </style> </head> <body> <div class="bg"></div> </body> </html>
理解練習:
通過雪碧圖制作如下布局:
*請認真填寫需求信息,我們會在24小時內與您取得聯系。