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: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: canvas
|
title: 💊 canvas
|
||||||
order: 1
|
order: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ nav:
|
|||||||
title: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: canvas
|
title: 💊 canvas
|
||||||
order: 2
|
order: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -3,12 +3,16 @@ nav:
|
|||||||
title: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: canvas
|
title: 💊 canvas
|
||||||
order: 6
|
order: 6
|
||||||
---
|
---
|
||||||
|
|
||||||
## 动画案例
|
## 动画案例
|
||||||
|
|
||||||
|
### 液体海报
|
||||||
|
|
||||||
|
<code src="./demos/demo1/index.jsx" />
|
||||||
|
|
||||||
### 大转盘(doing)
|
### 大转盘(doing)
|
||||||
|
|
||||||
```jsx
|
```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: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: canvas
|
title: 💊 canvas
|
||||||
order: 4
|
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: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: 设计模式
|
title: 💊 设计模式
|
||||||
order: 4
|
order: 4
|
||||||
---
|
---
|
||||||
|
|
||||||
## 适配器模式
|
## 适配器模式
|
||||||
|
|
||||||
|
将一个类的接口转化为另外一个接口,以满足用户需求,使类之间接口不兼容问题通过适配器得以解决。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import react from 'react';
|
import react from 'react';
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ nav:
|
|||||||
title: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: 设计模式
|
title: 💊 设计模式
|
||||||
order: 3
|
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: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: 设计模式
|
title: 💊 设计模式
|
||||||
order: 6
|
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
|
```js
|
||||||
/**
|
/**
|
||||||
* 发布订阅者模式
|
* 发布订阅者模式
|
||||||
|
@ -3,16 +3,15 @@ nav:
|
|||||||
title: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: 设计模式
|
title: 💊 设计模式
|
||||||
order: 1
|
order: 1
|
||||||
---
|
---
|
||||||
|
|
||||||
## 工厂模式
|
## 工厂模式
|
||||||
|
|
||||||
可以简单理解为批量生产
|
工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一个类的实例化延迟到了子类。而子类可以重写接口方法以便创建的时候指定自己的对象类型。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// ------------------- 工厂模式 -------------------
|
|
||||||
class User {
|
class User {
|
||||||
constructor(type) {
|
constructor(type) {
|
||||||
if (new.target === User) {
|
if (new.target === User) {
|
||||||
|
@ -3,12 +3,16 @@ nav:
|
|||||||
title: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: 设计模式
|
title: 💊 设计模式
|
||||||
order: 5
|
order: 5
|
||||||
---
|
---
|
||||||
|
|
||||||
## 代理模式
|
## 代理模式
|
||||||
|
|
||||||
|
是为一个对象提供一个代用品或占位符,以便控制对它的访问
|
||||||
|
|
||||||
|
### ES5 版
|
||||||
|
|
||||||
```js
|
```js
|
||||||
/**
|
/**
|
||||||
* 代理模式
|
* 代理模式
|
||||||
@ -29,3 +33,33 @@ 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: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: 设计模式
|
title: 💊 设计模式
|
||||||
order: 2
|
order: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
## 单例模式
|
## 单例模式
|
||||||
|
|
||||||
|
一个类只有一个实例,并提供一个访问它的全局访问点。
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// ------------------- 单例模式 -------------------
|
// ------------------- 单例模式 -------------------
|
||||||
export default class Singleton {
|
export default class Singleton {
|
||||||
|
@ -3,7 +3,7 @@ nav:
|
|||||||
title: 前端
|
title: 前端
|
||||||
path: /fea
|
path: /fea
|
||||||
group:
|
group:
|
||||||
title: 设计模式
|
title: 💊 设计模式
|
||||||
order: 7
|
order: 7
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -37,5 +37,5 @@ class CalculateMoney {
|
|||||||
|
|
||||||
|
|
||||||
let calculateMoney = new CalculateMoney('', 10000)
|
let calculateMoney = new CalculateMoney('', 10000)
|
||||||
// console.log(calculateMoney);
|
// => 4000000
|
||||||
```
|
```
|
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
hero:
|
hero:
|
||||||
title: niceNote
|
title: niceNote
|
||||||
desc: Json's 学习笔记
|
desc: 💊 Json's 学习笔记
|
||||||
actions:
|
actions:
|
||||||
- text: 开始学习
|
- text: 开始学习
|
||||||
link: /fea
|
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
|