数字雨
< canvas id = " matrix" > </ canvas>
< script>
const canvas = document. getElementById ( 'matrix' ) ;
const ctx = canvas. getContext ( '2d' ) ;
canvas. width = window. innerWidth;
canvas. height = window. innerHeight;
const chars = '01' ;
const drops = Array ( Math. floor ( canvas. width / 20 ) ) . fill ( 0 ) ;
function draw ( ) {
ctx. fillStyle = 'rgba(0,0,0,0.05)' ;
ctx. fillRect ( 0 , 0 , canvas. width, canvas. height) ;
ctx. fillStyle = '#0F0' ;
drops. forEach ( ( drop, i ) => {
ctx. fillText ( chars[ Math. random ( ) > 0.5 ? 0 : 1 ] , i * 20 , drop) ;
drops[ i] = drop > canvas. height ? 0 : drop + 20 ;
} ) ;
}
setInterval ( draw, 100 ) ;
</ script>
元素融化动画
< div onclick = " melt(this)" style = " cursor : pointer; padding : 20px; background : #ff6666; " > 点击融化!</ div>
< script>
function melt ( element ) {
let pos = 0 ;
const meltInterval = setInterval ( ( ) => {
element. style. borderRadius = ` ${ pos} px ` ;
element. style. transform = ` skew( ${ pos} deg) scale( ${ 1 - pos/ 100 } ) ` ;
element. style. opacity = 1 - pos / 100 ;
pos += 2 ;
if ( pos > 100 ) clearInterval ( meltInterval) ;
} , 50 ) ;
}
</ script>
电子签名
< style>
* {
margin : 0;
padding : 0;
}
body {
display : flex;
justify-content : center;
align-items : center;
flex-direction : column;
height : 100vh;
width : 100vw;
background-color : #f0f0f0;
overflow : hidden;
}
canvas {
border : 1px solid #000;
background-color : #fff;
}
.controls {
margin-top : 10px;
display : flex;
gap : 10px;
}
button,
select {
padding : 5px 10px;
cursor : pointer;
}
</ style>
< canvas id = " signature-pad" width = " 400" height = " 200" > </ canvas>
< div >
< select id = " stroke-style" >
< option value = " pen" > 钢笔</ option>
< option value = " brush" > 毛笔</ option>
</ select>
< button id = " clear" > 清空</ button>
< button id = " export" > 导出图片</ button>
</ div>
< script>
document. addEventListener ( 'DOMContentLoaded' , ( ) => {
const canvas = document. getElementById ( 'signature-pad' ) ;
const ctx = canvas. getContext ( '2d' ) ;
let drawing = false ;
let lastX = 0 , lastY = 0 ;
let strokeStyle = 'pen' ;
const startDrawing = ( e ) => {
e. preventDefault ( ) ;
drawing = true ;
ctx. beginPath ( ) ;
const { offsetX, offsetY } = getEventPosition ( e) ;
lastX = offsetX;
lastY = offsetY;
ctx. moveTo ( offsetX, offsetY) ;
} ;
const draw = ( e ) => {
e. preventDefault ( ) ;
if ( ! drawing) return ;
const { offsetX, offsetY } = getEventPosition ( e) ;
ctx. quadraticCurveTo (
lastX,
lastY,
( lastX + offsetX) / 2 ,
( lastY + offsetY) / 2
) ;
ctx. stroke ( ) ;
lastX = offsetX;
lastY = offsetY;
} ;
const stopDrawing = ( e ) => {
e. preventDefault ( ) ;
drawing = false ;
} ;
const getEventPosition = ( e ) => {
const offsetX = e. offsetX || e. touches[ 0 ] . clientX - canvas. offsetLeft;
const offsetY = e. offsetY || e. touches[ 0 ] . clientY - canvas. offsetTop;
return { offsetX, offsetY } ;
} ;
const bindMouseEvents = ( ) => {
canvas. addEventListener ( 'mousedown' , startDrawing) ;
canvas. addEventListener ( 'mousemove' , draw) ;
canvas. addEventListener ( 'mouseup' , stopDrawing) ;
canvas. addEventListener ( 'mouseout' , stopDrawing) ;
} ;
const bindTouchEvents = ( ) => {
canvas. addEventListener ( 'touchstart' , startDrawing) ;
canvas. addEventListener ( 'touchmove' , draw) ;
canvas. addEventListener ( 'touchend' , stopDrawing) ;
canvas. addEventListener ( 'touchcancel' , stopDrawing) ;
} ;
const clearCanvas = ( ) => {
document. getElementById ( 'clear' ) . addEventListener ( 'click' , ( ) => {
ctx. clearRect ( 0 , 0 , canvas. width, canvas. height) ;
} ) ;
} ;
const changeStrokeStyle = ( ) => {
document. getElementById ( 'stroke-style' ) . addEventListener ( 'change' , ( e ) => {
strokeStyle = e. target. value;
updateStrokeStyle ( ) ;
} ) ;
} ;
const updateStrokeStyle = ( ) => {
if ( strokeStyle === 'pen' ) {
ctx. lineWidth = 2 ;
ctx. lineCap = 'round' ;
} else if ( strokeStyle === 'brush' ) {
ctx. lineWidth = 5 ;
ctx. lineCap = 'round' ;
}
} ;
const exportImage = ( ) => {
document. getElementById ( 'export' ) . addEventListener ( 'click' , ( ) => {
const tempCanvas = document. createElement ( 'canvas' ) ;
tempCanvas. width = canvas. width;
tempCanvas. height = canvas. height;
const tempCtx = tempCanvas. getContext ( '2d' ) ;
tempCtx. fillStyle = 'white' ;
tempCtx. fillRect ( 0 , 0 , tempCanvas. width, tempCanvas. height) ;
tempCtx. drawImage ( canvas, 0 , 0 ) ;
const dataURL = tempCanvas. toDataURL ( 'image/png' ) ;
const link = document. createElement ( 'a' ) ;
link. href = dataURL;
link. download = 'signature.png' ;
link. click ( ) ;
} ) ;
} ;
const init = ( ) => {
bindMouseEvents ( ) ;
bindTouchEvents ( ) ;
clearCanvas ( ) ;
changeStrokeStyle ( ) ;
updateStrokeStyle ( ) ;
exportImage ( ) ;
} ;
init ( ) ;
} ) ;
</ script>
共享屏幕
< button> 共享屏幕</ button>
< script>
const button = document. querySelector ( "button" ) ;
button. addEventListener ( "click" , async ( ) => {
const stream = await navigator. mediaDevices. getDisplayMedia ( {
video: true ,
} ) ;
const mime = MediaRecorder. isTypeSupported ( "video/webm;codecs=h264" )
? "video/webm;codecs=h264"
: "video/webm" ;
const mediaRecorder = new MediaRecorder ( stream, { mimeType: mime } ) ;
const chunks = [ ] ;
mediaRecorder. addEventListener ( "dataavailable" , function ( e ) {
chunks. push ( e. data) ;
} ) ;
mediaRecorder. addEventListener ( "stop" , ( ) => {
const blob = new Blob ( chunks, { type: chunks[ 0 ] . type } ) ;
const url = URL . createObjectURL ( blob) ;
const a = document. createElement ( "a" ) ;
a. href = url;
a. download = "video.webm" ;
a. click ( ) ;
} ) ;
mediaRecorder. start ( ) ;
} ) ;
</ script>