Toggle navigation
在线编辑器
在线代码
文本比较
jQuery下载
前端库
在线手册
登录/注册
下载代码
html
css
js
分享到微信朋友圈
X
html
css
html, body { overflow: hidden; background: black; }
JavaScript
const hueBase = 60 const hueRange = 160 const segmentCount = 60 const bubbleCount = 500 const segmentLengthBase = 5 const fadeIn = (t, m) => t / m const fadeOut = (t, m) => (m - t) / m const fadeInOut = (t, m) => { let hm = 0.5 * m return abs((t + hm) % m - hm) / hm } const angle = (x1, y1, x2, y2) => atan2(y2 - y1, x2 - x1) let buffer let canvas let ctx let creature let bubbles let center let tick let simplex class AttributeArray { constructor(count, attrs) { this.count = count this.attrs = attrs this.spread = attrs.length this.values = new Float32Array(count * this.spread) } get length() { return this.values.length } set(a, i, normalize = false) { normalize && (i *= this.spread) this.values.set(a, i) } get(i, normalize = false) { normalize && (i *= this.spread) return this.values.slice(i, i + this.spread) } forEach(cb) { let i = 0 let j = 0 for (; i < this.length; i += this.spread, j++) { cb(this.get(i), j, this) } } map(cb) { let i = 0 let j = 0 for (; i < this.length; i += this.spread, j++) { this.set(cb(this.get(i), j, this), i) } } reverseMap(cb) { let i = this.length - this.spread let j = this.count - 1 for (; i >= 0; i -= this.spread, j--) { this.set(cb(this.get(i), j, this), i) } } } class Bubbles extends AttributeArray { constructor(count) { super(count, ['x', 'y', 'vx', 'vy', 's', 'd', 'h', 'l', 'ttl']) this.initPoints() this.repelTarget = null this.repelThreshold = 100 } setRepelTarget(target = null) { this.repelTarget = target } initPoints() { this.map(() => [ random(windowWidth), random(windowHeight), random(-2, 2), random(-4, -1), random(2, 6), random(2, 6), random(180, 240), random(0, 200), random(500, 1000) ]) } reset() { return [ random(windowWidth), random(windowHeight), 0, random(-4, -1), random(2, 6), random(2, 6), random(180, 240), 0, random(500, 1000) ] } drawParticle(x, y, d, h, l, ttl) { const ld = fadeInOut(l, ttl) buffer.stroke(h, 50, 100, 0.5 * ld) buffer.strokeWeight(1 + d * ld) buffer.point(x, y) } update() { this.map(([x, y, vx, vy, s, d, h, l, ttl]) => { const n = simplex.noise3D(x * 0.0015, y * 0.0015, tick * 0.0015) * TAU vx = lerp(vx, cos(n) * s, 0.15) vy = lerp(vy, (sin(n) + 2) * -s, 0.15) if ( this.repelTarget && dist(x, y, ...this.repelTarget) < this.repelThreshold ) { const theta = angle(x, y, ...this.repelTarget) vx = lerp(vx, vx - cos(theta) * s, 0.275) vy = lerp(vy, vy - sin(theta) * s, 0.275) } x = lerp(x, x + vx, 0.125) y = lerp(y, y + vy, 0.125) l++ this.drawParticle(x, y, d, h, l, ttl) if ( l > ttl || x > windowWidth + d || x < -d || y < -d ) { return this.reset() } return [x, y, vx, vy, s, d, h, l, ttl] }) } } class Segments extends AttributeArray { constructor(x, y, segmentNum, baseLength, baseDirection, additionalAttrs = []) { super(segmentNum, ['x1', 'y1', 'x2', 'y2', 'l', 'd', ...additionalAttrs]) this.position = [x, y] this.target = [x, y] this.baseLength = baseLength this.baseDirection = baseDirection } get segmentNum() { return this.count } setTarget(arg) { if (typeof arg === 'function') { this.target = arg(this.target) } else { this.target = arg } } setPosition(arg) { if (typeof arg === 'function') { this.position = arg(this.position) } else { this.position = arg } } mapSegments(cb, direction = 'forward') { if (direction === 'backward') { this.reverseMap(cb) } else { this.map(cb) } } updateSegments(cb, direction = 'forward') { let target = this.position this.mapSegments(([x1, y1, x2, y2, l, d, ..._rest], i) => { x1 = target[0] y1 = target[1] const [t, ...rest] = cb([x1, y1, x2, y2, l, d, ..._rest], i) x2 = x1 + l * (cos(t) || d) y2 = y1 + l * (sin(t) || d) target = [x2, y2] return [x1, y1, x2, y2, l, d, ...rest] }, direction) } } class Creature extends Segments { constructor() { super( center[0], center[1], segmentCount, segmentLengthBase, 0, ['h'] ) this.follow = false this.initSegments() } initSegments() { let x1, y1, x2, y2, l, d, h l = this.baseLength d = this.baseDirection this.mapSegments((_, i) => { x1 = x2 || this.position[0] y1 = y2 || this.position[1] x2 = x1 - l * cos(d) y2 = y1 - l * sin(d) d += 0.1 l *= 1.01 h = hueBase + fadeOut(i, this.segmentNum) * hueRange return [x1, y1, x2, y2, l, d, h] }) } updateTarget() { if (!this.follow) { const t = simplex.noise3D( this.target[0] * 0.005, this.target[1] * 0.005, tick * 0.005 ) * TAU this.setTarget([ lerp( this.target[0], this.target[0] + 20 * (cos(t) + cos(tick * 0.05)), 0.25 ), lerp( this.target[1], this.target[1] + 20 * (sin(t) + sin(tick * 0.05)), 0.25 ) ]) } if ( this.position[0] > windowWidth + 500 || this.position[0] < -500 || this.position[1] > windowHeight + 500 || this.position[1] < -500 ) { this.setTarget([...center]) } } update() { this.setPosition([ lerp(this.position[0], this.target[0], 0.015), lerp(this.position[1], this.target[1], 0.015) ]) this.updateTarget() this.updateSegments(([x1, y1, x2, y2, l, d, h], i) => { let n n = simplex.noise3D( x1 * 0.005, y1 * 0.005, (i + tick) * 0.005 ) d = angle(x1, y1, x2, y2) + (n * 0.075) this.drawSegment(x1, y1, x2, y2, h, n, d, i) return [d] }, 'backward') } drawSegment(x1, y1, x2, y2, h, n, tn, i) { const arcWidth = 6 + 30 * fadeIn(i, this.segmentNum) const lineLength = 1.35 * arcWidth const lineLeftX = x1 + lineLength * cos(tn + 0.85 + n) const lineLeftY = y1 + lineLength * sin(tn + 0.85 + n) const lineRightX = x1 + lineLength * cos(tn - 0.85 - n) const lineRightY = y1 + lineLength * sin(tn - 0.85 - n) const nubWidth = arcWidth * 0.35 buffer.strokeWeight(1 + fadeIn(i, this.segmentNum) * 4) buffer.stroke(h, 100, 100, 0.1) buffer.noFill() buffer.line( x1, y1, lineLeftX, lineLeftY ) buffer.ellipse(lineLeftX, lineLeftY, nubWidth) buffer.line( x1, y1, lineRightX, lineRightY ) buffer.ellipse(lineRightX, lineRightY, nubWidth) buffer.line(x2, y2, x1, y1) buffer.ellipse(x1, y1, arcWidth) } } function setup() { buffer = createGraphics(windowWidth, windowHeight) buffer.colorMode(HSB) canvas = createCanvas(windowWidth, windowHeight) canvas.mouseOver(mouseOver) canvas.mouseOut(mouseOut) ctx = canvas.canvas.getContext('2d') tick = 0 simplex = new SimplexNoise() center = [0.5 * windowWidth, 0.5 * windowHeight] creature = new Creature() bubbles = new Bubbles(bubbleCount) } function drawGlow() { ctx.save() ctx.filter = 'blur(6px) brightness(200%)' image(buffer, 0, 0) ctx.restore() } function drawImage() { ctx.save() ctx.globalCompositeOperation = 'lighter' image(buffer, 0, 0) ctx.restore() } function draw() { tick++ buffer.background(220, 70, 2) try { creature.update() bubbles.setRepelTarget(creature.position) bubbles.update() drawGlow() drawImage() } catch (e) { console.error(e) noLoop() } } function windowResized() { resizeCanvas(windowWidth, windowHeight) buffer.resizeCanvas(windowWidth, windowHeight) center = [0.5 * windowWidth, 0.5 * windowHeight] } function mouseMoved() { creature.setTarget([ mouseX, mouseY ]) } function mouseOut() { creature.follow = false } function mouseOver() { creature.follow = true }
粒子
时间
文字
hover
canvas
3d
游戏
音乐
火焰
水波
轮播图
鼠标跟随
动画
css
加载动画
导航
菜单
按钮
滑块
tab
弹出层
统计图
svg
×
Close
在线代码下载提示
开通在线代码永久免费下载,需支付20jQ币
开通后,在线代码模块中所有代码可终身免费下!
您已开通在线代码永久免费下载,关闭提示框后,点下载代码可直接下载!
您已经开通过在线代码永久免费下载
对不起,您的jQ币不足!可通过发布资源 或
直接充值获取jQ币
取消
开通下载
<!doctype html> <html> <head> <meta charset="utf-8"> <title>鼠标跟随-奇异生物-jq22.com</title> <script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script> <style>
</style> </head> <body>
<script>
</script>
</body> </html>
2012-2021 jQuery插件库版权所有
jquery插件
|
jq22工具库
|
网页技术
|
广告合作
|
在线反馈
|
版权声明
沪ICP备13043785号-1
浙公网安备 33041102000314号