feat: 新增模块
10
docs/fea/Q&A/index.md
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 💊 Q&A
|
||||
order: 100
|
||||
---
|
||||
|
||||
## 问题合集
|
@ -3,7 +3,7 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: canvas
|
||||
title: 💊 canvas
|
||||
order: 1
|
||||
---
|
||||
|
||||
|
@ -3,7 +3,7 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: canvas
|
||||
title: 💊 canvas
|
||||
order: 2
|
||||
---
|
||||
|
||||
|
@ -3,12 +3,16 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: canvas
|
||||
title: 💊 canvas
|
||||
order: 6
|
||||
---
|
||||
|
||||
## 动画案例
|
||||
|
||||
### 液体海报
|
||||
|
||||
<code src="./demos/demo1/index.jsx" />
|
||||
|
||||
### 大转盘(doing)
|
||||
|
||||
```jsx
|
||||
|
BIN
docs/fea/canvas/demos/demo1/img/clipImg1.jpg
Normal file
After Width: | Height: | Size: 166 KiB |
BIN
docs/fea/canvas/demos/demo1/img/clipImg2.jpg
Normal file
After Width: | Height: | Size: 150 KiB |
118
docs/fea/canvas/demos/demo1/index.jsx
Normal file
@ -0,0 +1,118 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
const img1 = require('./img/clipImg1.jpg')
|
||||
const img2 = require('./img/clipImg2.jpg')
|
||||
|
||||
export default () => {
|
||||
const canvasRef = useRef()
|
||||
const clipImgs1Ref = useRef()
|
||||
const clipImgs2Ref = useRef()
|
||||
|
||||
|
||||
function clipPathMaskRender() {
|
||||
const NUM_CIRCLES = 60
|
||||
const MIN_SIZE = 50
|
||||
const MAX_SIZE = 100
|
||||
|
||||
function getRndInt(min, max) {
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min
|
||||
}
|
||||
|
||||
var c = canvasRef && canvasRef.current
|
||||
var ctx = c.getContext('2d')
|
||||
var clipImg1 = clipImgs1Ref && clipImgs1Ref.current
|
||||
var clipImg2 = clipImgs2Ref && clipImgs2Ref.current
|
||||
var t
|
||||
|
||||
class Circle {
|
||||
constructor() {
|
||||
this.x = 0
|
||||
this.y = 0
|
||||
this.size = 0
|
||||
this._needsRandomized = false
|
||||
}
|
||||
|
||||
randomize () {
|
||||
this.x = getRndInt(50, c.width - 50)
|
||||
this.y = getRndInt(50, c.height - 50)
|
||||
this.maxSize = getRndInt(MIN_SIZE, MAX_SIZE)
|
||||
}
|
||||
|
||||
// 更新
|
||||
update (t, ofs) {
|
||||
// abs 绝对值
|
||||
this.size = Math.abs(Math.round(Math.sin(t + ofs) * this.maxSize))
|
||||
|
||||
if (this.size < 2) {
|
||||
if (this._needsRandomized) {
|
||||
this.randomize()
|
||||
this._needsRandomized = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 画
|
||||
draw () {
|
||||
ctx.moveTo(this.x, this.y)
|
||||
ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI)
|
||||
}
|
||||
}
|
||||
|
||||
var circles =[]
|
||||
for (let i = 0; i < NUM_CIRCLES; i++) {
|
||||
var circle = new Circle()
|
||||
circle.randomize()
|
||||
circles.push(circle)
|
||||
}
|
||||
|
||||
function update() {
|
||||
t = 0.001 * Date.now()
|
||||
circles.forEach((circle, idx) => {
|
||||
circle.update(t, idx)
|
||||
})
|
||||
}
|
||||
|
||||
async function render() {
|
||||
await ctx.drawImage(clipImg1, 0, 0)
|
||||
await ctx.save()
|
||||
await ctx.beginPath()
|
||||
|
||||
circles.forEach(function(circle) {
|
||||
circle.draw()
|
||||
})
|
||||
|
||||
ctx.closePath()
|
||||
ctx.clip()
|
||||
|
||||
ctx.drawImage(clipImg2, 0, 0)
|
||||
ctx.restore()
|
||||
}
|
||||
|
||||
function loop() {
|
||||
requestAnimationFrame(loop)
|
||||
update()
|
||||
render()
|
||||
}
|
||||
|
||||
loop()
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
clipPathMaskRender()
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="clipPathMask demo">
|
||||
<div className="wrap">
|
||||
<h1 className="wrap_tit">Nice Note</h1>
|
||||
<canvas ref={canvasRef} className="wrap_canvas" width="500px" height="500px"></canvas>
|
||||
</div>
|
||||
<div id="clipImgs">
|
||||
<img ref={clipImgs1Ref} id="clipImgs_1" crossOrigin="anonymous" src={img1} />
|
||||
<img ref={clipImgs2Ref} id="clipImgs_2" crossOrigin="anonymous" src={img2} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
18
docs/fea/canvas/demos/demo1/index.less
Normal file
@ -0,0 +1,18 @@
|
||||
.clipPathMask {
|
||||
text-align: center;
|
||||
height: 80vh;
|
||||
color: #fff;
|
||||
background: teal linear-gradient(transparent, #ff0099);
|
||||
.wrap {
|
||||
&_tit {
|
||||
padding: 10px 0;
|
||||
font-size: 30px;
|
||||
}
|
||||
&_canvas {
|
||||
border: 1px solid yellow;
|
||||
}
|
||||
}
|
||||
#clipImgs {
|
||||
display: none;
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: canvas
|
||||
title: 💊 canvas
|
||||
order: 4
|
||||
---
|
||||
|
||||
|
42
docs/fea/css/demos/demo1/index.less
Normal file
@ -0,0 +1,42 @@
|
||||
|
||||
.textMask {
|
||||
position: relative;
|
||||
height: 300px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
.bg {
|
||||
height: 300px;
|
||||
width: 100%;
|
||||
background-image: url('https://images4.alphacoders.com/284/284838.jpg');
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
transform: rotateY(180deg);
|
||||
transition: all 2.5s ease-in-out;
|
||||
}
|
||||
.text {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
background-image: url('https://images4.alphacoders.com/284/284838.jpg');
|
||||
background-size: 100% 100%;
|
||||
background-position: center;
|
||||
font-size: 50px;
|
||||
color: transparent;
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
line-height: 200px;
|
||||
transform: translate(-50%, -50%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
transition: all 2.5s ease-in-out;
|
||||
}
|
||||
&:hover {
|
||||
.text {
|
||||
background-size: 80% 80%;
|
||||
}
|
||||
.bg {
|
||||
background-size: 150% 150%;
|
||||
}
|
||||
}
|
||||
}
|
17
docs/fea/css/demos/demo1/index.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="demo textMask">
|
||||
<div className="bg"></div>
|
||||
<div className="text">
|
||||
Text Mask
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
BIN
docs/fea/css/demos/demo2/img/button1.png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
docs/fea/css/demos/demo2/img/button2.png
Normal file
After Width: | Height: | Size: 684 KiB |
BIN
docs/fea/css/demos/demo2/img/button3.png
Normal file
After Width: | Height: | Size: 1.9 MiB |
103
docs/fea/css/demos/demo2/index.less
Normal file
@ -0,0 +1,103 @@
|
||||
@keyframes ani {
|
||||
from {
|
||||
mask-position: 0 0;
|
||||
}
|
||||
to {
|
||||
mask-position: 100% 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ani2 {
|
||||
from {
|
||||
mask-position: 100% 0;
|
||||
}
|
||||
to {
|
||||
mask-position: 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.buttonMask {
|
||||
button {
|
||||
width: 101%;
|
||||
height: 100%;
|
||||
font-family: 'Righteous', cursive;
|
||||
font-weight: 300;
|
||||
font-size: 20px;
|
||||
letter-spacing: 1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.mas {
|
||||
margin-top: 12px;
|
||||
position: absolute;
|
||||
color: #000;
|
||||
text-align: center;
|
||||
width: 101%;
|
||||
font-family: 'Righteous' sans-serif;
|
||||
font-weight: 300;
|
||||
font-size: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.btn {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 6vh;
|
||||
overflow: hidden;
|
||||
border: 1px solid ;
|
||||
font-family: 'Righteous' sans-serif;
|
||||
font-weight: 300;
|
||||
font-size: 20;
|
||||
transition: .5s;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.button-container-1 {
|
||||
button {
|
||||
background: #000;
|
||||
mask: url('./img/button1.png');
|
||||
mask-size: 2300% 100%;
|
||||
border: none;
|
||||
color: #fff;
|
||||
-webkit-animation: ani2 .7s steps(22) forwards;
|
||||
animation: ani2 .7s steps(22) forwards;
|
||||
|
||||
&:hover {
|
||||
-webkit-animation: ani .7s steps(22) forwards;
|
||||
animation: ani .7s steps(22) forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-container-2 {
|
||||
button {
|
||||
background: #000;
|
||||
mask: url('./img/button2.png');
|
||||
mask-size: 3000% 100%;
|
||||
border: none;
|
||||
color: #fff;
|
||||
-webkit-animation: ani2 .7s steps(29) forwards;
|
||||
animation: ani2 .7s steps(29) forwards;
|
||||
|
||||
&:hover {
|
||||
-webkit-animation: ani .7s steps(29) forwards;
|
||||
animation: ani .7s steps(29) forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-container-3 {
|
||||
button {
|
||||
background: #000;
|
||||
mask: url('./img/button3.png');
|
||||
mask-size: 7100% 100%;
|
||||
border: none;
|
||||
color: #fff;
|
||||
-webkit-animation: ani2 0.7s steps(70) forwards;
|
||||
animation: ani2 0.7s steps(70) forwards;
|
||||
|
||||
&:hover {
|
||||
-webkit-animation: ani 0.7s steps(70) forwards;
|
||||
animation: ani 0.7s steps(70) forwards;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
docs/fea/css/demos/demo2/index.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="buttonMask">
|
||||
<div className="btn button-container-1">
|
||||
<span className="mas">MASK1</span>
|
||||
<button type="button" name="Hover">MASK1</button>
|
||||
</div>
|
||||
<div className="btn button-container-2">
|
||||
<span className="mas">MASK2</span>
|
||||
<button type="button" name="Hover">MASK2</button>
|
||||
</div>
|
||||
<div className="btn button-container-3">
|
||||
<span className="mas">MASK2</span>
|
||||
<button type="button" name="Hover">MASK2</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
BIN
docs/fea/css/demos/demo3/img/amazon_view.jpg
Normal file
After Width: | Height: | Size: 329 KiB |
47
docs/fea/css/demos/demo3/index.less
Normal file
@ -0,0 +1,47 @@
|
||||
.svgMask {
|
||||
position: relative;
|
||||
.rang {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
z-index: 10;
|
||||
svg {
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
text {
|
||||
text-anchor: middle;
|
||||
}
|
||||
.svgDemo {
|
||||
&_rect {
|
||||
fill: darken( #fff, 60%);
|
||||
}
|
||||
&_tit {
|
||||
letter-spacing: -2px;
|
||||
font-size: 6em;
|
||||
font-weight: 800;
|
||||
}
|
||||
&_subtit {
|
||||
letter-spacing: 8px;
|
||||
font-size: 1.2em;
|
||||
font-weight: 300;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
.down {
|
||||
fill: #000;
|
||||
mask: url(#svgDemo)
|
||||
}
|
||||
}
|
||||
}
|
||||
.intro {
|
||||
position: relative;
|
||||
background: url('./img/amazon_view.jpg');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
}
|
27
docs/fea/css/demos/demo3/index.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div class="svgMask">
|
||||
<div class="rang">
|
||||
<svg>
|
||||
<defs>
|
||||
<mask id="svgDemo" class="svgDemo" width="100%" heigth="100%" x="0" y="0">
|
||||
<rect class="svgDemo_rect" x="0" y="0" width="100%" height="100%" />
|
||||
|
||||
<text class="svgDemo_tit" x="50%" y="0" dy="1.58em">SVG + CSS</text>
|
||||
<text class="svgDemo_subtit" x="50%" y="0" dy="9.8em">welcome!</text>
|
||||
</mask>
|
||||
</defs>
|
||||
<rect class="down" x="0" y="0" width="100%" height="100%" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="intro">嗨,你好吗?</div>
|
||||
</div>
|
||||
)
|
||||
}
|
18
docs/fea/css/demos/demo4/img/dji.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="45px" height="26px" viewBox="0 0 45 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Group</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="block/navigation_primary_white" transform="translate(-165.000000, -12.000000)" fill="#303233">
|
||||
<g id="Group">
|
||||
<g transform="translate(165.000000, 12.000000)">
|
||||
<g id="systemicon/black/djilogo">
|
||||
<path d="M17.9822999,14.0172253 L21.3322723,0 L28.6674466,0 L24.8560701,15.9459198 C24.1224248,19.0236511 21.8345765,19.7624088 19.7179972,19.7624088 L2.81348162,19.7624088 C0.951249717,19.7624088 -0.609344073,18.9712479 0.235498266,15.4180531 L1.75902636,9.05809025 C2.52845917,5.83081808 4.92750466,5.09206033 6.6619238,5.09206033 L18.464154,5.09206033 L17.5119489,9.06831527 L11.4868555,9.06831527 C10.6023912,9.06831527 10.1167027,9.26131253 9.87002406,10.2927615 L8.89609083,14.354651 C8.54971825,15.8117164 9.05969116,15.9114104 10.1243714,15.9114104 L15.6458826,15.9114104 C16.6568816,15.9114104 17.5451803,15.8487821 17.9822999,14.0172253 Z M37.8744387,5.0897597 L45,5.0897597 L41.5477774,19.7626645 L34.422216,19.7626645 L37.8744387,5.0897597 Z M29.1385644,5.0897597 L36.2641257,5.0897597 L32.9461065,18.8807564 C31.5618943,24.6604494 27.6955583,25.9973709 25.077953,25.9973709 L15.0817171,25.9973709 L16.2767664,21.0254545 C16.2767664,21.0254545 21.5937772,21.0510171 21.7829401,21.0280108 C23.684794,20.869523 25.5777009,19.9441586 26.2333804,17.1974624 L29.1385644,5.0897597 Z" id="LOGO"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
50
docs/fea/css/demos/demo4/index.less
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
@keyframes move {
|
||||
0% {
|
||||
background-position: 0 0;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.realMask {
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
z-index: 1;
|
||||
height: 500px;
|
||||
&_bg {
|
||||
background-image: url('https://sp-webfront.skypixel.com/skypixel/v2/public/website/assets/1535027674204-f6eca6369ec03e70262b58b0e25cda7b.jpg');
|
||||
background-size: cover;
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
left: -20px;
|
||||
right: -20px;
|
||||
bottom: -20px;
|
||||
filter: blur(15px);
|
||||
z-index: -1;
|
||||
}
|
||||
&_mask {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 200px;
|
||||
height: 80px;
|
||||
animation: move 88s infinite;
|
||||
background-image: url(https://sp-webfront.skypixel.com/skypixel/v2/public/website/assets/1535027674204-f6eca6369ec03e70262b58b0e25cda7b.jpg);
|
||||
background-size: cover;
|
||||
mask-image: url('./img/dji.svg');
|
||||
mask-size: cover;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
&_slogan {
|
||||
color: white;
|
||||
margin-top: 24px;
|
||||
font-size: 36px;
|
||||
font-weight: 300;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
16
docs/fea/css/demos/demo4/index.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="realMask">
|
||||
<div className="realMask_bg"></div>
|
||||
<div className="realMask_mask"></div>
|
||||
<div className="realMask_slogan">NiceNote</div>
|
||||
</div>
|
||||
)
|
||||
}
|
32
docs/fea/css/demos/demo5/index.less
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
@keyframes Gradient {
|
||||
0%{background-position:50% 0%}
|
||||
50%{background-position:50% 100%}
|
||||
100%{background-position:50% 0%}
|
||||
}
|
||||
|
||||
.gradientMask {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-size: 50px;
|
||||
letter-spacing: 1px;
|
||||
font-weight: bold;
|
||||
background: linear-gradient(0deg, #e55d87, #5fc3e4);
|
||||
background-size: 400% 400%;
|
||||
animation: Gradient 4s linear infinite;
|
||||
svg {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
text {
|
||||
text-anchor: middle;
|
||||
}
|
||||
svg mask rect {
|
||||
fill: #eee;
|
||||
}
|
||||
svg > rect {
|
||||
fill: #eee;
|
||||
mask: url(#gradientMask_svg__mask);
|
||||
}
|
||||
}
|
28
docs/fea/css/demos/demo5/index.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="gradientMask">
|
||||
<svg
|
||||
className="gradientMask_svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="100%"
|
||||
height="100%"
|
||||
>
|
||||
<defs>
|
||||
<mask id="gradientMask_svg__mask" x="0" y="0" width="100%" height="100%">
|
||||
<rect x="0" y="0" width="100%" height="100%" />
|
||||
<text x="50%" y="1em">Hello</text>
|
||||
<text x="50%" y="2em">Motal</text>
|
||||
</mask>
|
||||
</defs>
|
||||
<rect x="0" y="0" width="100%" height="100%" />
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
}
|
BIN
docs/fea/css/demos/demo6/img/amazon_view.jpg
Normal file
After Width: | Height: | Size: 329 KiB |
47
docs/fea/css/demos/demo6/index.less
Normal file
@ -0,0 +1,47 @@
|
||||
.svgBgMask {
|
||||
position: relative;
|
||||
font-weight: 700;
|
||||
h1, h2 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.picture {
|
||||
img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
will-change: transform;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
z-index: -1;
|
||||
}
|
||||
svg {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.article {
|
||||
padding-top: 100px;
|
||||
background-color: #222;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
h1 {
|
||||
margin: 0;
|
||||
letter-spacing: 3pt;
|
||||
font-weight: 300;
|
||||
font-size: 50px;
|
||||
}
|
||||
ul {
|
||||
margin-top: 100px;
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 60px 100px;
|
||||
h2 {
|
||||
margin-top: 35px;
|
||||
font-size: 1.1em;
|
||||
font-weight: 300;
|
||||
color: #888;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
50
docs/fea/css/demos/demo6/index.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import React, { useRef, useEffect, FC } from 'react';
|
||||
import './index.less'
|
||||
|
||||
const img = require('./img/amazon_view.jpg')
|
||||
|
||||
export default (): any => {
|
||||
|
||||
useEffect(() => {
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="svgBgMask">
|
||||
<div className="picture">
|
||||
<img src={img} alt="" />
|
||||
<svg width="100%" height="1280">
|
||||
<defs>
|
||||
<linearGradient id="gradient" gradientTransform="rotate(76)">
|
||||
<stop offset="18%" stop-color="#1a237e" />
|
||||
<stop offset="80%" stop-color="#00e5ff" />
|
||||
</linearGradient>
|
||||
<mask id="mask">
|
||||
<rect width="100%" height="100%" fill="#fff" />
|
||||
<text x="10%" y="25%" font-size="50px" font-weight="300">hello</text>
|
||||
<text x="10%" y="50%" font-size="100px" letter-spacing="8">My Friend</text>
|
||||
</mask>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="url(#gradient)" fill-opacity="0.8" mask="url(#mask)" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="article">
|
||||
<h1>You Are The Best</h1>
|
||||
<ul>
|
||||
<li>
|
||||
<img src="https://s.cdpn.io/387787/scalable.svg" alt="" width="60" height="60" />
|
||||
<h2>bread</h2>
|
||||
</li>
|
||||
<li>
|
||||
<img src="https://s.cdpn.io/387787/customizable.svg" alt="" width="60" height="60" />
|
||||
<h2>hand</h2>
|
||||
</li>
|
||||
<li>
|
||||
<img src="https://s.cdpn.io/387787/accessible.svg" alt="" width="60" height="60" />
|
||||
<h2>heart</h2>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
34
docs/fea/css/index.md
Normal file
@ -0,0 +1,34 @@
|
||||
---
|
||||
nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 💊 css
|
||||
order: 3
|
||||
---
|
||||
|
||||
## 💊 css
|
||||
|
||||
### 镂空文字背景
|
||||
|
||||
<code src="./demos/demo1/index.tsx" />
|
||||
|
||||
### 涂鸦按钮
|
||||
|
||||
<code src="./demos/demo2/index.tsx" />
|
||||
|
||||
### Svg 蒙版
|
||||
|
||||
<code src="./demos/demo3/index.tsx" />
|
||||
|
||||
### 毛玻璃蒙版
|
||||
|
||||
<code src="./demos/demo4/index.tsx" />
|
||||
|
||||
### 渐变文字
|
||||
|
||||
<code src="./demos/demo5/index.tsx" />
|
||||
|
||||
### 渐变文字
|
||||
|
||||
<code src="./demos/demo6/index.tsx" />
|
1701
docs/fea/norms.md
Normal file
@ -3,12 +3,14 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 设计模式
|
||||
title: 💊 设计模式
|
||||
order: 4
|
||||
---
|
||||
|
||||
## 适配器模式
|
||||
|
||||
将一个类的接口转化为另外一个接口,以满足用户需求,使类之间接口不兼容问题通过适配器得以解决。
|
||||
|
||||
```js
|
||||
import react from 'react';
|
||||
|
||||
|
@ -3,7 +3,7 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 设计模式
|
||||
title: 💊 设计模式
|
||||
order: 3
|
||||
---
|
||||
|
||||
|
40
docs/fea/pattern/decorator.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 💊 设计模式
|
||||
order: 3
|
||||
---
|
||||
|
||||
## 装饰器模式
|
||||
|
||||
- 动态地给某个对象添加一些额外的职责,,是一种实现继承的替代方案
|
||||
- 在不改变原对象的基础上,通过对其进行包装扩展,使原有对象可以满足用户的更复杂需求,而不会影响从这个类中派生的其他对象
|
||||
|
||||
```js
|
||||
class Cellphone {
|
||||
create() {
|
||||
console.log('生成一个手机')
|
||||
}
|
||||
}
|
||||
class Decorator {
|
||||
constructor(cellphone) {
|
||||
this.cellphone = cellphone
|
||||
}
|
||||
create() {
|
||||
this.cellphone.create()
|
||||
this.createShell(cellphone)
|
||||
}
|
||||
createShell() {
|
||||
console.log('生成手机壳')
|
||||
}
|
||||
}
|
||||
// 测试代码
|
||||
let cellphone = new Cellphone()
|
||||
cellphone.create()
|
||||
|
||||
console.log('------------')
|
||||
let dec = new Decorator(cellphone)
|
||||
dec.create()
|
||||
```
|
@ -3,12 +3,62 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 设计模式
|
||||
title: 💊 设计模式
|
||||
order: 6
|
||||
---
|
||||
|
||||
## 发布订阅者模式
|
||||
|
||||
定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使它们能够自动更新自己,当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。
|
||||
|
||||
### 简单版
|
||||
|
||||
```js
|
||||
// 主题 保存状态,状态变化之后触发所有观察者对象
|
||||
class Subject {
|
||||
constructor() {
|
||||
this.state = 0
|
||||
this.observers = []
|
||||
}
|
||||
getState() {
|
||||
return this.state
|
||||
}
|
||||
setState(state) {
|
||||
this.state = state
|
||||
this.notifyAllObservers()
|
||||
}
|
||||
notifyAllObservers() {
|
||||
this.observers.forEach(observer => {
|
||||
observer.update()
|
||||
})
|
||||
}
|
||||
attach(observer) {
|
||||
this.observers.push(observer)
|
||||
}
|
||||
}
|
||||
|
||||
// 观察者
|
||||
class Observer {
|
||||
constructor(name, subject) {
|
||||
this.name = name
|
||||
this.subject = subject
|
||||
this.subject.attach(this)
|
||||
}
|
||||
update() {
|
||||
console.log(`${this.name} update, state: ${this.subject.getState()}`)
|
||||
}
|
||||
}
|
||||
|
||||
// 测试
|
||||
let s = new Subject()
|
||||
let o1 = new Observer('o1', s)
|
||||
let o2 = new Observer('02', s)
|
||||
|
||||
s.setState(12)
|
||||
```
|
||||
|
||||
### 复杂版
|
||||
|
||||
```js
|
||||
/**
|
||||
* 发布订阅者模式
|
||||
|
@ -3,16 +3,15 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 设计模式
|
||||
title: 💊 设计模式
|
||||
order: 1
|
||||
---
|
||||
|
||||
## 工厂模式
|
||||
|
||||
可以简单理解为批量生产
|
||||
工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一个类的实例化延迟到了子类。而子类可以重写接口方法以便创建的时候指定自己的对象类型。
|
||||
|
||||
```js
|
||||
// ------------------- 工厂模式 -------------------
|
||||
class User {
|
||||
constructor(type) {
|
||||
if (new.target === User) {
|
||||
|
@ -3,12 +3,16 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 设计模式
|
||||
title: 💊 设计模式
|
||||
order: 5
|
||||
---
|
||||
|
||||
## 代理模式
|
||||
|
||||
是为一个对象提供一个代用品或占位符,以便控制对它的访问
|
||||
|
||||
### ES5 版
|
||||
|
||||
```js
|
||||
/**
|
||||
* 代理模式
|
||||
@ -28,4 +32,34 @@ export default class ProxyPro {
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ES6 版
|
||||
|
||||
```js
|
||||
let Flower = function() {}
|
||||
let xiaoming = {
|
||||
sendFlower: function(target) {
|
||||
let flower = new Flower()
|
||||
target.receiveFlower(flower)
|
||||
}
|
||||
}
|
||||
let B = {
|
||||
receiveFlower: function(flower) {
|
||||
A.listenGoodMood(function() {
|
||||
A.receiveFlower(flower)
|
||||
})
|
||||
}
|
||||
}
|
||||
let A = {
|
||||
receiveFlower: function(flower) {
|
||||
console.log('收到花'+ flower)
|
||||
},
|
||||
listenGoodMood: function(fn) {
|
||||
setTimeout(function() {
|
||||
fn()
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
xiaoming.sendFlower(B)
|
||||
```
|
@ -3,12 +3,14 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 设计模式
|
||||
title: 💊 设计模式
|
||||
order: 2
|
||||
---
|
||||
|
||||
## 单例模式
|
||||
|
||||
一个类只有一个实例,并提供一个访问它的全局访问点。
|
||||
|
||||
```js
|
||||
// ------------------- 单例模式 -------------------
|
||||
export default class Singleton {
|
||||
|
@ -3,7 +3,7 @@ nav:
|
||||
title: 前端
|
||||
path: /fea
|
||||
group:
|
||||
title: 设计模式
|
||||
title: 💊 设计模式
|
||||
order: 7
|
||||
---
|
||||
|
||||
@ -37,5 +37,5 @@ class CalculateMoney {
|
||||
|
||||
|
||||
let calculateMoney = new CalculateMoney('', 10000)
|
||||
// console.log(calculateMoney);
|
||||
// => 4000000
|
||||
```
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
hero:
|
||||
title: niceNote
|
||||
desc: Json's 学习笔记
|
||||
desc: 💊 Json's 学习笔记
|
||||
actions:
|
||||
- text: 开始学习
|
||||
link: /fea
|
||||
@ -19,3 +19,4 @@ footer: Open-source MIT Licensed | Copyright © 2020<br />Powered by Json
|
||||
---
|
||||
|
||||
嗨~
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
Subproject commit 421af564f3cf2953a822fe25ecdea03536a58950
|
1
temp/javascript
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit f5c14cae2ff58000cead98290b8ec4b54dda2f14
|
1
temp/javascript-algorithms
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4548296affb227c29ead868309e48667f8280c55
|
1
temp/nodebestpractices
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit b16a2837446cfad928def157b769c46b3095aea7
|