难逃之阵
<style>#papa { left: -342px; width: 1280px; background: #000 url('https://638183.freep.cn/638183/Pic/81/ntzz.jpg') no-repeat center/cover; height: 780px; position: relative; z-index: 999; }
#canvas { background: #000; opacity: .75; }
#disc { position: absolute; width: 40px; height: 40px; left: 10px; top: 10px; background: conic-gradient(red,orange,yellow,green,teal,blue,purple); mask: radial-gradient(transparent 4px,red 0); -webkit-mask: radial-gradient(transparent 4px,red 0); border-radius: 50%; cursor: pointer; z-index: 10; animation: rot 2s linear infinite; }
#lrcbox { position: absolute; left: 60px; top: 10px;font: bold 22px / 40px sans-serif; color: lightblue; text-shadow: 2px 2px 4px #222; }
@keyframes rot { to { transform: rotate(360deg); } }
</style>
<div id="papa">
<span id="disc"></span>
<span id="lrcbox">难逃之阵</span>
<canvas id="canvas"></canvas>
</div>
<script>
let aud = new Audio();
aud.src = 'https://music.163.com/song/media/outer/url?id=1879108767.mp3';
aud.loop = true;
aud.autoplay = true;
disc.style.animationPlayState = aud.paused ? 'paused' : 'running';
disc.onclick = () => aud.paused ? aud.play() : aud.pause();
aud.addEventListener('playing', () => disc.style.animationPlayState = 'running');
aud.addEventListener('pause', () => disc.style.animationPlayState = 'paused');
window.requestAnimFrame = (function() {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback);
}
);
});
function init(elemid) {
let canvas = document.getElementById(elemid),
c = canvas.getContext("2d"),
w = canvas.width = papa.offsetWidth,
h = canvas.height = papa.offsetHeight;
c.fillStyle = "rgba(30,30,30,1)";
c.fillRect(0, 0, w, h);
return {c:c,canvas:canvas};
}
window.onload = function() {
let c = init("canvas").c,
canvas = init("canvas").canvas,
w = canvas.width = papa.offsetWidth,
h = canvas.height = papa.offsetHeight;
mouse = { x: false, y: false },
last_mouse = {};
function dist(p1x, p1y, p2x, p2y) {
return Math.sqrt(Math.pow(p2x - p1x, 2) + Math.pow(p2y - p1y, 2));
}
class segment {
constructor(parent, l, a, first) {
this.first = first;
if (first) {
this.pos = {
x: parent.x,
y: parent.y
};
} else {
this.pos = {
x: parent.nextPos.x,
y: parent.nextPos.y
};
}
this.l = l;
this.ang = a;
this.nextPos = {
x: this.pos.x + this.l * Math.cos(this.ang),
y: this.pos.y + this.l * Math.sin(this.ang)
};
}
update(t) {
this.ang = Math.atan2(t.y - this.pos.y, t.x - this.pos.x);
this.pos.x = t.x + this.l * Math.cos(this.ang - Math.PI);
this.pos.y = t.y + this.l * Math.sin(this.ang - Math.PI);
this.nextPos.x = this.pos.x + this.l * Math.cos(this.ang);
this.nextPos.y = this.pos.y + this.l * Math.sin(this.ang);
}
fallback(t) {
this.pos.x = t.x;
this.pos.y = t.y;
this.nextPos.x = this.pos.x + this.l * Math.cos(this.ang);
this.nextPos.y = this.pos.y + this.l * Math.sin(this.ang);
}
show() {
c.lineTo(this.nextPos.x, this.nextPos.y);
}
}
class tentacle {
constructor(x, y, l, n, a) {
this.x = x;
this.y = y;
this.l = l;
this.n = n;
this.t = {};
this.rand = Math.random();
this.segments = ;
for (let i = 1; i < this.n; i++) {
this.segments.push(
new segment(this.segments, this.l / this.n, 0, false)
);
}
}
move(last_target, target) {
this.angle = Math.atan2(target.y-this.y,target.x-this.x);
this.dt = dist(last_target.x, last_target.y, target.x, target.y)+5;
this.t = {
x: target.x - 0.8*this.dt*Math.cos(this.angle),
y: target.y - 0.8*this.dt*Math.sin(this.angle)
};
if(this.t.x){
this.segments.update(this.t);
}else{
this.segments.update(target);
}
for (let i = this.n - 2; i >= 0; i--) {
this.segments.update(this.segments.pos);
}
if (
dist(this.x, this.y, target.x, target.y) <=
this.l + dist(last_target.x, last_target.y, target.x, target.y)
) {
this.segments.fallback({ x: this.x, y: this.y });
for (let i = 1; i < this.n; i++) {
this.segments.fallback(this.segments.nextPos);
}
}
}
show(target) {
if (dist(this.x, this.y, target.x, target.y) <= this.l) {
c.globalCompositeOperation = "color-dodge";
c.beginPath();
c.lineTo(this.x, this.y);
for (let i = 0; i < this.n; i++) {
this.segments.show();
}
c.strokeStyle = "hsl("+(this.rand*60+180)+",100%," + (this.rand * 60 + 25) + "%)";
c.lineWidth = this.rand * 2;
c.lineCap="round";
c.lineJoin="round";
c.stroke();
c.globalCompositeOperation = "source-over";
}
}
show2(target) {
c.beginPath();
if (dist(this.x, this.y, target.x, target.y) <= this.l) {
c.arc(this.x, this.y, 2*this.rand+1, 0, 2 * Math.PI);
c.fillStyle = "white";
} else {
c.arc(this.x, this.y, this.rand*2, 0, 2 * Math.PI);
c.fillStyle = "darkcyan";
}
c.fill();
}
}
let maxl = 300,
minl = 50,
n = 30,
numt = 500,
tent = [],
clicked = false,
target = { x: 0, y: 0 },
last_target = {},
t = 0,
q = 10;
for (let i = 0; i < numt; i++) {
tent.push(
new tentacle(
Math.random() * w,
Math.random() * h,
Math.random() * (maxl - minl) + minl,
n,
Math.random() * 2 * Math.PI
)
);
}
function draw() {
if (mouse.x) {
target.errx = mouse.x - target.x;
target.erry = mouse.y - target.y;
} else {
target.errx =
w / 2 +
(h / 2 - q) *
Math.sqrt(2) *
Math.cos(t) /
(Math.pow(Math.sin(t), 2) + 1) -
target.x;
target.erry =
h / 2 +
(h / 2 - q) *
Math.sqrt(2) *
Math.cos(t) *
Math.sin(t) /
(Math.pow(Math.sin(t), 2) + 1) -
target.y;
}
target.x += target.errx / 10;
target.y += target.erry / 10;
t += 0.01;
c.beginPath();
c.arc(target.x, target.y, dist(last_target.x, last_target.y, target.x, target.y)+5, 0, 2 * Math.PI);
c.fillStyle = "hsl(210,100%,80%)";
c.fill();
for (i = 0; i < numt; i++) {
tent.move(last_target, target);
tent.show2(target);
}
for (i = 0; i < numt; i++) {
tent.show(target);
}
last_target.x = target.x;
last_target.y = target.y;
}
canvas.addEventListener(
"mousemove",
function(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.offsetX;
mouse.y = e.offsetY;
},
false
);
canvas.addEventListener("mouseleave", function(e) {
mouse.x = false;
mouse.y = false;
});
canvas.addEventListener(
"mousedown",
function(e) {
clicked = true;
},
false
);
canvas.addEventListener(
"mouseup",
function(e) {
clicked = false;
},
false
);
function loop() {
window.requestAnimFrame(loop);
c.clearRect(0, 0, w, h);
draw();
}
loop();
setInterval(loop, 1000 / 60);
}
</script>
代码分享(全):
<style>
#papa { left: -342px; width: 1280px; background: #000 url('https://638183.freep.cn/638183/Pic/81/ntzz.jpg') no-repeat center/cover; height: 780px; position: relative; z-index: 999; }
#canvas { background: #000; opacity: .75; }
#disc { position: absolute; width: 40px; height: 40px; left: 10px; top: 10px; background: conic-gradient(red,orange,yellow,green,teal,blue,purple); mask: radial-gradient(transparent 4px,red 0); -webkit-mask: radial-gradient(transparent 4px,red 0); border-radius: 50%; cursor: pointer; z-index: 10; animation: rot 2s linear infinite; }
#lrcbox { position: absolute; left: 60px; top: 10px;font: bold 22px / 40px sans-serif; color: lightblue; text-shadow: 2px 2px 4px #222; }
@keyframes rot { to { transform: rotate(360deg); } }
</style>
<div id="papa">
<span id="disc"></span>
<span id="lrcbox">难逃之阵</span>
<canvas id="canvas"></canvas>
</div>
<script>
let aud = new Audio();
aud.src = 'https://music.163.com/song/media/outer/url?id=1879108767.mp3';
aud.loop = true;
aud.autoplay = true;
disc.style.animationPlayState = aud.paused ? 'paused' : 'running';
disc.onclick = () => aud.paused ? aud.play() : aud.pause();
aud.addEventListener('playing', () => disc.style.animationPlayState = 'running');
aud.addEventListener('pause', () => disc.style.animationPlayState = 'paused');
window.requestAnimFrame = (function() {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback);
}
);
});
function init(elemid) {
let canvas = document.getElementById(elemid),
c = canvas.getContext("2d"),
w = canvas.width = papa.offsetWidth,
h = canvas.height = papa.offsetHeight;
c.fillStyle = "rgba(30,30,30,1)";
c.fillRect(0, 0, w, h);
return {c:c,canvas:canvas};
}
window.onload = function() {
let c = init("canvas").c,
canvas = init("canvas").canvas,
w = canvas.width = papa.offsetWidth,
h = canvas.height = papa.offsetHeight;
mouse = { x: false, y: false },
last_mouse = {};
function dist(p1x, p1y, p2x, p2y) {
return Math.sqrt(Math.pow(p2x - p1x, 2) + Math.pow(p2y - p1y, 2));
}
class segment {
constructor(parent, l, a, first) {
this.first = first;
if (first) {
this.pos = {
x: parent.x,
y: parent.y
};
} else {
this.pos = {
x: parent.nextPos.x,
y: parent.nextPos.y
};
}
this.l = l;
this.ang = a;
this.nextPos = {
x: this.pos.x + this.l * Math.cos(this.ang),
y: this.pos.y + this.l * Math.sin(this.ang)
};
}
update(t) {
this.ang = Math.atan2(t.y - this.pos.y, t.x - this.pos.x);
this.pos.x = t.x + this.l * Math.cos(this.ang - Math.PI);
this.pos.y = t.y + this.l * Math.sin(this.ang - Math.PI);
this.nextPos.x = this.pos.x + this.l * Math.cos(this.ang);
this.nextPos.y = this.pos.y + this.l * Math.sin(this.ang);
}
fallback(t) {
this.pos.x = t.x;
this.pos.y = t.y;
this.nextPos.x = this.pos.x + this.l * Math.cos(this.ang);
this.nextPos.y = this.pos.y + this.l * Math.sin(this.ang);
}
show() {
c.lineTo(this.nextPos.x, this.nextPos.y);
}
}
class tentacle {
constructor(x, y, l, n, a) {
this.x = x;
this.y = y;
this.l = l;
this.n = n;
this.t = {};
this.rand = Math.random();
this.segments = ;
for (let i = 1; i < this.n; i++) {
this.segments.push(
new segment(this.segments, this.l / this.n, 0, false)
);
}
}
move(last_target, target) {
this.angle = Math.atan2(target.y-this.y,target.x-this.x);
this.dt = dist(last_target.x, last_target.y, target.x, target.y)+5;
this.t = {
x: target.x - 0.8*this.dt*Math.cos(this.angle),
y: target.y - 0.8*this.dt*Math.sin(this.angle)
};
if(this.t.x){
this.segments.update(this.t);
}else{
this.segments.update(target);
}
for (let i = this.n - 2; i >= 0; i--) {
this.segments.update(this.segments.pos);
}
if (
dist(this.x, this.y, target.x, target.y) <=
this.l + dist(last_target.x, last_target.y, target.x, target.y)
) {
this.segments.fallback({ x: this.x, y: this.y });
for (let i = 1; i < this.n; i++) {
this.segments.fallback(this.segments.nextPos);
}
}
}
show(target) {
if (dist(this.x, this.y, target.x, target.y) <= this.l) {
c.globalCompositeOperation = "color-dodge";
c.beginPath();
c.lineTo(this.x, this.y);
for (let i = 0; i < this.n; i++) {
this.segments.show();
}
c.strokeStyle = "hsl("+(this.rand*60+180)+",100%," + (this.rand * 60 + 25) + "%)";
c.lineWidth = this.rand * 2;
c.lineCap="round";
c.lineJoin="round";
c.stroke();
c.globalCompositeOperation = "source-over";
}
}
show2(target) {
c.beginPath();
if (dist(this.x, this.y, target.x, target.y) <= this.l) {
c.arc(this.x, this.y, 2*this.rand+1, 0, 2 * Math.PI);
c.fillStyle = "white";
} else {
c.arc(this.x, this.y, this.rand*2, 0, 2 * Math.PI);
c.fillStyle = "darkcyan";
}
c.fill();
}
}
let maxl = 300,
minl = 50,
n = 30,
numt = 500,
tent = [],
clicked = false,
target = { x: 0, y: 0 },
last_target = {},
t = 0,
q = 10;
for (let i = 0; i < numt; i++) {
tent.push(
new tentacle(
Math.random() * w,
Math.random() * h,
Math.random() * (maxl - minl) + minl,
n,
Math.random() * 2 * Math.PI
)
);
}
function draw() {
if (mouse.x) {
target.errx = mouse.x - target.x;
target.erry = mouse.y - target.y;
} else {
target.errx =
w / 2 +
(h / 2 - q) *
Math.sqrt(2) *
Math.cos(t) /
(Math.pow(Math.sin(t), 2) + 1) -
target.x;
target.erry =
h / 2 +
(h / 2 - q) *
Math.sqrt(2) *
Math.cos(t) *
Math.sin(t) /
(Math.pow(Math.sin(t), 2) + 1) -
target.y;
}
target.x += target.errx / 10;
target.y += target.erry / 10;
t += 0.01;
c.beginPath();
c.arc(target.x, target.y, dist(last_target.x, last_target.y, target.x, target.y)+5, 0, 2 * Math.PI);
c.fillStyle = "hsl(210,100%,80%)";
c.fill();
for (i = 0; i < numt; i++) {
tent.move(last_target, target);
tent.show2(target);
}
for (i = 0; i < numt; i++) {
tent.show(target);
}
last_target.x = target.x;
last_target.y = target.y;
}
canvas.addEventListener(
"mousemove",
function(e) {
last_mouse.x = mouse.x;
last_mouse.y = mouse.y;
mouse.x = e.offsetX;
mouse.y = e.offsetY;
},
false
);
canvas.addEventListener("mouseleave", function(e) {
mouse.x = false;
mouse.y = false;
});
canvas.addEventListener(
"mousedown",
function(e) {
clicked = true;
},
false
);
canvas.addEventListener(
"mouseup",
function(e) {
clicked = false;
},
false
);
function loop() {
window.requestAnimFrame(loop);
c.clearRect(0, 0, w, h);
draw();
}
loop();
setInterval(loop, 1000 / 60);
}
</script>
特别说明:画布动画非原创,改装自开源代码 这个动画做全屏的效果最好。论坛上可以进一步放大,不过会很夸张,所以使用现在这个尺寸 电子乌贼对帖子区域内的鼠标指针移动极度敏感,不妨把玩把玩、体会一下 我来学习制作试一下。 手机上看不全,也无法评分。 挺好玩的,跟到鼠标跑。 这样的制作太精妙了,满天繁星任我摆布,再配上这天籁之音,似乎这璀璨的群星都是我的啦。妙,妙,妙! 这是啥怪物,修行到天阶几层哪,能在空间任一瞬移,了不起了不起{:4_203:} 只有转圈圈它才追不上{:4_173:} 马黑黑 发表于 2022-8-19 07:58
电子乌贼对帖子区域内的鼠标指针移动极度敏感,不妨把玩把玩、体会一下
鼠标不移动上去时,它就自己慢悠悠地走,鼠标过去,它立即变大并跟过来,像要吞了鼠标似的{:4_173:} 这个效果太神奇了。原来叫电子乌贼,还以为是外太空的怪物,用它的触角在宇宙的各个角落探索逡巡{:4_173:} 这么多触角像水一样流动,这个动画的动作好美,有种柔软的感觉{:4_187:} 加林森 发表于 2022-8-19 09:04
手机上看不全,也无法评分。
这个偏大了,一般也不会去考虑小屏幕了 红影 发表于 2022-8-19 11:57
这么多触角像水一样流动,这个动画的动作好美,有种柔软的感觉
八爪鱼一样的软体{:5_106:} 加林森 发表于 2022-8-19 08:53
我来学习制作试一下。
要得要得 红影 发表于 2022-8-19 11:55
这个效果太神奇了。原来叫电子乌贼,还以为是外太空的怪物,用它的触角在宇宙的各个角落探索逡巡
你这个理解是合理的。我说的电子乌贼是临时起名的。 加林森 发表于 2022-8-19 09:09
挺好玩的,跟到鼠标跑。
对。鼠标指针不在帖子里的话,它就自由活动。但它永远逃不出太空牢笼。 红影 发表于 2022-8-19 11:54
鼠标不移动上去时,它就自己慢悠悠地走,鼠标过去,它立即变大并跟过来,像要吞了鼠标似的
饿呗{:5_106:}