Skip to content

Commit

Permalink
feat: update
Browse files Browse the repository at this point in the history
  • Loading branch information
QinZhen001 committed May 28, 2024
1 parent c05bb2f commit ddb4272
Show file tree
Hide file tree
Showing 12 changed files with 420 additions and 19 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.30.1",
"lint-staged": "^13.0.3",
"yorkie": "^2.0.0"
"yorkie": "^2.0.0",
"sass": "^1.70.0"
}
}
92 changes: 92 additions & 0 deletions src/pages/animation/gradient-border/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
.gradient-border {

.section1 {
.gradient {
font-size: 64px;
}

.dilate {
filter: url(#dilate);
}


.erode {
filter: url(#erode);
}


}



.section2 {
font-size: 64px;

--stroke-width: 12px;
--background-gradient: linear-gradient(red 0%, green 100%);
--text-gradient: linear-gradient(white 0%, cyan 100%);



.text {
position: relative;
}

.text::before,
.text::after {
content: attr(data-text);
display: block;
background-clip: text;
color: transparent;
}

.text::before {
position: absolute;
inset: 0;
background-image: var(--background-gradient);
-webkit-text-stroke: var(--stroke-width);
}

.text::after {
position: relative;
z-index: 1;
background-image: var(--text-gradient);
}

}



.section3 {
div {
position: relative;
width: 100vw;
height: 150px;
font-size: 120px;
font-weight: bold;
text-align: left;

&::before,
&::after {
content: attr(data-text);
position: absolute;
inset: 0;
}

&::before {
color: transparent;
background: linear-gradient(0deg, #da00ff, #2a79b7, #7e3eff);
background-clip: text;
}

&::after {
filter: url(#outline);
}


}


}

}
60 changes: 60 additions & 0 deletions src/pages/animation/gradient-border/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// https://juejin.cn/post/7363220159505694747
// 渐变边框文字效果

import "./index.scss"

const GradientBorder = () => {
return (
<div className="gradient-border">
<section className="section1">
<div className="gradient">Normal Text</div>
<div className="gradient dilate">Normal Text</div>
<div className="gradient erode">Normal Text</div>

<svg width="0" height="0">
<filter id="dilate">
<feMorphology
in="SourceAlpha"
result="DILATED"
operator="dilate"
radius="3"
></feMorphology>
</filter>
<filter id="erode">
<feMorphology
in="SourceAlpha"
result="ERODE"
operator="erode"
radius="1"
></feMorphology>
</filter>
</svg>
</section>

<section className="section2">
<span className="text" data-text="我能吞下玻璃而不伤身体"></span>
</section>

<section className="section3">
<div data-text="123/678"></div>
<svg width="0" height="0">
<filter id="outline">
<feMorphology
in="SourceAlpha"
result="ERODE"
operator="erode"
radius="2"
></feMorphology>
<feFlood flood-color="#fff" flood-opacity="1" result="flood"></feFlood>
<feComposite in="flood" in2="ERODE" operator="in" result="OUTLINE"></feComposite>
<feMerge>
<feMergeNode in="OUTLINE" />
</feMerge>
</filter>
</svg>
</section>
</div>
)
}

export default GradientBorder
14 changes: 13 additions & 1 deletion src/pages/animation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const AtEditor = lazy(() => import("./at-editor"))
const ChineseInput = lazy(() => import("./chinese-input"))
const Notification = lazy(() => import("./notification"))
const Slider = lazy(() => import("../animation/slider"))
const MultipleType = lazy(() => import("./multiple-type"))
const GradientBorder = lazy(() => import("./gradient-border"))

export const children = [
{
Expand Down Expand Up @@ -37,7 +39,17 @@ export const children = [
{
path: "slider",
element: <Slider></Slider>,
title: "轮播图 (center active item)",
title: "轮播图 (center active)",
},
{
path: "multiple-type",
element: <MultipleType></MultipleType>,
title: "多行文字打字机效果",
},
{
path: "gradient-border",
element: <GradientBorder></GradientBorder>,
title: "渐变边框文字",
},
]

Expand Down
29 changes: 29 additions & 0 deletions src/pages/animation/multiple-type/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
:root {
--pointerColor: #000;
}

.multiple-type .example p {
display: inline;
background: linear-gradient(90deg, transparent, transparent calc(100% - 2px), var(--pointerColor) calc(100% - 2px), var(--pointerColor));
animation: colorChange .6s linear infinite;
padding-right: 4px;
white-space:pre-wrap;
}

/*
TIP:
在移动端浏览器中,无法在css中动态改变css变量
因为移动端浏览器的CSS解析引擎对于CSS变量的支持有限。
只能在js中改变css变量
getComputedStyle(document.documentElement).getPropertyValue('--pointerColor')
document.documentElement.style.setProperty('--pointerColor', "transparent")
*/
@keyframes colorChange {
0%, 50% {
--pointerColor: #000;
}
50%, 100% {
--pointerColor: transparent;
}
}
39 changes: 39 additions & 0 deletions src/pages/animation/multiple-type/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// https://github.com/chokcoco/iCSS/issues/262
// 内联元素的每一行都是会有不一样的效果,动画效果是以行为单位进行变换的

import { useEffect, useState } from "react"
import "./index.css"

const characters = "abcde fghijk lmnop qrstu vwxyz"

const MultipleType = () => {
const [text, setText] = useState("")

useEffect(() => {
const id = setInterval(() => {
setText((prev) => {
if (prev.length >= 1000) {
return ""
}
if (prev.length % 80 === 0) {
return prev + "\n"
}
return prev + characters[Math.floor(Math.random() * characters.length)]
})
}, 100)

return () => {
clearInterval(id)
}
}, [])

return (
<div className="multiple-type">
<div className="example">
<p>{text}</p>
</div>
</div>
)
}

export default MultipleType
File renamed without changes.
78 changes: 78 additions & 0 deletions src/pages/web-media/canvas-capture-stream/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { useRef, useState } from "react"

const WIDTH = 300
const HEIGHT = 300
let rotate = 0

const CanvasCaptureStream = () => {
const canvasRef = useRef<HTMLCanvasElement>(null)
const videoRef = useRef<HTMLVideoElement>(null)
const [videoUrl, setVideoUrl] = useState<string>("")
let recorder: any
const data: BlobPart[] = []

const onClickDrawCanvas = () => {
drawCanvas()
requestAnimationFrame(onClickDrawCanvas)
}

const drawCanvas = () => {
if (!canvasRef.current) {
throw new Error("canvasRef.current is null")
}
const ctx = canvasRef.current.getContext("2d")!
ctx.fillStyle = "red"
ctx.clearRect(0, 0, WIDTH, HEIGHT)
ctx.save()
ctx.translate(WIDTH / 2, HEIGHT / 2)
ctx.rotate((rotate++ * Math.PI) / 180)
ctx.translate(-WIDTH / 2, -HEIGHT / 2)
ctx.beginPath()
ctx.rect(100, 100, 50, 50)
ctx.fill()
ctx.restore()
}

const onClickRecordStart = () => {
if (!canvasRef.current) {
throw new Error("canvasRef.current is null")
}
const stream = canvasRef.current.captureStream()
console.log("stream", stream)

recorder = new MediaRecorder(stream, { mimeType: "video/webm" })

recorder.ondataavailable = (e: any) => {
console.log("mediaRecorder ondataavailable ", e)
// e.data 为 Blob 类型
data.push(e.data)
}

recorder.start(1000)
}

const onClickRecordEnd = () => {
recorder.stop()
const url = URL.createObjectURL(new Blob(data, { type: "video/webm" }))
console.log("onstop data", data)
console.log("onstop url", url)
videoRef!.current!.src = url
setVideoUrl(url)
}

return (
<div>
<div>
<button onClick={onClickDrawCanvas}>drawCanvas</button>
<button onClick={onClickRecordStart}>record</button>
<button onClick={onClickRecordEnd}>stop</button>
</div>
<canvas ref={canvasRef} width={WIDTH} height={HEIGHT}></canvas>
<div>
<video controls ref={videoRef}></video>
</div>
</div>
)
}

export default CanvasCaptureStream
16 changes: 11 additions & 5 deletions src/pages/web-media/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
import { lazy } from "react"
import { CommonPageRouter } from "../main"

const WebRtcSimple = lazy(() => import("./simple"))
const MediaRecorderComponent = lazy(() => import("./media-recorder"))
const WebRtcDataChannel = lazy(() => import("./data-channel"))
const AnalyserNode = lazy(() => import("./analyser-node"))
const AudioPcm = lazy(() => import("./audio-pcm"))
const AudioBuffer = lazy(() => import("./audio-buffer"))
const GainNode = lazy(() => import("./gain-node"))
const CanvasCaptureStream = lazy(() => import("./canvas-capture-stream"))

export const children = [
{
path: "webrtcSimple",
element: <WebRtcSimple></WebRtcSimple>,
title: "快速入门 WebRTC",
path: "mediaRecorder",
element: <MediaRecorderComponent></MediaRecorderComponent>,
title: "MediaRecorder相关",
},
{
path: "webrtcDataChannel",
path: "canvas-capture-stream",
element: <CanvasCaptureStream></CanvasCaptureStream>,
title: "canvasCaptureStream相关",
},
{
path: "dataChannel",
element: <WebRtcDataChannel></WebRtcDataChannel>,
title: "WebRTC DataChannel",
},
Expand Down
Loading

0 comments on commit ddb4272

Please sign in to comment.