canvas做静态图片波动
Posted 晚星@
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了canvas做静态图片波动相关的知识,希望对你有一定的参考价值。
用到的技术css, js,canvas, svg
第三方库TweenMax
本人对svg不是很会,也是找的相关的信息,这里提供一个好用的学习网站mdn
先来看看实现效果
说下实现这种效果的原理,首先在最下面有张图片,然后在图片上面创建了一个画布,这个画布可以自己手动去画,当然如果你没有此需求你可以设置成一张固定的图片(这里主要用的css是mask-image,不知道的小伙伴可以去搜下)他会把你画布中的你绘制的区域拿出来,然后咱代码下方有个svg是把这块区域弄完波纹,但是不是动态的,所以这时候用到了TimelineMax这是一个提供动画的库,类似于css动画但是比那个要丰富,就弄成了上图效果。我试过不用TimelineMax用定时器来模拟波纹,但是很丑,不推荐用。
html
<section class="bg"></section>
<main id="sketch">
<canvas id="canvas" data-img=""></canvas>
<div class="mask">
<div id="maskInner" class="mask-inner"></div>
</div>
</main>
<img src="" class="img1"></img>
<section class="button_container">
<button class="button">清除画布</button>
<button class="button"><input class="input" type="file" id="upload">切换图片</button>
</section>
<svg xlmns="http://www.w3.org/2000/svg" version="1.1" style="display: none;">
<filter id="heat" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
<feTurbulence id="heatturb" type="fractalNoise" numOctaves="1" seed="2" />
<feDisplacementMap xChannelSelector="G" yChannelSelector="B" scale="22" in="SourceGraphic" />
</filter>
</svg>
css
*
box-sizing: border-box;
margin: 0;
padding: 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
body, html
height: 100%;
overflow: hidden;
body
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: #121212;
background: -webkit-linear-gradient(to bottom, #434343, #121212);
background: linear-gradient(to bottom, #434343, #121212);
.bg
position: fixed;
top: -50%;
left: -50%;
right: -50%;
bottom: -50%;
width: 200%;
height: 200vh;
background: transparent url('../images/noise.png') repeat 0 0;
background-repeat: repeat;
animation: bg-animation .2s infinite;
opacity: .9;
visibility: visible;
@keyframes bg-animation
0% transform: translate(0,0)
10% transform: translate(-5%,-5%)
20% transform: translate(-10%,5%)
30% transform: translate(5%,-10%)
40% transform: translate(-5%,15%)
50% transform: translate(-10%,5%)
60% transform: translate(15%,0)
70% transform: translate(0,10%)
80% transform: translate(-15%,0)
90% transform: translate(10%,5%)
100% transform: translate(5%,0)
main
cursor: -webkit-grab;
cursor: grab;
width: 960px;
height: 540px;
flex-shrink: 0;
background-image: url('../images/bg.jpg');
background-size: cover;
background-position: 100% 50%;
position: relative;
border-radius: 16px;
overflow: hidden;
box-shadow: 1px 1px 10px rgba(0, 0, 0, .5);
border: 1px groove rgba(255, 255, 255, .2);
top: -50px;
canvas
opacity: 0;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
.mask
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
mask-mode: luminance;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
-webkit-backdrop-filter: hard-light;
backdrop-filter: hard-light;
-webkit-mask-image: url('../images/mask.png');
-moz-mask-image: url('../images/mask.png');
mask-image: url('../images/mask.png');
.mask-inner
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url('../images/bg.jpg') 0% 0% repeat;
background-size: cover;
background-position: 100% 50%;
filter: url(#heat);
-webkit-mask-image: url('../images/mask.png');
-moz-mask-image: url('../images/mask.png');
mask-image: url('../images/mask.png')
.button_container
margin: 40px auto;
position: fixed;
bottom: 0;
.button
height: 40px;
width: 200px;
position: relative;
-webkit-font-smoothing: antialiased;
background: #FFFFFF;
border-radius: 12px;
border: none;
outline: none;
-webkit-appearance: none;
color: #000000;
border-radius: 8px;
text-align: center;
font-size: 18px;
font-weight: 600;
text-decoration: none;
cursor: pointer;
overflow: hidden;
margin-bottom: 12px;
box-shadow: 0 1px 0 hsl(200,5%,80%),
0 2px 0 hsl(200,5%,75%),
0 3px 0 hsl(200,5%,70%),
0 4px 0 hsl(200,5%,66%),
0 5px 0 hsl(200,5%,64%),
0 6px 0 hsl(200,5%,62%),
0 7px 0 hsl(200,5%,61%),
0 8px 0 hsl(200,5%,60%),
0 0 5px rgba(0,0,0,.05),
0 1px 3px rgba(0,0,0,.2),
0 3px 5px rgba(0,0,0,.2),
0 5px 8px rgba(0,0,0,.2);
.button:hover
background: #EFEFEF;
.button:first-child
margin-right: 24px;
.button .input
position: absolute;
left: 0;
top: 0;
-webkit-appearance: none;
display: inline-block;
height: 100%;
width: 100%;
background: transparent;
opacity: 0;
cursor: pointer;
js
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var sketch = document.getElementById('sketch');
var sketchStyle = window.getComputedStyle(sketch);
var mouse = x: 0, y: 0 ;
canvas.width = parseInt(sketchStyle.getPropertyValue('width'));
canvas.height = parseInt(sketchStyle.getPropertyValue('height'));
canvas.addEventListener('mousemove', e =>
mouse.x = e.pageX - canvas.getBoundingClientRect().left;
mouse.y = e.pageY - canvas.getBoundingClientRect().top;
, false);
ctx.lineWidth = 40;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.strokeStyle = 'black';
canvas.addEventListener('mousedown', () =>
ctx.beginPath();
ctx.moveTo(mouse.x, mouse.y);
canvas.addEventListener('mousemove', onPaint, false);
, false);
canvas.addEventListener('mouseup', () =>
canvas.removeEventListener('mousemove', onPaint, false);
, false);
var onPaint = () =>
ctx.lineTo(mouse.x, mouse.y);
ctx.stroke();
var url = canvas.toDataURL();
document.querySelectorAll('div').forEach(item =>
item.style.cssText += `
display: initial;
-webkit-mask-image: url($url);
mask-image: url($url);
`;
);
;
document.querySelectorAll('div').forEach(item =>
item.style.cssText += `
display: initial;
`;
);
var timeline = new TimelineMax(
repeat: -1,
yoyo: true
),
feTurb = document.querySelector('#heatturb');
timeline.add(
new TweenMax.to(feTurb, 8,
onUpdate: function ()
var bfX = this.progress() * 0.01 + 0.025,
bfY = this.progress() * 0.003 + 0.01,
bfStr = bfX.toString() + ' ' + bfY.toString();
feTurb.setAttribute('baseFrequency', bfStr);
),
0);
function clear()
document.querySelectorAll('div').forEach(item =>
item.style.cssText += `
display: none;
-webkit-mask-image: none;
mask-image: none;
`;
);
document.querySelectorAll('.button').forEach(item =>
item.addEventListener('click', () =>
ctx.clearRect(0, 0, canvas.width, canvas.height);
clear();
)
);
document.getElementById('upload').onchange = function ()
var imageFile = this.files[0];
var newImg = window.URL.createObjectURL(imageFile);
clear();
document.getElementById('sketch').style.cssText += `
background: url($newImg);
background-size: cover;
background-position: center;
`;
document.getElementById('maskInner').style.cssText += `
background: url($newImg);
background-size: cover;
background-position: center;
`;
;
以上是关于canvas做静态图片波动的主要内容,如果未能解决你的问题,请参考以下文章