??????????前期回顧
打造極簡風(fēng)格動(dòng)效 —— 5 分鐘輕松實(shí)現(xiàn)驚艷、震撼人心的視覺效果_彩色之外的博客-CSDN博客
??
css動(dòng)畫 —— 把你喜歡css動(dòng)畫嵌入到瀏覽器中_css做的動(dòng)畫效果怎么嵌入網(wǎng)頁_彩色之外的博客-CSDN博客
?代碼已上傳資源
? 開頭省略200字》……
念及此
? 直接上圖
目錄
?? 進(jìn)度條
?? 唯美登錄背景
??? 蠟燭登錄動(dòng)畫
?? 火箭?
?????? 時(shí)間翻盤
?? 復(fù)選框動(dòng)畫
?? 基礎(chǔ)表單輸入動(dòng)畫
?? 卡包動(dòng)畫
?? 流光掃過動(dòng)畫
?? 酷炫標(biāo)題
?? 交互式評分
?? 動(dòng)態(tài)向上箭頭
????卸載對話框表情交互動(dòng)畫
????隨機(jī)密碼生成器代碼
???跟隨設(shè)備切換主題
?? 晝夜切換主題
???????使用系統(tǒng)取色器
?? 右鍵動(dòng)態(tài)菜單(已做邊緣動(dòng)畫及邊界外判斷)
?? 酷炫打字特效
?? 方形抽獎(jiǎng)
?? 圓形抽獎(jiǎng)
?? 吸頂樓層導(dǎo)航
?? 困了蓋坤
?? 扣扣樂
???簽名回溯
?? 翻盤抽獎(jiǎng)
?? 地址 ???????
?????? 謝謝觀看
?圖例:
??圖片過多,不在開頭一一展示了,下面圖與源碼會放在一起,代碼設(shè)計(jì)原生JS、VUE3
?? 進(jìn)度條
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>3款漂亮的html5+css3 3D百分比進(jìn)度條動(dòng)畫特效</title>
<style>
@import url("https://fonts.googleapis.com/css?family=Nunito:400,900");
* {
box-sizing: border-box;
}
body,
html {
font-family: "Nunito", sans-serif;
background: linear-gradient(0deg, #EEEFED, #F9E3E9);
margin: 0;
padding: 0;
color: #4D5075;
font-weight: 300;
width: 100%;
height: 100%;
margin: 0;
}
body {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 7vh 15vw 0vh 15vw;
}
h1 {
text-align: center;
margin: 0 0 10vh 0;
font-size: 7vh;
font-weight: 500;
text-shadow: 0px -15px 70px rgba(77, 80, 117, 0.6);
}
h1 b {
font-weight: 900;
}
p {
text-align: center;
font-size: 1.3rem;
text-shadow: 10px 5px 25px rgba(77, 80, 117, 0.6);
margin-bottom: 8vh;
}
.third-bar-p {
margin-top: 7vh;
}
.perspective {
-webkit-perspective: 70vh;
perspective: 70vh;
text-align: center;
-webkit-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
position: relative;
transition: -webkit-transform 0.3s ease;
transition: transform 0.3s ease;
transition: transform 0.3s ease, -webkit-transform 0.3s ease;
}
.perspective:hover {
-webkit-transform: scale(1.04);
transform: scale(1.04);
}
.bar-input {
position: absolute;
height: 100%;
left: 0;
right: 0;
margin: auto;
opacity: 0;
}
#first-bar .bar-input {
width: 55vh;
}
#second-bar .bar-input {
width: 40vh;
}
#third-bar .bar-input {
width: 42vh;
}
.bar {
display: inline-block;
position: relative;
-webkit-transform: rotateX(55deg);
transform: rotateX(55deg);
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.bar .bar-face {
display: inline-block;
width: 100%;
height: 100%;
position: absolute;
left: 0;
-webkit-transform-origin: 50% 100%;
transform-origin: 50% 100%;
}
.bar .bar-face.front {
-webkit-transform: rotateX(-90deg);
transform: rotateX(-90deg);
}
.bar .bar-face.percentage:before {
height: 100%;
content: "";
display: block;
position: absolute;
bottom: 0;
margin: 0;
}
#first-bar .bar {
width: 55vh;
height: 7vh;
}
#first-bar .bar .bar-face {
background: rgba(255, 255, 255, 0.5);
}
#first-bar .bar .bar-face.floor {
box-shadow: 0 1.3em 1.2em -0.4em rgba(0, 0, 70, 0.25), 0 -2em 15em 0.5em #4d5075, 0 -0.75em 25em 10em rgba(255, 255, 255, 0.4);
}
#first-bar .bar .bar-face.percentage:before {
box-shadow: 0 1.6em 7em -0.3em rgba(149, 65, 105, 0.5);
}
#first-bar .bar .bar-face.roof {
-webkit-transform: translateZ(7vh);
transform: translateZ(7vh);
}
#first-bar .bar .bar-face.back {
-webkit-transform: rotateX(-90deg) translateZ(-7vh);
transform: rotateX(-90deg) translateZ(-7vh);
}
#first-bar .bar .bar-face.percentage:before {
background-color: rgba(149, 65, 105, 0.6);
}
#second-bar .bar {
width: 40vh;
height: 10vh;
}
#second-bar .bar .bar-face {
background: rgba(60, 75, 132, 0.5);
background-image: linear-gradient(90deg, rgba(134, 114, 146, 0.5), rgba(60, 75, 132, 0.1)), url("https://zephyo.github.io/22Days/code/5/graphics/stars.svg"), url("https://zephyo.github.io/22Days/code/5/graphics/stars2.svg");
background-repeat: repeat repeat;
}
#second-bar .bar .bar-face.floor {
box-shadow: 0 1.3em 1.2em -0.4em rgba(0, 0, 70, 0.25), 0 -2em 15em 0.5em #4d5075, 0 -0.75em 25em 10em rgba(255, 255, 255, 0.4);
}
#second-bar .bar .bar-face.percentage:before {
box-shadow: 0 1.6em 7em -0.3em rgba(200, 212, 250, 0.5);
}
#second-bar .bar .bar-face.roof {
-webkit-transform: translateZ(10vh);
transform: translateZ(10vh);
}
#second-bar .bar .bar-face.back {
-webkit-transform: rotateX(-90deg) translateZ(-10vh);
transform: rotateX(-90deg) translateZ(-10vh);
}
#second-bar .bar .bar-face.percentage:before {
background-image: url("https://zephyo.github.io/22Days/code/5/graphics/sky.png");
opacity: 0.9;
}
#third-bar .bar {
width: 42vh;
height: 8vh;
}
#third-bar .bar .bar-face {
background: rgba(232, 154, 173, 0.7);
}
#third-bar .bar .bar-face.floor {
box-shadow: 0 1.3em 1.2em -0.4em rgba(0, 0, 70, 0.25), 0 -2em 15em 0.5em #4d5075, 0 -0.75em 25em 10em rgba(255, 255, 255, 0.4);
}
#third-bar .bar .bar-face.percentage:before {
box-shadow: 0 1.6em 7em -0.3em rgba(236, 0, 113, 0.5);
}
#third-bar .bar .bar-face.roof {
-webkit-transform: translateZ(8vh);
transform: translateZ(8vh);
}
#third-bar .bar .bar-face.back {
-webkit-transform: rotateX(-90deg) translateZ(-8vh);
transform: rotateX(-90deg) translateZ(-8vh);
}
#third-bar .bar .bar-face.percentage:before {
background: linear-gradient(90deg, rgba(245, 239, 200, 0.5), #ec0071);
}
#third-bar .bar .indicator {
box-shadow: 0px 15px 35px rgba(236, 0, 113, 0.3);
background: #ec0071;
width: 8vh;
height: 8vh;
color: white;
-webkit-transform: translateY(9.6vh);
transform: translateY(9.6vh);
text-align: center;
font-size: 2.5vh;
font-weight: 900;
line-height: 8vh;
}
#third-bar .bar .indicator:before {
content: "";
position: absolute;
background: #ec0071;
left: 0;
right: 0;
margin: auto;
top: -6px;
width: 4vh;
height: 4vh;
z-index: -1;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
</style>
</head>
<body>
<script src="/demos/googlegg.js"></script>
<h1>Scalable <b>3D</b> Range Sliders</h1>
<main class="perspective" id="first-bar">
<section class="bar">
<div class="bar-face back percentage"></div>
<div class="bar-face floor percentage"></div>
<div class="bar-face roof percentage"></div>
<div class="bar-face front percentage"></div>
</section>
<input class="bar-input" type="range" min="0" max="101" value="64" />
</main>
<p>Simple Range</p>
<main class="perspective" id="second-bar">
<section class="bar">
<div class="bar-face back percentage"></div>
<div class="bar-face floor percentage"></div>
<div class="bar-face roof percentage"></div>
<div class="bar-face front percentage"></div>
</section>
<input class="bar-input" type="range" min="0" max="101" value="37" />
</main>
<p>Patterned Range</p>
<main class="perspective" id="third-bar">
<section class="bar">
<div class="bar-face back percentage"></div>
<div class="bar-face floor percentage"></div>
<div class="bar-face roof percentage"></div>
<div class="bar-face front percentage"></div>
<div class="indicator">89%</div>
</section>
<input class="bar-input" type="range" min="0" max="100" value="89" />
</main>
<p class="third-bar-p">Gradient Range with Indicator</p>
<script>
function initInputs() {
var allInputs = document.body.querySelectorAll(".bar-input");
for (var i = 0; i < allInputs.length; i++) {
var input = allInputs[i];
var barId = input.parentNode.id;
var styleEl = document.head.appendChild(document.createElement("style"));
if (i == allInputs.length - 1) {
//set indicator
var indicator = input.parentNode.querySelector('.bar .indicator');
setBarIndicator(barId, input, styleEl, indicator);
input.oninput = setBarIndicator.bind(this, barId, input, styleEl, indicator);
input.onchange = setBarIndicator.bind(this, barId, input, styleEl, indicator);
} else {
setBar(barId, input, styleEl);
input.oninput = setBar.bind(this, barId, input, styleEl);
input.onchange = setBar.bind(this, barId, input, styleEl);
}
}
}
function setBar(barId, input, styleEl) {
styleEl.innerHTML =
"#" + barId + " .bar-face.percentage:before {width:" + input.value + "%;}";
}
function setBarIndicator(barId, input, styleEl, indicatorEl) {
styleEl.innerHTML =
"#" + barId + " .bar-face.percentage:before {width:" + input.value + "%;}";
indicatorEl.style.marginLeft = (input.value - 10) + '%';
indicatorEl.textContent = input.value + '%';
}
initInputs();
</script>
</div>
</body>
</html>
?? 唯美登錄背景
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HTML5 Canvas透明絲帶飄動(dòng)背景動(dòng)畫特效</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #000;
overflow: hidden;
}
.login-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div class="login-container"></div>
<script>
(function () {
let pi = Math.PI;
let pi2 = 2 * Math.PI;
this.Waves = function (holder, options) {
let Waves = this;
Waves.options = extend(options || {}, {
resize: false,
rotation: 45,
waves: 5,
width: 100,
hue: [11, 14],
amplitude: 0.5,
background: true,
preload: true,
speed: [0.004, 0.008],
debug: false,
fps: false,
});
Waves.waves = [];
Waves.holder = document.querySelector('.login-container');
Waves.canvas = document.createElement('canvas');
Waves.ctx = Waves.canvas.getContext('2d');
Waves.holder.appendChild(Waves.canvas);
Waves.hue = Waves.options.hue[0];
Waves.hueFw = true;
Waves.stats = new Stats();
Waves.resize();
Waves.init(Waves.options.preload);
if (Waves.options.resize)
window.addEventListener('resize', function () {
Waves.resize();
}, false);
};
Waves.prototype.init = function (preload) {
let Waves = this;
let options = Waves.options;
for (let i = 0; i < options.waves; i++)
Waves.waves[i] = new Wave(Waves);
if (preload) Waves.preload();
};
Waves.prototype.preload = function () {
let Waves = this;
let options = Waves.options;
for (let i = 0; i < options.waves; i++) {
Waves.updateColor();
for (let j = 0; j < options.width; j++) {
Waves.waves[i].update();
}
}
};
Waves.prototype.render = function () {
let Waves = this;
let ctx = Waves.ctx;
let options = Waves.options;
Waves.updateColor();
Waves.clear();
if (Waves.options.debug) {
ctx.beginPath();
ctx.strokeStyle = '#f00';
ctx.arc(Waves.centerX, Waves.centerY, Waves.radius, 0, pi2);
ctx.stroke();
}
if (Waves.options.background) {
Waves.background();
}
each(Waves.waves, function (wave, i) {
wave.update();
wave.draw();
});
};
Waves.prototype.animate = function () {
let Waves = this;
Waves.render();
// if (Waves.options.fps) {
// Waves.stats.log();
// Waves.ctx.font = '12px Arial';
// Waves.ctx.fillStyle = '#fff';
// Waves.ctx.fillText(Waves.stats.fps() + ' FPS', 10, 22);
// }
window.requestAnimationFrame(Waves.animate.bind(Waves));
};
Waves.prototype.clear = function () {
let Waves = this;
Waves.ctx.clearRect(0, 0, Waves.width, Waves.height);
};
Waves.prototype.background = function () {
let Waves = this;
let ctx = Waves.ctx;
let gradient = Waves.ctx.createLinearGradient(0, 0, 0, Waves.height);
gradient.addColorStop(0, '#000');
gradient.addColorStop(1, Waves.color);
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, Waves.width, Waves.height);
};
Waves.prototype.resize = function () {
let Waves = this;
let width = Waves.holder.offsetWidth;
let height = Waves.holder.offsetHeight;
Waves.scale = window.devicePixelRatio || 1;
Waves.width = width * Waves.scale;
Waves.height = height * Waves.scale;
Waves.canvas.width = Waves.width;
Waves.canvas.height = Waves.height;
Waves.canvas.style.width = width + 'px';
Waves.canvas.style.height = height + 'px';
Waves.radius = Math.sqrt(Math.pow(Waves.width, 2) + Math.pow(Waves.height, 2)) / 2;
Waves.centerX = Waves.width / 2;
Waves.centerY = Waves.height / 2;
//Waves.radius /= 2; // REMOVE FOR FULLSREEN
};
Waves.prototype.updateColor = function () {
let Waves = this;
Waves.hue += (Waves.hueFw) ? 0.01 : -0.01;
if (Waves.hue > Waves.options.hue[1] && Waves.hueFw) {
Waves.hue = Waves.options.hue[1];
Waves.Waves = false;
} else if (Waves.hue < Waves.options.hue[0] && !Waves.hueFw) {
Waves.hue = Waves.options.hue[0];
Waves.Waves = true;
}
let a = Math.floor(127 * Math.sin(0.3 * Waves.hue + 0) + 128);
let b = Math.floor(127 * Math.sin(0.3 * Waves.hue + 2) + 128);
let c = Math.floor(127 * Math.sin(0.3 * Waves.hue + 4) + 128);
Waves.color = 'rgba(' + a + ',' + b + ',' + c + ', 0.1)';
};
function Wave(Waves) {
let Wave = this;
let speed = Waves.options.speed;
Wave.Waves = Waves;
Wave.Lines = [];
Wave.angle = [
rnd(pi2),
rnd(pi2),
rnd(pi2),
rnd(pi2)
];
Wave.speed = [
rnd(speed[0], speed[1]) * rnd_sign(),
rnd(speed[0], speed[1]) * rnd_sign(),
rnd(speed[0], speed[1]) * rnd_sign(),
rnd(speed[0], speed[1]) * rnd_sign(),
];
return Wave;
}
Wave.prototype.update = function () {
let Wave = this;
let Lines = Wave.Lines;
let color = Wave.Waves.color;
Lines.push(new Line(Wave, color));
if (Lines.length > Wave.Waves.options.width) {
Lines.shift();
}
};
Wave.prototype.draw = function () {
let Wave = this;
let Waves = Wave.Waves;
let ctx = Waves.ctx;
let radius = Waves.radius;
let radius3 = radius / 3;
let x = Waves.centerX;
let y = Waves.centerY;
let rotation = dtr(Waves.options.rotation);
let amplitude = Waves.options.amplitude;
let debug = Waves.options.debug;
let Lines = Wave.Lines;
each(Lines, function (line, i) {
if (debug && i > 0) return;
let angle = line.angle;
let x1 = x - radius * Math.cos(angle[0] * amplitude + rotation);
let y1 = y - radius * Math.sin(angle[0] * amplitude + rotation);
let x2 = x + radius * Math.cos(angle[3] * amplitude + rotation);
let y2 = y + radius * Math.sin(angle[3] * amplitude + rotation);
let cpx1 = x - radius3 * Math.cos(angle[1] * amplitude * 2);
let cpy1 = y - radius3 * Math.sin(angle[1] * amplitude * 2);
let cpx2 = x + radius3 * Math.cos(angle[2] * amplitude * 2);
let cpy2 = y + radius3 * Math.sin(angle[2] * amplitude * 2);
ctx.strokeStyle = (debug) ? '#fff' : line.color;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x2, y2);
ctx.stroke();
if (debug) {
ctx.strokeStyle = '#fff';
ctx.globalAlpha = 0.3;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(cpx1, cpy1);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(x2, y2);
ctx.lineTo(cpx2, cpy2);
ctx.stroke();
ctx.globalAlpha = 1;
}
});
};
function Line(Wave, color) {
let Line = this;
let angle = Wave.angle;
let speed = Wave.speed;
Line.angle = [
Math.sin(angle[0] += speed[0]),
Math.sin(angle[1] += speed[1]),
Math.sin(angle[2] += speed[2]),
Math.sin(angle[3] += speed[3])
];
Line.color = color;
}
function Stats() {
this.data = [];
}
Stats.prototype.time = function () {
return (performance || Date)
.now();
};
Stats.prototype.log = function () {
if (!this.last) {
this.last = this.time();
return 0;
}
this.new = this.time();
this.delta = this.new - this.last;
this.last = this.new;
this.data.push(this.delta);
if (this.data.length > 10)
this.data.shift();
};
Stats.prototype.fps = function () {
let fps = 0;
each(this.data, function (data, i) {
fps += data;
});
return Math.round(1000 / (fps / this.data.length));
};
function each(items, callback) {
for (let i = 0; i < items.length; i++) {
callback(items[i], i);
}
}
function extend(options, defaults) {
for (let key in options)
if (defaults.hasOwnProperty(key))
defaults[key] = options[key];
return defaults;
}
function dtr(deg) {
return deg * pi / 180;
}
function rtd(rad) {
return rad * 180 / pi;
}
function diagonal_angle(w, h) {
let a = Math.atan2(h, w) * 1.27325;
return a;
}
function rnd(a, b) {
if (arguments.length == 1)
return Math.random() * a;
return a + Math.random() * (b - a);
}
function rnd_sign() {
return (Math.random() > 0.5) ? 1 : -1;
}
})();
let waves = new Waves('.login-container ', {
fps: true,
waves: 3,
width: 200,
});
waves.animate();
</script>
</body>
</html>
??? 蠟燭登錄動(dòng)畫
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CSS3可愛卡通蠟燭交互式動(dòng)畫特效</title>
<style>
body {
background: #13b280;
/* 背景 */
animation: change-background 5s infinite linear;
}
.wrapper {
position: absolute;
left: 80%;
top: 70%;
transform: scale(1.5, 1.5) translate(-50%, -50%);
}
.floor {
position: absolute;
left: 50%;
top: 50%;
width: 350px;
height: 5px;
background: #673C63;
transform: translate(-50%, -50%);
box-shadow: 0px 2px 5px #111;
z-index: 2;
}
.candles {
position: absolute;
left: 50%;
top: 50%;
width: 250px;
height: 150px;
transform: translate(-50%, -100%);
z-index: 1;
}
.candle1 {
position: absolute;
left: 50%;
top: 50%;
width: 35px;
height: 100px;
background: #fff;
border: 3px solid #673C63;
border-bottom: 0px;
border-radius: 3px;
transform-origin: center right;
transform: translate(60%, -25%);
box-shadow: -2px 0px 0px #95c6f2 inset;
/* 高蠟燭向上伸展動(dòng)畫 */
animation: expand-body 5s infinite linear;
}
.candle1__stick,
.candle2__stick {
position: absolute;
left: 50%;
top: 0%;
width: 3px;
height: 15px;
background: #673C63;
border-radius: 8px;
transform: translate(-50%, -100%);
}
.candle2__stick {
height: 12px;
transform-origin: bottom center;
/* 蠟燭芯 */
animation: stick-animation 5s infinite linear;
}
.candle1__eyes,
.candle2__eyes {
position: absolute;
left: 50%;
top: 0%;
width: 35px;
height: 30px;
transform: translate(-50%, 0%);
}
.candle1__eyes-one {
position: absolute;
left: 30%;
top: 20%;
width: 5px;
height: 5px;
border-radius: 100%;
background: #673C63;
transform: translate(-70%, 0%);
/* 高蠟燭眼睛 */
animation: blink-eyes 5s infinite linear;
}
.candle1__eyes-two {
position: absolute;
left: 70%;
top: 20%;
width: 5px;
height: 5px;
border-radius: 100%;
background: #673C63;
transform: translate(-70%, 0%);
/* 高蠟燭眼睛 */
animation: blink-eyes 5s infinite linear;
}
.candle1__mouth {
position: absolute;
left: 40%;
top: 20%;
width: 0px;
height: 0px;
border-radius: 20px;
background: #673C63;
transform: translate(-50%, -50%);
/* 高蠟燭嘴吹氣 */
animation: uff 5s infinite linear;
}
.candle__smoke-one {
position: absolute;
left: 30%;
top: 50%;
width: 30px;
height: 3px;
background: grey;
transform: translate(-50%, -50%);
/* 氣體動(dòng)畫 向左*/
animation: move-left 5s infinite linear;
}
.candle__smoke-two {
position: absolute;
left: 30%;
top: 40%;
width: 10px;
height: 10px;
border-radius: 10px;
background: grey;
transform: translate(-50%, -50%);
/* 氣體動(dòng)畫 向上 */
animation: move-top 5s infinite linear;
}
.candle2 {
position: absolute;
left: 20%;
top: 65%;
width: 42px;
height: 60px;
background: #fff;
border: 3px solid #673C63;
border-bottom: 0px;
border-radius: 3px;
transform: translate(60%, -15%);
transform-origin: center right;
box-shadow: -2px 0px 0px #95c6f2 inset;
/* 矮蠟燭 漲紅臉 */
animation: shake-left 5s infinite linear;
}
.candle2__eyes-one {
position: absolute;
left: 30%;
top: 50%;
width: 5px;
height: 5px;
display: inline-block;
border: 0px solid #673C63;
border-radius: 100%;
float: left;
background: #673C63;
transform: translate(-80%, 0%);
/* 矮蠟燭 眼睛 */
animation: changeto-lower 5s infinite linear;
}
.candle2__eyes-two {
position: absolute;
left: 70%;
top: 50%;
width: 5px;
height: 5px;
display: inline-block;
border: 0px solid #673C63;
border-radius: 100%;
float: left;
background: #673C63;
transform: translate(-80%, 0%);
/* 矮蠟燭眼睛 */
animation: changeto-greater 5s infinite linear;
}
.light__wave {
position: absolute;
top: 35%;
left: 35%;
width: 75px;
height: 75px;
border-radius: 100%;
z-index: 0;
transform: translate(-25%, -50%) scale(2.5, 2.5);
border: 2px solid rgba(255, 255, 255, 0.2);
/* 高蠟燭 向上伸張 */
animation: expand-light 5s infinite linear;
}
.candle2__fire {
position: absolute;
top: 50%;
left: 40%;
display: block;
width: 16px;
height: 20px;
background-color: red;
border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
background: #FF9800;
transform: translate(-50%, -50%);
/* 火焰 */
animation: dance-fire 5s infinite linear;
}
@keyframes blink-eyes {
0%,
35% {
opacity: 1;
transform: translate(-70%, 0%);
}
36%,
39% {
opacity: 0;
transform: translate(-70%, 0%);
}
40% {
opacity: 1;
transform: translate(-70%, 0%);
}
50%,
65% {
transform: translate(-140%, 0%);
}
66% {
transform: translate(-70%, 0%);
}
}
@keyframes expand-body {
0%,
40% {
transform: scale(1, 1) translate(60%, -25%);
}
45%,
55% {
transform: scale(1.1, 1.1) translate(60%, -28%);
}
60% {
transform: scale(0.89, 0.89) translate(60%, -25%);
}
65% {
transform: scale(1, 1) translate(60%, -25%);
}
70% {
transform: scale(0.95, 0.95) translate(60%, -25%);
}
75% {
transform: scale(1, 1) translate(60%, -25%);
}
}
@keyframes uff {
0%,
40% {
width: 0px;
height: 0px;
}
50%,
54% {
width: 15px;
height: 15px;
left: 30%;
}
59% {
width: 5px;
height: 5px;
left: 20%;
}
62% {
width: 2px;
height: 2px;
left: 20%;
}
67% {
width: 0px;
height: 0px;
left: 30%;
}
}
@keyframes change-background {
0%,
59%,
98%,
100% {
background: #13b280;
}
61%,
97% {
background: #F8AE39;
}
}
@keyframes move-left {
0%,
59%,
100% {
width: 0px;
left: 40%;
}
60% {
width: 30px;
left: 30%;
}
68% {
width: 0px;
left: 20%;
}
}
@keyframes move-top {
0%,
64%,
100% {
width: 0px;
height: 0px;
top: 0%;
}
65% {
width: 10px;
height: 10px;
top: 40%;
left: 40%;
}
80% {
width: 0px;
height: 0px;
top: 20%;
}
}
@keyframes shake-left {
0%,
40% {
left: 20%;
transform: translate(60%, -15%);
}
50%,
54% {
left: 20%;
transform: translate(60%, -15%);
}
59% {
left: 20%;
transform: translate(60%, -15%);
}
62% {
left: 18%;
transform: translate(60%, -15%);
}
65% {
left: 21%;
transform: translate(60%, -15%);
}
67% {
left: 20%;
transform: translate(60%, -15%);
}
75% {
left: 20%;
transform: scale(1.15, 0.85) translate(60%, -15%);
background: #fff;
border-color: #673C63;
}
91% {
left: 20%;
transform: scale(1.18, 0.82) translate(60%, -10%);
background: #F44336;
border-color: #F44336;
box-shadow: -2px 0px 0px #F44336 inset;
}
92% {
left: 20%;
transform: scale(0.85, 1.15) translate(60%, -15%);
}
95% {
left: 20%;
transform: scale(1.05, 0.95) translate(60%, -15%);
}
97% {
left: 20%;
transform: scale(1, 1) translate(60%, -15%);
}
}
@keyframes stick-animation {
0%,
40% {
left: 50%;
top: 0%;
transform: translate(-50%, -100%);
}
50%,
54% {
left: 50%;
top: 0%;
transform: translate(-50%, -100%);
}
59% {
left: 50%;
top: 0%;
transform: translate(-50%, -100%);
}
62% {
left: 50%;
top: 0%;
transform: rotateZ(-15deg) translate(-50%, -100%);
}
65% {
left: 50%;
top: 0%;
transform: rotateZ(15deg) translate(-50%, -100%);
}
70% {
left: 50%;
top: 0%;
transform: rotateZ(-5deg) translate(-50%, -100%);
}
72% {
left: 50%;
top: 0%;
transform: rotateZ(5deg) translate(-50%, -100%);
}
74%,
84% {
left: 50%;
top: 0%;
transform: rotateZ(0deg) translate(-50%, -100%);
}
85% {
transform: rotateZ(180deg) translate(0%, 120%);
}
92% {
left: 50%;
top: 0%;
transform: translate(-50%, -100%);
}
}
@keyframes expand-light {
10%,
29%,
59%,
89% {
transform: translate(-25%, -50%) scale(0, 0);
border: 2px solid rgba(255, 255, 255, 0);
}
90%,
20%,
50% {
transform: translate(-25%, -50%) scale(1, 1);
}
95%,
96%,
26%,
27%,
56%,
57% {
transform: translate(-25%, -50%) scale(2, 2);
border: 2px solid rgba(255, 255, 255, 0.5);
}
0%,
28%,
58%,
100% {
transform: translate(-25%, -50%) scale(2.5, 2.5);
border: 2px solid rgba(255, 255, 255, 0.2);
}
}
@keyframes dance-fire {
59%,
89% {
left: 40%;
width: 0px;
height: 0px;
}
90%,
0%,
7%,
15%,
23%,
31%,
39%,
47%,
55% {
left: 40.8%;
width: 16px;
height: 20px;
background: #FFC107;
}
94%,
3%,
11%,
19%,
27%,
35%,
43%,
51%,
58% {
left: 41.2%;
width: 16px;
height: 20px;
background: #FF9800;
}
}
@keyframes changeto-lower {
0%,
70%,
90% {
padding: 0px;
display: inline-block;
border-radius: 100%;
background: #673C63;
border-width: 0 0 0 0;
border: 0px solid #673C63;
transform: translate(-90%, 0%);
}
71%,
89% {
background: none;
border: solid #673C63;
border-radius: 0px;
border-width: 0 2px 2px 0;
display: inline-block;
padding: 1px;
float: left;
transform-origin: bottom left;
transform: rotate(-45deg) translate(-50%, -65%);
-webkit-transform: rotate(-45deg) translate(-50%, -65%);
}
}
@keyframes changeto-greater {
0%,
70%,
90% {
top: 50%;
padding: 0px;
display: inline-block;
border-radius: 100%;
background: #673C63;
border-width: 0 0 0 0;
border: 0px solid #673C63;
transform: translate(-80%, 0%);
}
71%,
89% {
top: 30%;
background: none;
border: solid #673C63;
border-radius: 0px;
border-width: 0 2px 2px 0;
display: inline-block;
padding: 1px;
float: left;
transform-origin: bottom left;
transform: rotate(135deg) translate(-80%, 20%);
-webkit-transform: rotate(135deg) translate(-80%, 20%);
}
}
</style>
</head>
<body>
<div class="wrapper">
<div class="candles">
<div class="light__wave"></div>
<div class="candle1">
<div class="candle1__body">
<div class="candle1__eyes">
<span class="candle1__eyes-one"></span>
<span class="candle1__eyes-two"></span>
</div>
<div class="candle1__mouth"></div>
</div>
<div class="candle1__stick"></div>
</div>
<div class="candle2">
<div class="candle2__body">
<div class="candle2__eyes">
<div class="candle2__eyes-one"></div>
<div class="candle2__eyes-two"></div>
</div>
</div>
<div class="candle2__stick"></div>
</div>
<div class="candle2__fire"></div>
<div class="sparkles-one"></div>
<div class="sparkles-two"></div>
<div class="candle__smoke-one">
</div>
<div class="candle__smoke-two">
</div>
</div>
<div class="floor">
</div>
</div>
</body>
</html>
?? 火箭?
源碼倉庫在后面,文件比較多,會影響閱讀,
?????? 時(shí)間翻盤
?原生js、vue版本,請移步倉庫里
?? 復(fù)選框動(dòng)畫
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CSS3 SVG點(diǎn)擊復(fù)選框勾選動(dòng)畫特效</title>
<style>
@import url("https://fonts.googleapis.com/css?family=Exo");
html {
font-size: 100%;
}
body {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background-color: #00acc1;
font-family: 'Exo', sans-serif;
}
input[type="checkbox"] {
display: none;
}
input[type="checkbox"] + .label {
position: relative;
padding-left: 1.7em;
color: #ffffff;
font-size: 3.125rem;
cursor: pointer;
}
input[type="checkbox"] + .label::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 1em;
height: 1em;
border: 3px solid #ffffff;
border-radius: 0.1em;
}
input[type="checkbox"] + .label::after {
content: '';
position: absolute;
top: 0.1em;
left: 0.1em;
width: 0.92em;
height: 0.92em;
transform: scale(0);
background-color: #ffffff;
border-radius: 0.02em;
transition: all 0.2s linear;
opacity: 0;
}
input[type="checkbox"] + .label svg {
position: absolute;
top: 0.2em;
left: 0.12em;
z-index: 1;
}
input[type="checkbox"] + .label #check-icon {
stroke: #00acc1;
stroke-dasharray: 36;
stroke-dashoffset: 36;
}
input[type="checkbox"]:checked + .label::after {
transform: scale(1);
opacity: 1;
}
input[type="checkbox"]:checked + .label #check-icon {
animation-name: check-animation;
animation-duration: 0.2s;
animation-delay: 0.4s;
animation-fill-mode: forwards;
animation-timing-function: cubic-bezier(1, 0.12, 0.96, 0.62);
}
@keyframes check-animation {
0% {
stroke-dashoffset: 36;
}
100% {
stroke-dashoffset: 0;
}
}
</style>
</head>
<body>
<input type="checkbox" id="check-me">
<label for="check-me" class="label">
Check Me!
<svg viewBox="-9 -9 43 35.191" width="43" height="35">
<path id="check-icon" d=" M 0 9 Q 8 17 8 17 Q 8 17 25 0" fill="none" stroke-width="6" stroke="rgb(0,0,0)" stroke-linecap="round" />
</svg>
</label>
</body>
</html>
?? 基礎(chǔ)表單輸入動(dòng)畫
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>form input動(dòng)畫</title>
<style>
input[type='text'],
input[type='password'] {
height: 40px;
width: 200px;
background: transparent;
border: none;
border-bottom: 1px solid #999;
text-indent: 20px;
transition: 0.3;
outline: none;
}
input[type='text']:hover,
input[type='password']:hover {
border-color: #42b983;
}
input[type='text']:focus,
input[type='password']:focus {
border-bottom-color: #f1190d;
}
input[type='password']::-webkit-input-placeholder,
input[type='text']::-webkit-input-placeholder {
transition: 0.5s;
font-size: 14px;
transform-origin: top left;
}
input[type='password']:focus::-webkit-input-placeholder,
input[type='text']:focus::-webkit-input-placeholder {
transform: scale(0.8) translateY(-10px);
}
</style>
</head>
<body>
<input type="text" placeholder="請輸入您的姓名" />
<input type="password" placeholder="請輸入您的密碼" />
</body>
</html>
?? 卡包動(dòng)畫
<template>
<div>
<div class="tariffCards">
<div class="economy">
<img
src="https://creditcard.ecitic.com/2019_gw/images/g-logo.png"
alt="中信銀行"
height="74"
/>
<h3>中信銀行</h3>
<span>zhongxin bank</span>
</div>
<div class="premiumeconomy">
<img
src="https://www.bankofchina.com/images/boc2013_logo.png"
alt="中國銀行"
height="30"
/>
<h3>中國銀行</h3>
<span>chinease bank</span>
</div>
<div class="business">
<img
src="http://www.jsbchina.cn/data/tosend/resource/upload/20201127/f97a668d-3cce-435c-8cb5-ca4e69b86aec.jpg"
alt="交通銀行"
height="74"
/>
<h3>交通銀行</h3>
<span>jiaotong bank</span>
</div>
<div class="first">
<img
src="http://www.jsbchina.cn/CN/index.html"
alt="江蘇銀行"
height="74"
/>
<h3>江蘇銀行</h3>
<span>jiangsu bank</span>
</div>
</div>
</div>
</template>
<style scoped>
.tariffCards {
position: absolute;
top: 50%;
left: 50%;
margin: -180px 0 0 -140px;
user-select: none;
transform: translate3d(0, 0, 0);
transform-style: preserve-3d;
}
.tariffCards:after {
position: absolute;
bottom: -27px;
left: 5%;
content: '';
width: 65%;
height: 10px;
border-radius: 100%;
background-image: radial-gradient(
rgba(34, 50, 84, 0.04),
rgba(34, 50, 84, 0)
);
}
.tariffCards > div {
position: relative;
width: 280px;
height: 140px;
border-radius: 12px;
color: white;
transform: rotateX(45deg) rotateY(-15deg) rotate(45deg);
transition: all 0.4s ease;
overflow: hidden;
cursor: pointer;
}
.tariffCards > div:after {
position: absolute;
top: -70px;
left: 0;
content: '';
width: 200%;
height: 200%;
background-image: linear-gradient(
60deg,
rgba(255, 255, 255, 0) 20%,
rgba(255, 255, 255, 0.1),
rgba(255, 255, 255, 0) 80%
);
transform: translateX(-100%);
}
.tariffCards > div img {
margin-top: 15px;
pointer-events: none;
}
.tariffCards > div h3 {
position: absolute;
bottom: 28px;
left: 15px;
font-size: 18px;
font-weight: 800;
}
.tariffCards > div span {
position: absolute;
font-weight: 700;
bottom: 15px;
left: 15px;
font-size: 12px;
font-weight: 600;
opacity: 0.8;
}
.tariffCards > div.economy {
margin-top: 0;
z-index: 3;
background-color: #8063e1;
background-image: linear-gradient(135deg, #bd7be8, #8063e1);
box-shadow: 20px 20px 60px rgba(34, 50, 84, 0.5), 1px 1px 0px 1px #8063e1;
}
.tariffCards > div.premiumeconomy {
margin-top: -70px;
z-index: 2;
background-color: #3f58e3;
background-image: linear-gradient(135deg, #7f94fc, #3f58e3);
box-shadow: 20px 20px 60px rgba(34, 50, 84, 0.5), 1px 1px 0px 1px #3f58e3;
}
.tariffCards > div.business {
margin-top: -70px;
z-index: 1;
background-color: #2c6fd1;
background-image: linear-gradient(135deg, #21bbfe, #2c6fd1);
box-shadow: 20px 20px 60px rgba(34, 50, 84, 0.5), 1px 1px 0px 1px #2c6fd1;
}
.tariffCards > div.first {
margin-top: -70px;
background-color: #352f64;
background-image: linear-gradient(135deg, #415197, #352f64);
box-shadow: 5px 5px 60px rgba(34, 50, 84, 0.1), 1px 1px 0px 1px #352f64;
}
.tariffCards > div:hover {
transform: rotateX(30deg) rotateY(-15deg) rotate(30deg) translate(-25px, 50px);
}
.tariffCards > div:hover:after {
transform: translateX(100%);
transition: all 1.2s ease-in-out;
}
</style>
?? 流光掃過動(dòng)畫
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.flash-container {
width: 148px;
height: 148px;
background: #333333;
margin: 0 auto;
position: relative;
overflow: hidden;
&::after {
content: '';
height: 150%;
width: 25px;
background: #fff;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
opacity: 0.6;
filter: blur(6px);
animation: move 2s infinite ease-out;
}
}
@keyframes move {
0% {
transform: translate(-200px, -200px) rotate(45deg);
}
100% {
transform: translate(200px, 200px) rotate(45deg);
}
}
</style>
</head>
<body>
<div class="flash-container">
<img src="https://img-blog.csdnimg.cn/180fbfb5f0434211b3e8640891ecea33.gif" alt />
</div>
</body>
</html>
?? 酷炫標(biāo)題
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.wrap {
position: relative;
display: inline-block;
left: 50%;
top: 20px;
}
.wrap span {
position: relative;
z-index: 2;
display: inline-block;
padding: 0 15px;
height: 32px;
line-height: 32px;
background-color: #42b983;
color: #fff;
font-size: 16px;
box-shadow: 0 10px 6px -9px rgba(0, 0, 0, 0.6);
}
.wrap span::before,
.wrap span::after {
position: absolute;
bottom: -6px;
border-width: 3px 5px;
border-style: solid;
content: '';
}
.wrap span::before {
left: 0;
border-color: #42b983 #42b983 transparent transparent;
}
.wrap span::after {
right: 0;
border-color: #42b983 transparent transparent #42b983;
}
.wrap::before,
.wrap::after {
position: absolute;
top: 6px;
content: '';
border-style: solid;
border-color: #42b983;
}
.wrap::before {
left: -32px;
border-width: 16px 26px 16px 16px;
border-left-color: transparent;
}
.wrap::after {
right: -32px;
border-width: 16px 16px 16px 26px;
border-right-color: transparent;
}
</style>
</head>
<body>
<div class="wrap">
<span>距離高考還有10天</span>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
padding: 20px;
}
.wrap {
position: relative;
background-color: pink;
height: 200px;
/* width: 500px;
margin: 0 auto; */
}
.left {
width: 200px;
height: 140px;
position: absolute;
top: -8px;
left: -8px;
overflow: hidden;
}
.left::before {
position: absolute;
left: 124px;
border-radius: 8px 8px 0 0;
width: 16px;
height: 8px;
background-color: #42b983;
content: '';
}
.left::after {
position: absolute;
left: 0;
top: 124px;
border-radius: 0 8px 8px 0;
width: 8px;
height: 16px;
background-color: #42b983;
content: '';
}
.left span {
display: inline-block;
text-align: center;
width: 200px;
height: 40px;
line-height: 40px;
position: absolute;
top: 30px;
left: -50px;
z-index: 2;
overflow: hidden;
-ms-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
transform: rotate(-45deg);
border: 1px dashed #fff;
box-shadow: 0 0 0 3px #42b983, 0 14px 7px -9px rgba(0, 0, 0, 0.6);
background-color: #42b983;
color: #fff;
}
.right {
width: 140px;
height: 200px;
position: absolute;
top: -8px;
right: -8px;
overflow: hidden;
}
.right::before {
position: absolute;
right: 124px;
border-radius: 8px 8px 0 0;
width: 16px;
height: 8px;
background-color: #42b983;
content: '';
}
.right::after {
position: absolute;
right: 0;
top: 124px;
border-radius: 0 8px 8px 0;
width: 8px;
height: 16px;
background-color: #42b983;
content: '';
}
.right span {
display: inline-block;
text-align: center;
width: 200px;
height: 40px;
line-height: 40px;
position: absolute;
top: 30px;
right: -50px;
z-index: 2;
overflow: hidden;
-ms-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
border: 1px dashed #fff;
box-shadow: 0 0 0 3px #42b983, 0 14px 7px -9px rgba(0, 0, 0, 0.6);
background-color: #42b983;
color: #fff;
}
</style>
</head>
<body>
<div class="wrap">
<div class="left">
<span>張</span>
</div>
<div class="right">
<span>坤</span>
</div>
</div>
</body>
</html>
?? 交互式評分
?文件較多、參考倉庫
?? 動(dòng)態(tài)向上箭頭
????卸載對話框表情交互動(dòng)畫
????隨機(jī)密碼生成器代碼
?下面是功能篇章
???跟隨設(shè)備切換主題
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>切換主題 dark、light、system</title>
<style>
/* dark 主題 */
[data-theme="dark"] {
--text-color: white;
--background-color: black;
}
/* light 主題 */
[data-theme="light"] {
--text-color: black;
--background-color: white;
}
body {
color: var(--text-color);
background-color: var(--background-color);
}
</style>
</head>
<body>
<h1>跟隨設(shè)備切換主題</h1>
<p>這是一段測試文本。</p>
<img src="https://www4.bing.com//th?id=OHR.GoliathHeron_ZH-CN2413747227_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp&w=360&h=202"
alt="">
<!-- 下拉框 -->
<select id="select-wrap" title="切換主題">
<option value="light">light</option>
<option value="dark">dark</option>
<option value="system">system</option>
</select>
<script>
const selectWrap = document.querySelector('#select-wrap');
const bodyTheme = document.querySelector('body');
window.onload = () => {
// 獲取用戶的選擇
const theme = localStorage.getItem('theme');
// 如果用戶選擇了主題,就設(shè)置主題同時(shí)改變下拉框的選中項(xiàng)
if (theme) {
// 設(shè)置下拉框的選中項(xiàng)
selectWrap.value = theme;
// 動(dòng)態(tài)設(shè)置 system 主題
setTheme()
}
}
// 監(jiān)聽下拉框的變化
selectWrap.onchange = () => {
setTheme()
localStorage.setItem('theme', selectWrap.value);
}
// 動(dòng)態(tài)設(shè)置 system 主題 函數(shù)
function setTheme() {
/*
下拉框改變時(shí),先移除 system 主題,因?yàn)閐ark、light主題不需要使用系統(tǒng)主題,
系統(tǒng)主題只需要在下拉框選擇 system 時(shí)才需要使用,動(dòng)態(tài)添加,解決系統(tǒng)切換主題時(shí),項(xiàng)目不需要刷新
*/
removeSystemLink()
if (selectWrap.value === 'system') {
setTimeout(() => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = './system.css';
// 加上名稱方便找到移除
link.id = 'system';
// 在head中插入link 添加到最后
document.head.appendChild(link);
}, 0);
// 在某個(gè)元素前面插入一個(gè)元素 語法:parentElement.insertBefore(newElement, targetElement)
// parentElement是要插入新元素的父元素,newElement是要插入的新元素對象,targetElement是當(dāng)前元素的前一個(gè)兄弟元素,也就是新元素要插入到這個(gè)元素之前。
// 例子:在head中插入link 添加到最前面
// document.head.insertBefore(link, document.head.firstChild);
// document.head.insertBefore(link, document.head.children[0]);
// 或者:document.head.insertBefore(link, document.head.lastChild); // 在head中插入link 添加到最后面
// 或者:document.head.insertBefore(link, document.querySelector('title')); // 在head中插入link 添加到title前面
} else {
// 動(dòng)態(tài)設(shè)置 light 和 dark 主題
bodyTheme.setAttribute('data-theme', selectWrap.value);
}
}
/*
移除 system 主題 函數(shù):
有時(shí)候切換系統(tǒng)主題了,項(xiàng)目還要刷新一下:
因?yàn)橄到y(tǒng)主題的切換需要重新加載樣式表才能生效,但有時(shí)候頁面中的部分元素已經(jīng)渲染出來,
樣式表被加載后并不會自動(dòng)刷新渲染結(jié)果。在這種情況下,動(dòng)態(tài)移除和添加樣式表就能解決這個(gè)問題。
*/
function removeSystemLink() {
const link = document.querySelector('#system');
if (link) link.remove();
}
</script>
</body>
</html>
?system.css
:root {
--text-color: black;
--background-color: white;
}
@media (prefers-color-scheme: dark) {
:root {
--text-color: white;
--background-color: black;
}
}
body {
color: var(--text-color);
background-color: var(--background-color);
}
?? 晝夜切換主題
???????使用系統(tǒng)取色器
<!DOCTYPE html>
<html>
<head>
<title>使用系統(tǒng)取色器</title>
<style>
.box {
width: 200px;
height: 200px;
border: 1px solid black;
}
</style>
</head>
<body>
<button>打開取色器</button>
<div class="box"></div>
<br>
<label></label>
<script>
const btn = document.querySelector('button');
const box = document.querySelector('.box');
const label = document.querySelector('label');
btn.onclick = async () => {
const dropper = new EyeDropper();
try {
const result = await dropper.open();
console.log(result);
box.style.backgroundColor = result.sRGBHex;
label.textContent = result.sRGBHex;
} catch {
console.log('用戶取消了操作');
}
}
</script>
</body>
</html>
?? 右鍵動(dòng)態(tài)菜單(已做邊緣動(dòng)畫及邊界外判斷)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>右鍵菜單</title>
<style>
* {
margin: 0;
padding: 0;
}
#context-menu {
position: fixed;
width: 300px;
height: 400px;
background-image: linear-gradient(235deg, #f7f0ac, #acf7f0, #f0acf7);
transition: all 0.3s ease-in-out;
border-radius: 5px;
/* 使用 display: none; 會造成邊界判斷失敗 */
visibility: hidden;
opacity: 0;
z-index: 9999;
}
.menu-item {
padding: 10px;
cursor: pointer;
}
.menu-item:hover {
background-color: #d6d6d6;
}
.rebound {
animation: rebound .5s;
}
@keyframes rebound {
0% {
transform: translate(-100%, 0);
opacity: 0;
}
40% {
transform: translate(10%, 0);
}
70% {
transform: translate(-5%, 0);
}
100% {
transform: translate(0);
opacity: 1;
}
}
</style>
</head>
<body>
<div id="context-menu">
<div class="menu-item">菜單項(xiàng)1</div>
<div class="menu-item">菜單項(xiàng)2</div>
<div class="menu-item">菜單項(xiàng)3</div>
</div>
<script>
const contextMenu = document.getElementById('context-menu');
function setPosition(event, menu) {
// 獲取窗口寬度和高度
const screenWidth = window.innerWidth;
const screenHeight = window.innerHeight;
// 獲取菜單寬度和高度
const menuWidth = menu.offsetWidth;
const menuHeight = menu.offsetHeight;
// 獲取鼠標(biāo)在頁面中的位置
const x = event.clientX;
const y = event.clientY;
// 計(jì)算菜單的調(diào)整后的水平位置和垂直位置
const adjustedX = (x + menuWidth) >= screenWidth ? (x - menuWidth) : x; // 檢查是否超出右側(cè)邊界
const adjustedY = (y + menuHeight) >= screenHeight ? (y - menuHeight) : y; // 檢查是否超出底部邊界
// 如果超出右側(cè)邊界,讓菜單反彈一下
if (adjustedX !== x) {
menu.classList.add('rebound');
setTimeout(() => {
menu.classList.remove('rebound');
}, 1000);
}
// 設(shè)置菜單的位置
menu.style.left = adjustedX + 'px';
menu.style.top = adjustedY + 'px';
}
document.addEventListener('contextmenu', function (event) {
event.preventDefault(); // 阻止系統(tǒng)默認(rèn)的右鍵菜單
setPosition(event, contextMenu); // 計(jì)算并設(shè)置菜單的位置
contextMenu.style.visibility = 'visible'; // 顯示菜單
contextMenu.style.opacity = '1';
});
// 如果點(diǎn)擊的地方不在菜單內(nèi),隱藏菜單
document.addEventListener('click', function (event) {
console.log(event.target);
console.log(contextMenu);
if (contextMenu !== event.target) {
contextMenu.style.visibility = 'hidden';
contextMenu.style.opacity = '0';
}
});
const menuItems = document.querySelectorAll('.menu-item');
// 為每個(gè)菜單項(xiàng)添加事件監(jiān)聽 不優(yōu)化
// for (let i = 0; i < menuItems.length; i++) {
// menuItems[i].addEventListener('click', function (event) {
// console.log(`您點(diǎn)擊了菜單項(xiàng)${i + 1}`);
// contextMenu.style.visibility = 'visible';
// });
// menuItems[i].addEventListener('mousedown', function (event) {
// event.stopPropagation();
// });
// }
// 使用事件委托 優(yōu)化
contextMenu.addEventListener('click', function (event) {
const target = event.target;
if (target.classList.contains('menu-item')) {
// indexOf() 返回指定元素在目標(biāo)隊(duì)列中首次出現(xiàn)的索引,找不到指定元素,則會返回 -1。
// call 第一個(gè)參數(shù)是指定該方法執(zhí)行時(shí)的上下文環(huán)境(寫誰指向誰),第二個(gè)參數(shù),它表示要傳遞給被調(diào)用的方法的參數(shù)。
const index = Array.prototype.indexOf.call(menuItems, target);
console.log(`您點(diǎn)擊了菜單項(xiàng)${index + 1}`);
}
});
</script>
</body>
</html>
?? 酷炫打字特效
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>刪庫跑路</title>
<style>
* {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
box-sizing: border-box;
color: inherit;
}
body {
background-image: linear-gradient(120deg, #4f0088 0%, #000 100%);
height: 100vh;
}
div {
background: rgba(0, 0, 0, 0);
width: 70vw;
position: relative;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
margin: 0 auto;
padding: 30px 30px 10px;
box-shadow: 0 0 150px -20px rgba(0, 0, 0, 0.5);
z-index: 3;
}
P {
font-family: "Share Tech Mono", monospace;
color: #f5f5f5;
margin: 0 0 20px;
font-size: 17px;
line-height: 1.2;
}
span {
color: #f0c674;
}
i {
color: #8abeb7;
}
div a {
text-decoration: none;
}
b {
color: #81a2be;
}
a.avatar {
position: fixed;
bottom: 15px;
right: -100px;
-webkit-animation: slide 0.5s 4.5s forwards;
animation: slide 0.5s 4.5s forwards;
display: block;
z-index: 4;
}
a.avatar img {
border-radius: 100%;
width: 44px;
border: 2px solid white;
}
@-webkit-keyframes slide {
from {
right: -100px;
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
opacity: 0;
}
to {
right: 15px;
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
opacity: 1;
}
}
@keyframes slide {
from {
right: -100px;
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
opacity: 0;
}
to {
right: 15px;
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
opacity: 1;
}
}
</style>
</head>
<body>
<div id="container">
<p>
>
<span> [root@VM-0-7-centos ~]# </span>
: "
<i> rm -rf /*正在刪除本地的數(shù)據(jù) </i>
"
</p>
<p>
>
<span> [root@VM-0-7-centos ~]# </span>
: "
<i> 刪除成功 </i>
"
</p>
<p>
>
<span> [root@VM-0-7-centos ~]# </span>
: "
<i> 文件備份自動(dòng)啟用中... </i>
"
</p>
<p>
>
<span> [root@VM-0-7-centos ~]# </span>
: "
<i> 備份失敗! 僅備份文件碎片... </i>
"
</p>
<p>
>
<span> [root@VM-0-7-centos ~]# </span>
: "
<i> 文件碎片正在加載... </i>
"
</p>
<p>
>
<span> [root@VM-0-7-centos ~]# </span>
: "
<i> 加載失敗 對不起我們跑路了... </i>
"
</p>
<p>
>
<span> [root@VM-0-7-centos ~]# </span>
: "
<i> 不要傷心 不要難過... </i>
"
</p>
<p>
>
<span> [root@VM-0-7-centos ~]# </span>
: "
<i> 或許我們還會再建個(gè)站繼續(xù)騙你 ... </i>
"
</p>
</div>
<script>
// 將元素內(nèi)容轉(zhuǎn)換為字符串
let str = document.querySelector("#container").innerHTML.toString();
let i = 0;
let containerHtml = document.querySelector("#container");
containerHtml.innerHTML = "";
setTimeout(function () {
let se = setInterval(function () {
i++;
// str.slice(start, end) 表示從 str 字符串的 start 索引處開始,提取到 end 索引處之前(不包含 end)的子串。如果不指定 end 參數(shù),則默認(rèn)提取到字符串末尾。
containerHtml.innerHTML = str.slice(0, i) + "|";
if (i == str.length) {
clearInterval(se);
containerHtml.innerHTML = str;
}
}, 30);
}, 0);
</script>
</body>
</html>
?? 方形抽獎(jiǎng)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>轉(zhuǎn)盤</title>
<style>
.main {
display: flex;
width: 320px;
flex-wrap: wrap;
}
.item {
width: 100px;
height: 100px;
background-color: #ddd;
display: flex;
align-items: center;
justify-content: center;
border: 2px solid #fff;
}
.item.active {
background-color: #999;
}
.item.btn {
background-color: green;
color: #fff;
}
</style>
</head>
<body>
<div class="main"></div>
<script>
window.onload = () => {
const data = {
jp: [
{ name: "代金券1" },
{ name: "代金券2", is: true },
{ name: "代金券3" },
{ name: "代金券4" },
{ name: "代金券5" },
{ name: "代金券6" },
{ name: "代金券7" },
{ name: "代金券8" },
],
};
const main = document.querySelector(".main");
main.innerHTML = data.jp
.map(
(v) =>
`<div class="item" ${v.is ? "is='true'" : ""}>${v.name}</div>`
)
.join("");
const btnEl = document.createElement("div");
btnEl.className = "item btn";
btnEl.innerHTML = "抽獎(jiǎng)";
main.insertBefore(btnEl, main.children[4]);
let isRunning = false;
let itemIndex = 0;
const spinWheel = () => {
const nodesList = [...main.childNodes].filter(
(v) => !v.classList.contains("btn")
);
const spinOrder = [0, 1, 2, 4, 7, 6, 5, 3];
const spinItems = spinOrder.map((v) => nodesList[v]);
if (!spinItems[itemIndex]) {
itemIndex = 0;
}
const active1 = main.querySelector(".active");
active1 && active1.classList.remove("active");
spinItems[itemIndex].classList.add("active");
if (!isRunning && spinItems[itemIndex].getAttribute("is")) {
clearInterval(intervalId);
}
itemIndex++;
};
let intervalId;
btnEl.onclick = () => {
if (isRunning) return;
isRunning = true;
intervalId = setInterval(spinWheel, 100);
setTimeout(() => {
isRunning = false;
}, 3000);
};
};
</script>
</body>
</html>
?? 圓形抽獎(jiǎng)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>轉(zhuǎn)盤</title>
<style>
.zp {
position: relative;
border-radius: 100%;
width: 300px;
overflow: hidden;
margin:0 auto;
}
.zp-panel {
background: url(./images/zp.webp) no-repeat center center;
background-size: 100%;
width: 300px;
height: 300px;
position: relative;
transition: transform 4s ease-out;
}
.item {
font-size: 12px;
position: absolute;
top: 50%;
left: 0;
right: 0;
text-align: center;
margin-top: -7px;
line-height: 1;
}
.btn {
position: absolute;
background-color: green;
width: 80px;
height: 80px;
border-radius: 100%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
z-index: 2;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
.btn:after {
content: '';
position: absolute;
height: 80px;
width: 4px;
background-color: green;
left: 38px;
bottom: 60px;
}
</style>
</head>
<body>
<div class="zp">
<div class="zp-panel"></div>
<div class="btn">開始</div>
</div>
</body>
<script>
const arr = [
{name: '積分+1'},
{name: '積分+2'},
{name: '積分+3'},
{name: '積分+4'},
{name: '電動(dòng)車一輛', is: true},
{name: '積分+10'}
]
const zp = document.querySelector('.zp-panel')
const btn = document.querySelector('.btn')
const d = 360 / arr.length
zp.innerHTML = arr.map((v, i) => {
return `<div class="item"
style="transform:rotate(${i*d - 90}deg) translate(75px)">${v.name}</div>`
}).join('')
btn.onclick = () => {
const zpIndex = arr.findIndex(v => v.is)
const deg = -(zpIndex * d + 720)
// 清空上次抽獎(jiǎng),暫停動(dòng)畫效果
zp.style.transition = 'inherit'
zp.style.transform = ''
setTimeout(() => {
// 重置transition,恢復(fù)動(dòng)畫效果
zp.style.transition = ''
setTimeout(() => {
// 觸發(fā)動(dòng)畫
zp.style.transform = `rotate(${deg}deg)`
})
})
}
</script>
</html>
?? 吸頂樓層導(dǎo)航
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>樓層滾動(dòng)</title>
</head>
<style>
* {
padding: 0;
margin: 0;
}
body,
html {
height: auto;
width: 100%;
background-image: linear-gradient(to right, #f7f0ac, #acf7f0, #f0acf7);
}
.nav-wrap {
position: fixed;
z-index: 99;
top: 50%;
left: 120px;
transform: translateY(-50%);
width: 100px;
height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
.stick {
position: sticky;
top: 10px;
height: 15px;
padding: 5px;
line-height: 15px;
background-color: #5f9ea0;
color: #ffff;
font-weight: 900;
}
.nav {
width: 100px;
flex: 1;
margin-bottom: 10px;
background: url(https://img1.baidu.com/it/u=105002249,3897918256&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281)
no-repeat center center/cover;
display: flex;
align-items: center;
justify-content: center;
font-size: 25px;
}
.main {
text-align: center;
line-height: 900px;
font-size: 30px;
color: #ffff;
width: 800px;
height: 900px;
/* background-color: hsla(0, 0%, 100%, 0.2); */
background: rgba(255, 255, 255, 0.4);
position: relative;
left: 50%;
transform: translateX(-50%);
}
.nav-active {
color: red;
background: url("https://img1.baidu.com/it/u=833204098,2930185410&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=745")
no-repeat center center/cover;
}
</style>
<body>
<div class="nav-wrap">
<div class="nav">A</div>
<div class="nav">B</div>
<div class="nav">C</div>
<div class="nav">D</div>
</div>
<div class="main">A</div>
<div class="main">
<div class="stick">B</div>
</div>
<div class="main">
<div class="stick">C</div>
</div>
<div class="main">
<div class="stick">D</div>
</div>
</body>
<script>
const navAll = document.querySelector(".nav-wrap");
const mainAll = document.querySelectorAll(".main");
function reset() {
for (let i = 0; i < navAll.children.length; i++) {
navAll.children[i].classList.remove("nav-active");
}
}
// 進(jìn)入頁面時(shí),第一個(gè)導(dǎo)航欄高亮
navAll.children[0].classList.add("nav-active");
navAll.addEventListener("click", (event) => {
if (event.target.classList.contains("nav")) {
const index = Array.from(navAll.children).indexOf(event.target);
console.log(index);
window.scrollTo({
top: Math.floor(mainAll[index].offsetTop),
behavior: "smooth",
});
}
});
window.addEventListener("scroll", () => {
const scrollTop = document.scrollingElement.scrollTop;
let left = 0;
let right = navAll.children.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
const currentMain = mainAll[mid];
if (
currentMain.offsetTop <= scrollTop &&
currentMain.offsetTop + currentMain.offsetHeight > scrollTop
) {
reset();
navAll.children[mid].classList.add("nav-active");
break;
} else if (currentMain.offsetTop > scrollTop) {
right = mid - 1;
} else {
left = mid + 1;
}
}
});
</script>
</html>
?? 困了蓋坤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>羊了個(gè)羊</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.main {
position: relative;
}
.item {
position: absolute;
background: no-repeat center center #ffffff;
border: 1px solid #ddd;
background-size: 100%;
color: transparent;
display: flex;
justify-content: center;
align-items: center;
z-index: 0;
transition: left 0.3s, top 0.3s, transform 0.3s;
}
.item:after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
transition: background-color 0.2s;
}
.disabled:after {
background-color: rgba(0, 0, 0, 0.7);
}
.move-list {
border: 1px solid #ddd;
background-color: #ddd;
margin: 0 auto;
}
</style>
</head>
<body>
<div class="main"></div>
<div class="move-list"></div>
</body>
<script>
// 基礎(chǔ)數(shù)據(jù)
const simpleData = [
{ name: "虎", color: "#ff1100", bg: "./xxl-img/1.png" },
{ name: "兔", color: "#ff8800", bg: "./xxl-img/2.png" },
{ name: "牛", color: "green", bg: "./xxl-img/3.png" },
{ name: "羊", color: "blue", bg: "./xxl-img/4.png" },
{ name: "蛇", color: "#779922", bg: "./xxl-img/5.png" },
{ name: "鼠", color: "#335577", bg: "./xxl-img/6.png" },
];
// 卡片大小
const size = 40;
// 矩陣行
const rows = 10;
// 矩陣列
const cols = 10;
// 每組為3個(gè)
const oneGoupCount = 3;
// 每個(gè)卡片有x組
const group = 6;
// 總共6層,即6個(gè)表格
const layerCount = 6;
// 表格html
const cellHtml = [];
// 將生成所有的十二生肖
const renderData = Array.from(new Array(oneGoupCount * group))
.map((v) => {
return simpleData.map((v) => ({ ...v }));
})
.flat()
.sort((v) => Math.random() - 0.5);
// 第一步:繪制出表格矩陣
for (let ly = layerCount - 1; ly >= 0; ly--) {
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
let pyStep = (ly + 1) % 2 === 0 ? size / 2 : 0;
let item = Math.random() > 0.7 && renderData.pop();
item &&
cellHtml.push(`<div class="item" onclick="move(this)" id="m${ly}-${i}-${j}"
style="width:${size}px;height:${size}px;left:${size * j + pyStep}px;top:${size * i + pyStep
}px;background-image:url(${item.bg || ""})">${item.name || ""}</div>`);
}
}
}
const main = document.querySelector(".main");
const moveList = document.querySelector(".move-list");
main.innerHTML = cellHtml.reverse().join("");
main.style.height = `${size * rows + size * 2}px`;
main.style.width = `${size * cols}px`;
moveList.style.height = `${size}px`;
moveList.style.width = `${size * 6}px`;
// 第二步:計(jì)算被遮住的底牌需標(biāo)暗色
const checkDisabled = (items) => {
(items || main.querySelectorAll(".item")).forEach((v, i) => {
const arr = v.id
.substring(1)
.split("-")
.map((v) => Number(v));
const isPy = (arr[0] + 1) % 2 === 0;
for (let i = arr[0] + 1; i <= layerCount - 1; i++) {
const isPyB = (i + 1) % 2 === 0;
if (isPy === isPyB) {
const el = main.querySelector(`#m${i}-${arr[1]}-${arr[2]}`);
if (el) {
v.classList.add("disabled");
break;
}
} else if (isPy && !isPyB) {
if (
![
`${i}-${arr[1]}-${arr[2]}`,
`${i}-${arr[1]}-${arr[2] + 1}`,
`${i}-${arr[1] + 1}-${arr[2]}`,
`${i}-${arr[1] + 1}-${arr[2] + 1}`,
].every((k) => {
return !main.querySelector("#m" + k);
})
) {
v.classList.add("disabled");
break;
} else {
v.classList.remove("disabled");
}
} else if (!isPy && isPyB) {
if (
![
`${i}-${arr[1]}-${arr[2]}`,
`${i}-${arr[1]}-${arr[2] - 1}`,
`${i}-${arr[1] - 1}-${arr[2]}`,
`${i}-${arr[1] - 1}-${arr[2] - 1}`,
].every((k) => {
return !main.querySelector("#m" + k);
})
) {
v.classList.add("disabled");
break;
} else {
v.classList.remove("disabled");
}
}
}
});
};
// 第三步:點(diǎn)擊卡片進(jìn)行消除計(jì)算
let canMove = true;
// 點(diǎn)擊棋子,動(dòng)畫移動(dòng)
const move = (me) => {
let left = moveList.offsetLeft;
let top = moveList.offsetTop;
if (!canMove || me.className.indexOf("disabled") >= 0) {
return;
}
canMove = false;
if (moveList.children.length > 0) {
let el = moveList.children[moveList.children.length - 1];
left = el.offsetLeft + size;
top = el.offsetTop;
}
me.style.top = `${top}px`;
me.style.left = `${left}px`;
me.transitionNamesCount = 0;
me.ontransitionend = (e) => {
me.transitionNamesCount++;
if (me.transitionNamesCount === 2) {
moveEnd(me);
canMove = true;
}
};
};
// 動(dòng)畫結(jié)束的相關(guān)計(jì)算
const moveEnd = (me) => {
me.ontransitionend = null;
me.setAttribute("onclick", "");
moveList.appendChild(me);
const findResult = [...moveList.children].filter((v) => v.innerHTML === me.innerHTML);
if (findResult.length === 3) {
findResult.forEach((v) => {
v.ontransitionend = (e) => {
moveList.removeChild(v);
[...moveList.children].forEach((v, i) => {
v.style.left = `${i * size + moveList.offsetLeft}px`;
});
};
setTimeout(() => (v.style.transform = "scale(0)"));
});
}
if (moveList.children.length === 6) {
return alert("池子已滿,游戲結(jié)束");
} else if (main.children.length === 0) {
return alert("恭喜通關(guān)");
}
checkDisabled();
};
checkDisabled();
</script>
</html>
?? 扣扣樂
<canvas id="cvs" width="605" height="338"></canvas>
<style>
canvas {
background: url(./images/zj.png) no-repeat center center;
background-size: 100%;
}
</style>
<script>
const cvs = document.getElementById('cvs')
const ctx = cvs.getContext('2d')
const url = './images/zj-bg.jpeg'
const img = new Image()
img.src = url
img.onload = () => {
ctx.drawImage(img, 0, 0, cvs.width, cvs.height)
}
let isClearing = false
cvs.addEventListener('mousedown', e => {
isClearing = true
})
cvs.addEventListener('mousemove', e => {
if (isClearing) {
const clearSize = 60
ctx.clearRect(e.pageX - clearSize, e.pageY - clearSize,
clearSize, clearSize)
}
})
document.addEventListener('mouseup', e => {
isClearing = false
})
</script>
???簽名回溯
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>HTML5 繪圖</title>
<style>
.canvas {
border: 1px solid #ccc;
cursor: crosshair;
}
</style>
</head>
<body>
<input type="button" value="重放" id="btn1" />
<input type="button" value="清空" id="btn2" />
<input type="button" value="保存" id="btn3" />
<br />
<canvas id="cvs" class="canvas"></canvas>
</body>
</html>
<script>
class Draw {
constructor(selector, width, height) {
this.element = document.querySelector(selector);
this.canvas = this.element.getContext("2d");
this.element.width = width;
this.element.height = height;
this.timeId = null;
this.animateArr = [];
}
init() {
const { canvas: c, element: el } = this;
let isDrag = false;
c.lineWidth = 2;
c.lineJoin = "round";
c.shadowColor = "#000";
c.shadowBlur = 4;
el.onmousedown = () => {
isDrag = true;
c.beginPath();
};
el.onmousemove = (e) => {
if (isDrag) {
const x = e.pageX - el.offsetLeft;
const y = e.pageY - el.offsetTop;
c.lineTo(x, y);
c.stroke();
this.animateArr.push([x, y]);
}
};
el.onmouseup = () => {
isDrag = false;
this.animateArr.push(-1);
};
el.onmouseout = () => {
el.onmouseup();
};
}
animateGo() {
const { canvas: c } = this;
this.clear();
c.beginPath();
const loop = (animate, i) => {
if (i < animate.length - 1) {
const arr = animate[i];
if (arr === -1) {
c.beginPath();
} else {
c.lineTo(arr[0], arr[1]);
c.stroke();
}
i++;
this.timeId = setTimeout(() => {
loop(animate, i);
}, 10);
}
};
loop(this.animateArr, 0);
}
clear() {
const { canvas: c } = this;
const { width, height } = this.element;
c.clearRect(0, 0, width, height);
}
}
const g = new Draw("#cvs", 600, 500);
g.init();
document.getElementById("btn1").onclick = () => {
g.animateGo();
};
document.getElementById("btn2").onclick = () => {
g.clear();
g.animateArr = [];
};
document.getElementById("btn3").onclick = () => {
const canvas = document.querySelector("#cvs");
const dataURL = canvas.toDataURL();
// 將dataURL發(fā)送到服務(wù)器進(jìn)行保存操作
console.log(dataURL);
};
</script>
?? 翻盤抽獎(jiǎng)
?畫面 挺多、不一一展示了,快來一鍵三連抱走吧
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>9宮格翻牌抽獎(jiǎng)</title>
<style>
.title {
text-align: center;
}
.box {
display: flex;
flex-wrap: wrap;
justify-content: center;
width: 330px;
margin:0 auto;
}
.item {
position: relative;
margin: 5px;
width: 100px;
height: 100px;
}
.style1, .style2 {
position: absolute;
left:0;
top: 0;
bottom: 0;
right: 0;
display: flex;
justify-content: center;
align-items: center;
border-radius: 5px;
text-align: center;
transition: transform .4s
}
.style1 {
background-color: #ff8800;
color: #fff;
}
.style2 {
color: #ff8800;
border:1px solid #ff8800;
padding: 0 10px;
transform: scaleX(0);
background-color: #ffe6c9;
}
.hide {
transform: scaleX(0);
}
.show {
transform: scaleX(1);
}
.show-result {
transform: scaleX(1);
opacity: 0.5;
}
</style>
</head>
<style>
</style>
<body>
<div class="title">可抽獎(jiǎng)<label id="count">0</label>次</div>
<div class="box"></div>
</body>
<script>
// 獎(jiǎng)品列表
const list = [
{id: 1, name: '1元優(yōu)惠券', is: true},
{id: 2, name: '10元優(yōu)惠券', is: true},
{id: 3, name: '謝謝惠顧', is: true},
{id: 4, name: '豪華電動(dòng)車'},
{id: 5, name: '1w購物券'},
{id: 6, name: '5w購物券'},
{id: 7, name: '豪華轎車'},
{id: 8, name: '房子一套'},
{id: 9, name: '頂配筆記本'}
].sort(v => Math.random() - 0.5)
// 中獎(jiǎng)項(xiàng)
const isArr = list.filter(v => v.is)
// 非中獎(jiǎng)項(xiàng)
const noArr = list.filter(v => !v.is)
// 抽獎(jiǎng)次數(shù)
let count = 3
const box = document.querySelector('.box')
const countEL = document.querySelector('#count')
countEL.innerHTML = count
box.innerHTML = list.map(v => {
return `<div class="item" onclick="fp(this)">
<div class="style1">抽獎(jiǎng)</div>
<div class="style2"></div>
</div>`
}).join('')
// 翻牌抽獎(jiǎng)
const fp = (me) => {
if (count === 0) {
return
}
me.querySelector('.style1').classList.add('hide')
// 抽獎(jiǎng)動(dòng)畫
setTimeout(() => {
// 從非中獎(jiǎng)項(xiàng)中取最后一個(gè),并從數(shù)組中移除該項(xiàng)
const item = isArr.pop()
const style2 = me.querySelector('.style2')
style2.innerHTML = item.name
style2.classList.add('show')
}, 400)
count--
countEL.innerHTML = count
// 當(dāng)抽獎(jiǎng)次數(shù)為0的時(shí)候,就把剩余的獎(jiǎng)項(xiàng)全部展示出來
if (count === 0) {
setTimeout(() => {
box.querySelectorAll('.style1').forEach(v => {
v.classList.add('hide')
if (v.nextElementSibling.className.indexOf('show') === -1) {
const item = noArr.pop()
v.nextElementSibling.innerHTML = item.name
}
})
setTimeout(() => {
box.querySelectorAll('.style2').forEach(v => {
if (v.className.indexOf('show') === -1) {
v.classList.add('show-result')
}
})
}, 400)
}, 1000)
}
}
</script>
</html>
?? 地址 ???????
??
?????? 謝謝觀看
文章來源:http://www.zghlxwxcb.cn/news/detail-575861.html
?_______________________________??期待再見??_______________________________?文章來源地址http://www.zghlxwxcb.cn/news/detail-575861.html
到了這里,關(guān)于前端:UI 交互式特效 —— Css、Js的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!