拉帘效果是基于胡克定律与阻尼的canvas物理动画:用变量w控制矩形宽度,按v += (targetw−w)×k − v×d、w += v逐帧更新;canvas固定定位、全屏适配;支持拖拽映射targetw及松手回弹;辅以半透色、微颤偏移和边缘渐变增强表现。

用 Canvas 实现“拉帘效果”本身不是传统意义上的窗帘开合,而是指一种**带物理感的弹性展开/收拢动画**——比如页面区域像被手拉开一样延展、松手后按弹簧规律回弹衰减。这种效果不能靠 CSS `transform: scaleX()` 配 `cubic-bezier` 模拟,必须引入真实物理模型(胡克定律 + 阻尼),由 Canvas 驱动逐帧计算。
核心思路:把“帘子”建模为可拉伸的物理对象
不渲染两块布料纹理,而是将“帘子”抽象为一个沿水平方向伸缩的矩形区域,其宽度由一个受控变量 w 决定;该变量的演化遵循阻尼弹簧方程:
v += (targetW − w) × k − v × d
w += v
其中 k 是劲度系数(决定回弹快慢),d 是阻尼系数(0.85–0.97 之间较自然),v 是当前伸缩速度。
Canvas 层级与定位关键
要让拉帘效果不干扰内容,需严格分层:
- 用
<canvas id="curtain"></canvas>单独承载帘子动画,CSS 设为position: fixed; top: 0; left: 0; z-index: 10; - 确保
canvas.width和canvas.height通过 JS 动态设为window.innerWidth与window.innerHeight,避免 CSS 缩放导致模糊 - 绘制时只清空本 canvas 区域(
ctx.clearRect(0, 0, width, height)),不覆盖下方内容层 - 帘子矩形默认从左向右展开,起始 x=0,宽度 w,高度铺满全屏(或指定区域高度)
交互逻辑:拖拽 → 拉伸 → 松手 → 弹性归位
监听鼠标/触屏事件,将用户横向拖动距离映射为临时目标宽度:
-
mousedown/touchstart:记录初始 x 坐标,启用拖拽状态
isDragging = true -
mousemove/touchmove:计算横向偏移
deltaX = currentX − startX,设targetW = baseWidth + deltaX(限制 min/max 防止过拉) -
mouseup/touchend:冻结
targetW为当前值,isDragging = false,后续仅靠物理公式自动收敛
渲染优化与视觉增强
单纯画个色块太单调,加一点科技感提升体验:
- 用
ctx.fillStyle = 'rgba(0, 0, 0, 0.7)'绘制半透黑帘,保留背景可见性 - 添加轻微垂直扰动:在绘制矩形前,对 y 坐标加一个随时间变化的小正弦偏移(
yOffset = Math.sin(Date.now() * 0.002) * 3),模拟布料微颤 - 边缘做线性渐变遮罩:用
ctx.createLinearGradient(x, 0, x + w, 0)让右侧边缘柔和过渡,避免硬切 - 移动端注意 touch 事件需加
{ passive: false }并调用e.preventDefault()防止页面滚动干扰
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











