管理员 10 months ago
parent c24c6751db
commit 754e003467

@ -0,0 +1,89 @@
class GifPlayer {
/**
*
* @param {*} template 图片模板路径:变量,{i}
* @param {*} num 图片的总数{i}=0~(num-1), 默认34
* @param {*} canvas 画布
* @param {*} radioRate 播放速率比,0=不播放 默认1
*/
constructor(template, num, canvas, radioRate) {
this.load = false;
this.canvas = canvas;
this.radioRate = radioRate;
this.ctx = this.canvas.getContext('2d');
// this.ctx.save();
this.#init(template, num);
}
async #init(template, num) {
this.imgs = await this.loadImgs(template, num);
this.canvas.dispatchEvent(new CustomEvent('loadend', { bubbles: false }))
this.load = true;
this.canvas.width = this.imgs[0].naturalWidth * window.devicePixelRatio;
this.canvas.height = this.imgs[0].naturalHeight * window.devicePixelRatio;
this.i = 0;
this.time = Date.now();
this.playing = true;
this.ctx.drawImage(this.imgs[0], 0, 0, this.canvas.width, this.canvas.height);
this.#backgroudPlay();
}
/**
* 加载图片
* @param {*} template 图片模板路径:变量,{i}
* @param {*} num 图片的总数{i}=0~(num-1), 默认34
*/
loadImgs(template, num = 34) {
return new Promise((resolve, reject) => {
const imgs = [];
const ps = [];
for (let i = 0; i < num; i++) {
const img = new Image();
img.src = template.replace('{i}', i);
imgs[i] = img;
ps.push(new Promise((resolve1, reject1) => {
img.onload = resolve1;
img.onerror = reject1;
}));
}
Promise.all(ps).then(() => {
resolve(imgs);
}).catch(err => {
reject(err);
})
})
}
#backgroudPlay() {
if (this.radioRate === 0 || !this.playing) {
requestAnimationFrame(() => { this.#backgroudPlay() });
return;
}
let now = Date.now();
if (now - this.time >= 50 / this.radioRate) {
this.time = now;
this.i++;
if (this.i >= this.imgs.length) {
this.i = 0;
this.canvas.dispatchEvent(new CustomEvent('loopend', { bubbles: false }))
}
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
// this.ctx.restore();
this.ctx.drawImage(this.imgs[this.i], 0, 0, this.canvas.width, this.canvas.height);
}
requestAnimationFrame(() => { this.#backgroudPlay() });
}
start() {
this.playing = true;
}
stop() {
this.playing = false;
}
}
export { GifPlayer };

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

@ -0,0 +1,271 @@
.login {
position: relative;
width: 100vw;
height: 100vh;
--w-bg: #c9dcf6;
--w-bg-1: #00000004;
overflow: hidden;
* {
box-sizing: border-box;
border: none;
padding: 0;
margin: 0;
outline: none;
background-color: #0000;
}
&>div {
position: absolute;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
}
.login-bg {
background-color: var(--w-bg);
background-image: repeating-linear-gradient(45deg, #0000 0, #0000 .3em, var(--w-bg-1) .6em, #0000 1em, #0000 1.2em),
repeating-linear-gradient(-45deg, #0000 0, #0000 .3em, var(--w-bg-1) .6em, #0000 1em, #0000 1.2em);
filter: url(#bgFilter);
transform: scale(2);
}
.login-layout {
&>div {
width: 50em;
height: 50em;
position: relative;
display: flex;
justify-content: center;
align-items: center;
.energy-base {
position: absolute;
inset: 0;
background-image: url(./energy-base.png);
background-repeat: no-repeat;
background-position: 1em 20em;
background-size: calc(713em / 20) auto;
/* filter: brightness(190%); */
animation: am-login-doing 1.7s infinite alternate-reverse;
}
.energy-body {
position: absolute;
inset: 0;
background-image: url(./energy-body.png);
background-repeat: no-repeat;
background-position: 7em 5em;
background-size: calc(495em / 20) auto;
}
.login-frame {
width: 30em;
/* min-height: 30em; */
background-color: #FFF;
border-radius: 1em;
box-shadow: 0 0 1em rgba(0, 0, 0, 0.1);
padding: 3em;
h1 {
font-size: 1.7em;
}
}
}
}
.canvas {
width: 10em;
position: absolute;
transform: scaleX(-1);
}
.login-input {
display: flex;
border-bottom: solid 1px #0002;
align-items: center;
padding: 2em .5em .3em;
width: 100%;
box-sizing: border-box;
transition: all .3s ease-in-out;
svg {
width: 1.5em;
height: 1.5em;
margin-right: 1em;
path {
fill: #0003;
transition: all .3s ease-in-out;
}
}
&>* {
flex-grow: 0;
flex-shrink: 0;
}
input {
flex-grow: 1;
flex-shrink: 1;
font-size: 1.1em;
padding: .5em 0em;
color: #0005;
transition: all .3s ease-in-out;
&::placeholder {
color: #0005;
}
}
img {
width: 5em;
height: 2em;
cursor: pointer;
}
&:has(input:focus) {
border-bottom: solid 1px #0004;
input{
color: #0009;
}
path {
fill: #0007;
}
}
}
.reme {
display: flex;
align-items: center;
margin: .6em 1em;
color: #0008;
input {
margin-right: .5em;
transform: translateY(.11em) scale(1.3);
}
}
.login-btn {
user-select: none;
margin-top: 2em;
height: 2.3em;
position: relative;
background-color: #1163fd;
color: #FFF;
font-size: 1.1em;
font-weight: normal;
letter-spacing: 2em;
text-indent: 2em;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
border-radius: .3em;
width: 100%;
transition: all .3s ease-in-out;
cursor: pointer;
&:not(.loading) {
&:hover {
filter: brightness(120%);
}
&:active {
filter: brightness(80%);
}
}
&.loading {
pointer-events: none;
&::before {
content: '';
position: absolute;
inset: 0;
background-color: #0003;
backdrop-filter: blur(.1em);
}
&::after {
position: absolute;
content: '';
width: 1em;
height: 1em;
border-radius: 1em;
border: solid .2em #fff;
mask-image: conic-gradient(from 0deg,#0000 0%,#000 75%,#000 83%,#0000 85%);
animation: am-login-loading 1s ease infinite;
}
}
}
}
@keyframes am-login-loading {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes am-login-doing {
0% {
filter: brightness(100%);
}
20% {
filter: brightness(110%);
}
40% {
filter: brightness(100%);
}
}
@property --noise-base {
syntax: '<number>';
inherits: true;
initial-value: 0;
}
.noise {
filter: url(#noiseFilter);
--noise-base: 0;
animation: am-noise 5.1s linear infinite;
}
@keyframes am-noise {
0% {
--noise-base: 0;
}
10% {
--noise-base: 0.1;
}
20% {
--noise-base: 0;
}
}

@ -0,0 +1,189 @@
<!DOCTYPE html>
<html lang="en" style="font-size: .85vw;">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="assets/login/login.css">
<script type="module" src="login.js"></script>
</head>
<body style="margin: 0; padding: 0;">
<div class="login">
<label style="position: absolute; right: 1em; bottom: 1em; z-index: 10;"><input type="checkbox" onchange="if(this.checked){document.body.style.setProperty('--dyn','flex');document.body.style.setProperty('--sta','none'); }else{document.body.style.setProperty('--sta','flex');document.body.style.setProperty('--dyn','none'); }">转动风车</label>
<div class="login-bg">
<svg style="display: none;">
<defs>
<filter id="bgFilter" color-interpolation-filters="linearRGB" filterUnits="objectBoundingBox"
primitiveUnits="userSpaceOnUse">
<feTurbulence type="turbulence" baseFrequency=".5 .5" numOctaves="100" seed="100" stitchTiles="stitch"
x="-20%" y="-20%" width="140%" height="140%" result="turbulence" />
<feDisplacementMap in="SourceGraphic" in2="turbulence" scale="200" xChannelSelector="R" yChannelSelector="A"
x="-20%" y="-20%" width="140%" height="140%" result="displacementMap" />
</filter>
</defs>
</svg>
</div>
<div class="login-layout">
<div>
<svg viewBox="0 0 2000 2000" xmlns="http://www.w3.org/2000/svg"
style="width: 200em; height: 200em; position: absolute; top:0; left: -5em; --line-light:#60b17c;">
<!-- 定义阴影滤镜 -->
<defs>
<filter id="shadow" x="-200%" y="-200%" width="500%" height="500%">
<feDropShadow dx="0" dy="0" stdDeviation="2" flood-color="var(--line-light,red)" flood-opacity="1" />
</filter>
<!-- 定义线性渐变 -->
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color: black; stop-opacity: 1" />
<stop offset="100%" style="stop-color: white; stop-opacity: 1" />
</linearGradient>
<!-- 定义mask -->
<mask id="mask">
<rect x="-20" y="-1" width="20" height="3" fill="url(#gradient)">
<animateMotion dur="2.3s" repeatCount="indefinite" rotate="auto">
<mpath href="#bezierPath" />
</animateMotion>
</rect>
</mask>
<mask id="mask2">
<rect x="-20" y="-1" width="20" height="3" fill="url(#gradient)">
<animateMotion dur="1.7s" repeatCount="indefinite" rotate="auto">
<mpath href="#bezierPath2" />
</animateMotion>
</rect>
</mask>
<mask id="mask3">
<rect x="-20" y="-1" width="20" height="3" fill="url(#gradient)">
<animateMotion dur="2.1s" repeatCount="indefinite" rotate="auto">
<mpath href="#bezierPath3" />
</animateMotion>
</rect>
</mask>
</defs>
<path id="bezierPath" d="
M 40,518
Q 180,500,200,435
" stroke-width="1" stroke="#0001" fill="none" />
<path d="
M 40,518
Q 180,500,200,435
" stroke-width="1" stroke="var(--line-light,red)" fill="none" mask="url(#mask)" />
<circle cx="0" cy="0" r="1" fill="var(--line-light,red)" filter="url(#shadow)">
<animateMotion dur="2.3s" repeatCount="indefinite" calcMode="linear">
<mpath href="#bezierPath" rotate="reverse" />
</animateMotion>
</circle>
<path id="bezierPath2" d="
M 560,200
Q 500,400,400,390
" stroke-width="1" stroke="#0001" fill="none" />
<path d="
M 560,200
Q 500,400,400,390
" stroke-width="1" stroke="var(--line-light,red)" fill="none" mask="url(#mask2)" />
<circle cx="0" cy="0" r="1" fill="var(--line-light,red)" filter="url(#shadow)">
<animateMotion dur="1.7s" repeatCount="indefinite" calcMode="linear">
<mpath href="#bezierPath2" rotate="reverse" />
</animateMotion>
</circle>
<path id="bezierPath3" d="
M 995,528
Q 400,500,300,431
" stroke-width="1" stroke="#0001" fill="none" />
<path d="
M 995,528
Q 400,500,300,431
" stroke-width="1" stroke="var(--line-light,red)" fill="none" mask="url(#mask3)" />
<circle cx="0" cy="0" r="1" fill="var(--line-light,red)" filter="url(#shadow)">
<animateMotion dur="2.1s" repeatCount="indefinite" calcMode="linear">
<mpath href="#bezierPath3" rotate="reverse" />
</animateMotion>
</circle>
</svg>
<div class="energy-base"></div>
<div class="energy-body noise">
<svg style="display: none;">
<defs>
<filter id="noiseFilter" color-interpolation-filters="linearRGB" filterUnits="objectBoundingBox"
primitiveUnits="userSpaceOnUse">
<feTurbulence type="turbulence" baseFrequency="0 0.21" numOctaves="2" seed="2" stitchTiles="stitch"
x="0%" y="0%" width="100%" height="100%" result="turbulence" />
<feDisplacementMap in="SourceGraphic" in2="turbulence" scale="10" xChannelSelector="R"
yChannelSelector="B" x="0%" y="0%" width="100%" height="100%" result="displacementMap" />
</filter>
</defs>
</svg>
</div>
<canvas class="canvas" style="width: 30em; left: 80em; top: 14em; display: var(--dyn,none); "></canvas>
<canvas class="canvas" style="width: 15em; left: 44em; top: 1em; display: var(--dyn,none);"></canvas>
<canvas class="canvas" style="width: 9em; left: -6em; top: 40.2em; transform: none; display: var(--dyn,none);"></canvas>
<img class="canvas" src="./assets/login/energy-input.png"
style="width: 18em; left: 86em; top: 15em; transform: none; display: var(--sta,flex);" />
<img class="canvas" src="./assets/login/energy-input.png"
style="width: 12em; left: 45em; top: -5em; transform: none; display: var(--sta,flex);" />
<img class="canvas" src="./assets/login/energy-input.png" style="width: 8em; left: -5em; top: 35em; display: var(--sta,flex);" />
</div>
<div>
<div class="login-frame">
<h1>欢迎登录</h1>
<h1>园区智慧能源综合管控平台</h1>
<div class="login-input" style="margin-top: 2em;">
<svg t="1739438726965" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="3160">
<path
d="M164.655 68.977v0 0zM866.321 769.149q0 59.804-36.377 94.437t-96.684 34.632h-435.544q-60.293 0-96.684-34.632t-36.377-94.437q0-26.414 1.744-51.573t6.977-54.321 13.2-54.069 21.432-48.586 30.892-40.367 42.614-26.665 55.563-9.963q4.479 0 20.931 10.717t37.131 23.916 53.819 23.916 66.531 10.717 66.531-10.717 53.819-23.916 37.131-23.916 20.931-10.717q30.405 0 55.563 9.963t42.614 26.665 30.893 40.367 21.432 48.586 13.2 54.069 6.977 54.321 1.744 51.573zM706.846 324.131q0 79.242-56.065 135.292t-135.293 56.065-135.293-56.065-56.065-135.292 56.065-135.293 135.293-56.065 135.293 56.065 56.065 135.293z"
p-id="3161"></path>
</svg>
<input type="text" autocomplete="off" placeholder="请输入用户名" autofocus />
</div>
<div class="login-input">
<svg t="1739438853067" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="4166" width="200" height="200">
<path
d="M807.049 391.258c0.946-9.62 1.45-19.37 1.45-29.239 0-163.7-132.706-296.406-296.406-296.406S215.687 198.318 215.687 362.02c0 9.802 0.498 19.486 1.432 29.043-43.925 18.95-74.675 62.638-74.675 113.516v330.363c0 68.25 55.328 123.58 123.58 123.58h491.672c68.25 0 123.578-55.328 123.578-123.58V504.578c0-50.704-30.54-94.267-74.225-113.32zM510.917 165.905c109.134 0 197.604 88.47 197.604 197.603 0 5.895-0.275 11.726-0.782 17.49H314.094a200.097 200.097 0 0 1-0.782-17.49c0.002-109.132 88.472-197.603 197.605-197.603z"
p-id="4167"></path>
</svg>
<input type="password" autocomplete="off" placeholder="请输入登录密码" />
</div>
<div class="login-input">
<svg t="1739438995410" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
p-id="5146" width="200" height="200">
<path
d="M908.65 256.38c-2.81-27.59-23.15-50.2-50.29-55.9a1187.653 1187.653 0 0 1-162.65-37.44A604.025 604.025 0 0 1 550.39 78.1c-23.19-16.7-54.47-16.7-77.67 0a381.187 381.187 0 0 1-146.42 84.39 545.725 545.725 0 0 1-158.17 39.09c-27.74 4.48-48.52 27.83-49.74 55.9s-1.69 140.29-1.69 263.77c0 223.54 263.77 439.86 395.7 439.86 131.88 0 355.46-152.59 391.22-436.48 8.95-167.68 5.03-268.29 5.03-268.29v0.04zM765.02 429.05L489.47 688.93c-12.4 11.82-31.35 13.68-45.81 4.48l-7.23-6.17-152.04-158.12c-14.2-15.43-13.21-39.45 2.22-53.65 15.43-14.2 39.45-13.2 53.65 2.22l125.2 131.34L713.6 374.29c15.44-14.2 39.47-13.2 53.67 2.24 14.2 15.44 13.2 39.47-2.24 53.67v-1.15h-0.01z"
p-id="5147"></path>
</svg>
<input type="input" autocomplete="off" placeholder="请输入验证码" />
<img title="点击更换验证码" src="http://dummyimage.com/110x40/6aadfb/FFF&text=123456"/>
</div>
<label class="reme"><input type="checkbox" /> 记住密码</label>
<div class="login-btn" onclick="this.classList.toggle('loading');" style="pointer-events: all;">登录</div>
</div>
</div>
</div>
</div>
</body>
</html>

@ -0,0 +1,22 @@
import { GifPlayer } from './GifPlayer.js';
window.onload = () => {
const noise = document.querySelector('.noise');
const noiseStyle = getComputedStyle(noise);
const noiseFilter = document.querySelector('#noiseFilter').firstElementChild;
const noisePlayer = () => {
let base = noiseStyle.getPropertyValue('--noise-base');
noiseFilter.setAttribute('baseFrequency', `0 ${base}`);
requestAnimationFrame(noisePlayer)
}
noisePlayer();
let speed = [.75,.5,.35]
document.querySelectorAll("canvas.canvas").forEach((canvas,i) => {
console.debug(i)
new GifPlayer('./assets/login/gif/{i}.png', 19, canvas, speed[i]);
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
<canvas id="gifCanvas"></canvas>
<div>
<button onclick="window.gifPlayer.start()">start</button>
<button onclick="window.gifPlayer.stop()">stop</button>
<input type="number" max="10" min="0" step="0.1" value="1"><button onclick="window.gifPlayer.radioRate=Number(this.previousElementSibling.value)">播放速率比</button>
</div>
</div>
<script>
const gifCanvas = document.querySelector('#gifCanvas');
class GifPlayer {
/**
*
* @param {*} template 图片模板路径:变量,{i}
* @param {*} num 图片的总数{i}=0~(num-1), 默认34
* @param {*} canvas 画布
* @param {*} radioRate 播放速率比,0=不播放 默认1
*/
constructor(template, num, canvas, radioRate) {
this.load = false;
this.canvas = canvas;
this.radioRate = radioRate;
this.ctx = this.canvas.getContext('2d');
// this.ctx.save();
this.#init(template, num);
}
async #init(template, num) {
this.imgs = await this.loadImgs(template, num);
this.canvas.dispatchEvent(new CustomEvent('loadend',{bubbles:false}))
this.load = true;
this.canvas.width = this.imgs[0].naturalWidth * window.devicePixelRatio;
this.canvas.height = this.imgs[0].naturalHeight * window.devicePixelRatio;
this.i = 0;
this.time = Date.now();
this.playing = true;
this.ctx.drawImage(this.imgs[0], 0, 0, this.canvas.width, this.canvas.height);
this.#backgroudPlay();
}
/**
* 加载图片
* @param {*} template 图片模板路径:变量,{i}
* @param {*} num 图片的总数{i}=0~(num-1), 默认34
*/
loadImgs(template, num = 34) {
return new Promise((resolve, reject) => {
const imgs = [];
const ps = [];
for (let i = 0; i < num; i++) {
const img = new Image();
img.src = template.replace('{i}', i);
imgs[i] = img;
ps.push(new Promise((resolve1, reject1) => {
img.onload = resolve1;
img.onerror = reject1;
}));
}
Promise.all(ps).then(() => {
resolve(imgs);
}).catch(err => {
reject(err);
})
})
}
#backgroudPlay() {
if (this.radioRate === 0 || !this.playing) {
requestAnimationFrame(()=>{this.#backgroudPlay()});
return;
}
let now = Date.now();
if (now - this.time >= 50 / this.radioRate) {
this.time = now;
this.i++;
if (this.i >= this.imgs.length) {
this.i = 0;
}
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
// this.ctx.restore();
this.ctx.drawImage(this.imgs[this.i], 0, 0, this.canvas.width, this.canvas.height);
}
requestAnimationFrame(()=>{this.#backgroudPlay()});
}
start() {
this.playing = true;
}
stop() {
this.playing = false;
}
}
window.gifPlayer = new GifPlayer('./gif/{i}.png', 34, gifCanvas, 1);
</script>
</body>
</html>

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<img class="noise" src="https://evoai.cn/assets/img/team.png" alt="">
<svg style="display: none;">
<defs>
<filter id="noiseFilter" color-interpolation-filters="linearRGB" filterUnits="objectBoundingBox"
primitiveUnits="userSpaceOnUse">
<feTurbulence type="turbulence" baseFrequency="0 0.21" numOctaves="2" seed="2" stitchTiles="stitch" x="0%" y="0%"
width="100%" height="100%" result="turbulence" />
<feDisplacementMap in="SourceGraphic" in2="turbulence" scale="10" xChannelSelector="R" yChannelSelector="B"
x="0%" y="0%" width="100%" height="100%" result="displacementMap" />
</filter>
</defs>
</svg>
<style>
@property --noise-base {
syntax: '<number>';
inherits: true;
initial-value: 0;
}
.noise {
width: 50vmin;
margin: 1em auto;
filter: url(#noiseFilter);
--noise-base: 0;
animation: am-noise 3s linear infinite;
}
@keyframes am-noise {
0% {--noise-base: 0;}
10% {--noise-base: 0.1;}
20% {--noise-base: 0;}
}
</style>
<script>
const noise = document.querySelector('.noise');
const noiseStyle = getComputedStyle(noise);
const noiseFilter = document.querySelector('#noiseFilter').firstElementChild;
console.info(noiseFilter);
const noisePlayer = ()=>{
let base = noiseStyle.getPropertyValue('--noise-base');
noiseFilter.setAttribute('baseFrequency', `0 ${base}`);
requestAnimationFrame(noisePlayer)
}
noisePlayer();
</script>
</body>
</html>
Loading…
Cancel
Save