我正在参加「构思开发 投稿大赛」详情请看:构思开发大赛来了!

声明:本文触及图文和模型素材仅用于个人学习、研究和欣赏,请勿二次修正、不合法传播、转载、出版、商用、及进行其他获利行为。

布景

假如你有玩过 《王者荣耀》《阴阳师》 等手游,一定留意到过它的发动动画、皮肤立绘卡片等场景,常常采用静态底图加部分液态活动作用的简略动画,这些活动动画可能出现在慢慢活动的水流 、迎风飘动的旗号 、游戏人物衣袖 ‍♀️、跟着时间缓动的云、雨、雾气候作用 等。这种过渡作用不只节省了开发全量动画的本钱,并且使得游戏画面更加热血、冒险、奥德赛、高级,也更加容易招引玩家氪金

本文运用前端开发技能,结合 SVGCSS 来完结类似的液化活动作用。本文包含的常识点首要包含:mask-image 遮罩、feTurbulencefeDisplacementMap 滤镜、filter 特点、canvas 制造办法、TimelineMax 动画以及input[type=file] 本地图片资源加载等。

作用

先来看看完结作用,下面几个示例以及 文章 Banner 图都是应用了由本文内容生成的液态活动动画作用。因为GIF 图紧缩比较严重,动画作用看起来不是很流通 ,大家不妨经过以下演示页面链接,亲自体会一下作用,生成自己的 传说典藏 皮肤立绘吧

在线体会:dragonir.github.io/paint-heat-…

雾气分散 塞尔达传说:旷野之息

运用前端技能完结静态图片部分活动作用

衣袖飘动 貂蝉:猫影幻舞

运用前端技能完结静态图片部分活动作用

湖光动摇

运用前端技能完结静态图片部分活动作用

文字液化

运用前端技能完结静态图片部分活动作用

ps:体会页面布置在 Gitpage 上传图片功用不是真实上传到服务器,而是只会加载到浏览器本地,页面不会获取任何信息,大家能够放心体会,不用担心隐私走漏问题。

码上

完结

页面首要由 2 部分构成,顶部用于加载图片 ,并且能够经过按住 鼠标划动的方法制造热门途径,给图片增加活动作用;底部是控制区域,点击按钮 铲除画布,能够铲除制造的活动动画作用、点击按钮 切换图片能够加载本地的图片。

运用前端技能完结静态图片部分活动作用

留意,还有一个隐形的功用,当你制造完结时,能够点击 鼠标右键,然后挑选保存图片,保存的这张图片便是咱们制造流体动画途径的热门图,运用这张热门图,运用本文的 CSS 常识,就能把静态图片转化成动态图啦!

HTML 页面结构

#sketch 元素首要是用于制造和加载活动作用热门图的画板;#button_container 是页面底部的按钮控制区域;svg 元素用于运用其 filter 滤镜完结液态活动动画作用,包含 feTurbulencefeDisplacementMap 滤镜。

<main id="sketch">
  <canvas id="canvas" data-img=""></canvas>
  <div class="mask">
    <div id="maskInner" class="mask-inner"></div>
  </div>
</main>
<section class="button_container">
  <button class="button">铲除画布</button>
  <button class="button"><input class="input" type="file" id="upload">上传图片</button>
</section>
<svg>
  <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>

feTurbulence 和 feDisplacementMap

  • feTurbulence:滤镜运用 Perlin 噪声函数创建了一个图画,运用它能够完结人造纹理比如说云纹、大理石纹等模拟滤镜作用。
  • feDisplacementMap:映射置换滤镜,该滤镜用来自图画中从 in2 到空间的像素值置换图画从 in 到空间的像素值。即它能够改动元素和图形的像素方位,经过遍历原图形的一切像素点,feDisplacementMap 重新映射替换一个新的方位,构成一个新的图形。该滤镜在业界的主流应用是对图形进行形变,扭曲,液化。

CSS 款式

接着看看款式的完结,main 元素作为主容器并将主图案作为布景图片;canvas 作为画布占有 100% 的空间方位;.mask.mask-inner 用于生成如下图所示热门途径与布景图相溶的作用,这种作用是凭借 mask-image 完结的。最后,为了生成动态活动作用,.mask-inner 经过 filter: url(#heat) 将前面生成的 svg 作为滤镜来源,后续即将在 JavaScript 中经过不间断修正 svg 滤镜的特点,来生成液态活动动画。

main {
  position: relative;
  background-image: url('bg.jpg');
  background-size: cover;
  background-position: 100% 50%;
}
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%;
  mask-mode: luminance;
  mask-size: 100% 100%;
  backdrop-filter: hard-light;
  mask-image: url('mask.png');
}
.mask-inner {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: url('bg.jpg') 0% 0% repeat;
  background-size: cover;
  background-position: 100% 50%;
  filter: url(#heat);
  mask-image: url('mask.png')
}

运用前端技能完结静态图片部分活动作用

mask-image

mask-image CSS 特点用于设置元素上遮罩层的图画。

语法

// 默认值,透明的黑色图画层,也便是没有遮罩层。
mask-image: none;
// <mask-source><mask>或CSS图画的url的值
mask-image: url(masks.svg#mask1);
// <image> 图片作为遮罩层
mask-image: linear-gradient(rgba(0, 0, 0, 1.0), transparent);
mask-image: image(url(mask.png), skyblue);
// 多个值
mask-image: image(url(mask.png), skyblue), linear-gradient(rgba(0, 0, 0, 1.0), transparent);
// 大局值
mask-image: inherit;
mask-image: initial;
mask-image: unset;

兼容性

运用前端技能完结静态图片部分活动作用

此功用某些浏览器尚在开发中,需要运用浏览器前缀以兼容不同浏览器。

JavaScript 办法

① 制造热门图

监听鼠标移动和点击事件,在 canvas 上制造动摇途径热门。

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});
    `;
  });
};

制造完结后,能够在页面中右键保存生成的动摇途径热门图,直接将制造满足的热门图放到 CSS 中,就能给喜爱的图片增加部分动摇作用了,下面这张图片便是本示例页面运用的动摇的热门途径图。

运用前端技能完结静态图片部分活动作用

② 生成动画

为了生成实时更新的动摇作用,本文运用了 TweenMax 来经过改动 feTurbulencebaseFrequency 特点值来完结,运用其他动画库或运用 requestAnimationFrame 也是能够完结相同的功用。

feTurb = document.querySelector('#heatturb');
var timeline = new TimelineMax({
  repeat: -1,
  yoyo: true
}),
timeline.add(
  new TweenMax.to(feTurb, 8, {
    onUpdate: () => {
      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);

③ 铲除画布

点击铲除画布按钮,能够清空已经制造的动摇途径,首要是经过铲除页面元素 mask-image 的特点值以及清 canvas 画布来完结的。

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();
  })
});

④ 切换图片

点击切换图片,能够加载本地的一张图片作为制造底图,该功用是经过 input[type=file] 来完结图片资源的获取,然后经过修正 CSS 将它设置成新的画布布景。

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;
  `;
};

到这儿,全部功用都完结结束了,大家从速制造一张自己喜爱的 史诗皮肤奥德赛小游戏 的发动页面吧

运用前端技能完结静态图片部分活动作用

源码地址:github.com/dragonir/pa…

总结

本文包含的新常识点首要包含:

  • mask-image 遮罩元素
  • feTurbulencefeDisplacementMap svg滤镜
  • filter 特点
  • Canvas 制造办法
  • TimelineMax 动画
  • input[type=file] 本地图片资源加载

想了解其他前端常识或其他未在本文中详细描述的 Web 3D 开发技能相关常识,可阅览我往期的文章。转载请注明原文地址和作者。假如觉得文章对你有帮助,不要忘了一键三连哦

附录

  • 我的3D专栏能够点击此链接访问

  • [1]. 运用Three.js完结炫酷的赛博朋克风格3D数字地球大屏

  • [2]. Three.js 完结3D敞开世界小游戏:阿狸的多元宇宙

  • [3]. Three.js 火焰作用完结艾尔登法环动态logo

  • [4]. Three.js 完结2022冬奥主题3D趣味页面,含冰墩墩

  • ...

  • [1]. 前端完结很哇塞的浏览器端扫码功用

  • [2]. 前端瓦片地图加载之塞尔达传说旷野之息

  • [3]. 仅用CSS几步完结赛博朋克2077风格视觉作用

  • ...

参考

  • [1]. developer.mozilla.org/zh-CN/docs/…
  • [2]. developer.mozilla.org/zh-CN/docs/…
  • [3]. developer.mozilla.org/zh-CN/docs/…
  • [4]. developer.mozilla.org/zh-CN/docs/…