![three.js创建光线](https://i-blog.csdnimg.cn/blog_migrate/20ad1591fd3645fccd3c655a204039b0.png)
three.js创建光线
![Motion_feat](https://i-blog.csdnimg.cn/blog_migrate/522d663295e30d117c501cc8528a50fb.png)
The reveal hover effect on images has become a very popular pattern in modern websites. It plays an important role in taking the user experience to a higher level. But usually these kind of animations remain too “flat”. Natural movements with a realistic feel are much more enjoyable for the user. In this tutorial we’re going to build some special interactive reveal effects for images when a link is hovered. The aim is to add fluid and interesting motion to the effects. We will be exploring three different types of animations. This dynamic experience consists of two parts:
在图像上显示悬停效果已成为现代网站中非常流行的模式。 它在将用户体验提升到更高水平方面起着重要作用。 但是通常这些动画仍然太“平坦”。 具有逼真的感觉的自然运动对于用户而言更加令人愉悦。 在本教程中,我们将在悬停链接时为图像构建一些特殊的交互式显示效果。 目的是为效果添加流畅而有趣的运动。 我们将探索三种不同类型的动画。 这种动态体验包括两个部分:
Distortion Image Effect (main effect)
失真图像效果(主要效果)
RGB Displacement, Image Trail Effect, Image Stretch (additional effects)
RGB位移,图像拖尾效果,图像拉伸(附加效果)
We assume that you are confident with JavaScript and have some basic understanding of Three.js and WebGL.
我们假设您对JavaScript充满信心,并且对Three.js和WebGL有一些基本的了解。
入门 (Getting started)
The markup for this effect will include a link element that contains an image (and some other elements that are not of importance for our effect):
此效果的标记将包括一个链接元素,其中包含一个图像(以及一些其他对我们的效果不重要的元素):
<a class="link" href="#">
<!-- ... -->
<img src="img/demo1/img1.jpg" alt="Some image" />
</a>
The EffectShell class will group common methods and properties of the three distinct effects we’ll be creating. As a result, each effect will extend EffectShell.
EffectShell类将对我们将要创建的三个不同效果的通用方法和属性进行分组。 结果,每个效果都会扩展EffectShell。
Three.js设置 (Three.js setup)
First of all, we need to create the Three.js scene.
首先,我们需要创建Three.js场景。
class EffectShell {
constructor(container = document.body, itemsWrapper = null) {
this.container = container
this.itemsWrapper = itemsWrapper
if (!this.container || !this.itemsWrapper) return
this.setup()
}
setup() {
window.addEventListener('resize', this.onWindowResize.bind(this), false)
// renderer
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
this.renderer.setSize(this.viewport.width, this.viewport.height)
this.renderer.setPixelRatio = window.devicePixelRatio
this.container.appendChild(this.renderer.domElement)
// scene
this.scene = new THREE.Scene()
// camera
this.camera = new THREE.PerspectiveCamera(
40,
this.viewport.aspectRatio,
0.1,
100
)
this.camera.position.set(0, 0, 3)
// animation loop
this.renderer.setAnimationLoop(this.render.bind(this))
}
render() {
// called every frame
this.renderer.render(this.scene, this.camera)
}
get viewport() {
let width = this.container.clientWidth
let height = this.container.clientHeight
let aspectRatio = width / height
return {
width,
height,
aspectRatio
}
}
onWindowResize() {
this.camera.aspect = this.viewport.aspectRatio
this.camera.updateProjectionMatrix()
this.renderer.setSize(this.viewport.width, this.viewport.height)
}
}
获取项目并加载纹理 (Get items and load textures)
In our markup we have links with images inside. The next step is to get each link from the DOM and put them in an array.
在我们的标记中,我们具有内部图像的链接。 下一步是从DOM获取每个链接,并将它们放入数组中。
class EffectShell {
...
get itemsElements() {
// convert NodeList to Array
const items = [...this.itemsWrapper.querySelectorAll('.link')]
//create Array of items including element, image and index
return items.map((item, index) => ({
element: item,
img: item.querySelector('img') || null,
index: index
}))
}
}
Because we will use the images as a texture, we have to load the textures through Three.js’ TextureLoader. It’s an asynchronous operation so we shouldn’t initialize the effect without all textures being loaded. Otherwise our texture will be fully black. That’s why we use Promises here:
因为我们将图像