实现原理:通过遍历 getImageData 函数返回的元素逐像素获取原始画布每个点的rgba值,然后每一帧通过运动函数对每个点的位置进行偏移,对比原画布,获取该点在原位置的rgba值,然后直接对a分量进行修改,修改的依据仍然是斜率。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>T.R.E. 飘扬旗帜</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
* {
margin: 0;
padding: 0;
}
html,
body {
width: 100%;
height: 100%;
}
#canvas {
position: absolute;
top: 50%;
left: 50%;
transform-origin: center;
transform: translate3d(-50%, -50%, 0);
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
var IMG_MAX_WIDTH = 600
var IMG_MAX_HEIGHT = 600
var imgWidth, imgHeight
var image = new Image()
image.src = 'tre.jpg'
var amplitude = 25 // 振幅
var period = 1.5 // 周期数
var frequency = 1 // 频率
var wavelength // 波长
var v // 波速
var cftX // x系数
var cftA // 振幅系数
image.onload = function(ev) {
imgWidth = Math.floor(image.width)
imgHeight = Math.floor(image.height)
var canvas = document.getElementById('canvas')
var scale = 1
if (imgWidth > IMG_MAX_WIDTH) {
scale = IMG_MAX_WIDTH / imgWidth
}
if (imgHeight > IMG_MAX_HEIGHT) {
scale = scale * IMG_MAX_HEIGHT / imgHeight
}
canvasWidth = imgWidth
canvasHeight = imgHeight + amplitude * 2
canvas.width = canvasWidth
canvas.height = canvasHeight
wavelength = imgWidth / period
cftX = 2 * Math.PI / wavelength
cftA = amplitude / imgWidth
v = wavelength * frequency
tick()
}
var fps = 60 // 每秒帧数
var interval = 1000 / fps // 连续帧之间间隔(理论)
var stop = false // 停止动画
var timeNow = Date.now() // 当前时间
var timeLast = timeNow // 上一帧时间
var delta = 0 // 连续帧之间间隔(实际)
var y = 0
var lastY = 0
var distance = 0
var tick = function() {
if (stop) return false
timeNow = Date.now()
delta = timeNow - timeLast
if (delta > interval) {
timeLast = timeNow
distance += (delta / 1000 * v)
ctx.clearRect(0, 0, canvasWidth, canvasHeight)
for (var x = 0; x < imgWidth; x++) {
y = cftA * x * Math.sin(cftX * (x - distance)) + amplitude
ctx.drawImage(image, x, 0, 1, imgHeight, x, y, 1, imgHeight)
ctx.fillStyle = 'rgba(255,255,255,' + (x === 0 ? 0 : (y - lastY) * 0.5) + ')'
ctx.fillRect(x, y, 1, imgHeight)
lastY = y
}
}
requestAnimationFrame(tick)
}
</script>
</body>
</html>
本文链接地址: T.R.E. 飘动旗帜