Toggle navigation
在线编辑器
在线代码
文本比较
jQuery下载
前端库
在线手册
登录/注册
下载代码
html
css
js
分享到微信朋友圈
X
html
Hover me I am liquid
css
body { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: #eef; } .button { position: relative; padding: 1.6em 2.8em; text-decoration: none; } .button__canvas { --offset: 32px; position: absolute; top: calc(var(--offset) * -1); left: calc(var(--offset) * -1); width: calc(100% + var(--offset) * 2); height: calc(100% + var(--offset) * 2); transition: opacity 2s ease; } .button__text { position: relative; color: white; font-weight: bold; letter-spacing: 0.02em; pointer-events: none; } .button:hover .button__canvas { opacity: 0.85; transition: opacity 0.2s ease; } .button:active .button__canvas { opacity: 1; transition: none; }
JavaScript
(function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):(global=global||self,global.Ola=factory())})(this,function(){"use strict";const position=(x0,v0,t1,t)=>{const a=(v0*t1+2*x0)/t1**3;const b=-(2*v0*t1+3*x0)/t1**2;const c=v0;const d=x0;return a*t**3+b*t**2+c*t+d};const speed=(x0,v0,t1,t)=>{const a=(v0*t1+2*x0)/t1**3;const b=-(2*v0*t1+3*x0)/t1**2;const c=v0;return 3*a*t**2+2*b*t+c};const each=function(values,cb){const multi=typeof values==="number"?{value:values}:values;Object.entries(multi).map(([key,value])=>cb(value,key))};function Single(init,time){this.start=new Date/1e3;this.time=time;this.from=init;this.current=init;this.to=init;this.speed=0}Single.prototype.get=function(now){const t=now/1e3-this.start;if(t<0){throw new Error("Cannot read in the past")}if(t>=this.time){return this.to}return this.to-position(this.to-this.from,this.speed,this.time,t)};Single.prototype.getSpeed=function(now){const t=now/1e3-this.start;if(t>=this.time){return 0}return speed(this.to-this.from,this.speed,this.time,t)};Single.prototype.set=function(value,time){const now=new Date;const current=this.get(now);this.speed=this.getSpeed(now);this.start=now/1e3;this.from=current;this.to=value;if(time){this.time=time}return current};function Ola(values,time=300){if(typeof values==="number"){values={value:values}}each(values,(init,key)=>{const value=new Single(init,time/1e3);Object.defineProperty(values,"_"+key,{value:value});Object.defineProperty(values,"$"+key,{get:()=>value.to});Object.defineProperty(values,key,{get:()=>value.get(new Date),set:val=>value.set(val),enumerable:true})});Object.defineProperty(values,"get",{get:()=>(function(name="value",now=new Date){return this["_"+name].get(now)})});Object.defineProperty(values,"set",{get:()=>(function(values,time=0){each(values,(value,key)=>{this["_"+key].set(value,time/1e3)})})});return values}return Ola}); document.querySelectorAll('.button').forEach((elem) => { const canvas = elem.querySelector('.button__canvas') const ctx = canvas.getContext('2d') const offset = 32 const background = '#eef' const foreground = '#7551e9' let points = [] let position const distance = new Ola({ value: offset }) const size = () => { canvas.width = canvas.getBoundingClientRect().width canvas.height = canvas.getBoundingClientRect().height position = new Ola({ x: canvas.width / 2, y: canvas.height / 2 }) const pixelsWidth = canvas.width - offset * 2 const pixelsHeight = canvas.height - offset * 2 const leftTop = [ offset, offset ] const rightTop = [ canvas.width - offset, offset ] const rightBottom = [ canvas.width - offset, canvas.height - offset ] const leftBottom = [ offset, canvas.height - offset ] points = [] Array(pixelsWidth).fill().forEach((_, index) => { points.push([ leftTop[0] + index, leftTop[1] ]) }) Array(pixelsHeight).fill().forEach((_, index) => { points.push([ rightTop[0], rightTop[1] + index ]) }) Array(pixelsWidth).fill().forEach((_, index) => { points.push([ rightBottom[0] - index, rightBottom[1] ]) }) Array(pixelsHeight).fill().forEach((_, index) => { points.push([ leftBottom[0], leftBottom[1] - index ]) }) } size() const reset = () => { ctx.fillStyle = background ctx.fillRect(0, 0, canvas.width, canvas.height) } const draw = () => { ctx.fillStyle = foreground ctx.beginPath() points.forEach((point, index) => { const [ vx, vy ] = attract(point) if (index === 0) ctx.moveTo(vx, vy) else ctx.lineTo(vx, vy) }) ctx.closePath() ctx.fill() } const attract = (point) => { const [ x, y ] = point const dx = x - position.x const dy = y - position.y const dist = Math.sqrt(dx * dx + dy * dy) const dist2 = Math.max(1, dist) const d = Math.min(dist2, Math.max(12, (dist2 / 4) - dist2)) const D = dist2 * distance.value return [ x + (d / D) * (position.x - x), y + (d / D) * (position.y - y) ] } const loop = () => { reset() draw() requestAnimationFrame(loop) } window.onresize = size canvas.onmousemove = (e) => { position.set({ x: e.clientX - e.target.getBoundingClientRect().left, y: e.clientY - e.target.getBoundingClientRect().top }, 200) } canvas.onmouseenter = () => { distance.set({ value: 1 }, 200) } canvas.onmouseleave = () => { position.set({ x: canvas.width / 2, y: canvas.height / 2 }, 2000) distance.set({ value: offset }, 12000) } loop() })
粒子
时间
文字
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号