curtainsJs是一款让照片与视频动起来的插件

 curtainsJs是一款让照片与视频动起来的插件

curtainsJs是一款让照片与视频动起来的插件,属于轻量级的WebGL js库,可将HTML元素转换为交互式纹理平面,让其动起来。

使用方式:

第一步引入bfwone 加载依赖项curtainsJs

第二步准备html

<body>
  <!-- div that will hold our WebGL canvas -->
  <div id="canvas"></div>

  <!-- div used to create our plane -->
  <div class="plane">

    <!-- image that will be used as a texture by our plane -->
    <img src="path/to/my-image.jpg" />
      
  </div>

</body>

第三步设置css

body {
  /* make the body fit our viewport */
  position: relative;
  width: 100%;
  height: 100vh;
  margin: 0;
  
  /* hide scrollbars */
  overflow: hidden;
}

#canvas {
  /* make the canvas wrapper fit the window */
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
}

.plane {
  /* define the size of your plane */
  width: 80%;
  max-width: 1400px;
  height: 80vh;
  position: relative;
  top: 10vh;
  margin: 0 auto;
}

.plane img {
  /* hide the img element */
  display: none;
}

/*** in case of error show the image ***/

.no-curtains .plane {
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.no-curtains .plane img {
  display: block;
  max-width: 100%;
  object-fit: cover;
}

第四步js

  var webGLCurtain = new Curtains("canvas");

  // if there's any error during init, we're going to catch it here
  webGLCurtain.onError(function() {
    // we will add a class to the document body to display original images
    document.body.classList.add("no-curtains");
  });

  // get our plane element
  var planeElement = document.getElementsByClassName("plane")[0];

  // set our initial parameters (basic uniforms)
  var params = {
    vertexShaderID: "plane-vs", // our vertex shader ID
    fragmentShaderID: "plane-fs", // our fragment shader ID
    uniforms: {
      time: {
        name: "uTime", // uniform name that will be passed to our shaders
        type: "1f", // this means our uniform is a float
        value: 0,
      },
    }
  }

  // create our plane mesh
  var plane = webGLCurtain.addPlane(planeElement, params);

  // if our plane has been successfully created
  // we use the onRender method of our plane fired at each requestAnimationFrame call
  plane && plane.onRender(function() {
    plane.uniforms.time.value++; // update our time uniform value
  });

第五步阴影设置

我们需要编写顶点着色。基本上,我们需要根据模型视图和投影矩阵定位平面,并将不同的变量传递给片段明暗器。
其中一个变量称为vtexturecoord,并在片段着色中用于在平面上映射纹理。我们可以直接传递ATextureCoord属性,但是我们会得到一个拉伸的纹理,因为我们的平面和图像不一定具有相同的纵横比。幸运的是,库提供了一个统一的纹理矩阵,我们可以使用它来计算新的坐标,该坐标将裁剪纹理,使其始终适合平面(将其视为背景大小:覆盖等效)。

<!-- vertex shader -->
<script id="plane-vs" type="x-shader/x-vertex">
  #ifdef GL_ES
  precision mediump float;
  #endif

  // those are the mandatory attributes that the lib sets
  attribute vec3 aVertexPosition;
  attribute vec2 aTextureCoord;

  // those are mandatory uniforms that the lib sets and that contain our model view and projection matrix
  uniform mat4 uMVMatrix;
  uniform mat4 uPMatrix;

  // our texture matrix uniform (this is the lib default name, but it could be changed)
  uniform mat4 uTextureMatrix0;

  // if you want to pass your vertex and texture coords to the fragment shader
  varying vec3 vVertexPosition;
  varying vec2 vTextureCoord;

  void main() {
    // get the vertex position from its attribute
    vec3 vertexPosition = aVertexPosition;
    // set its position based on projection and model view matrix
    gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);

    // set the varying variables
    // thanks to the texture matrix we will be able to calculate accurate texture coords
    // so that our texture will always fit our plane without being distorted
    vTextureCoord = (uTextureMatrix0 * vec4(aTextureCoord, 0.0, 1.0)).xy;
    vVertexPosition = vertexPosition;
  }
</script>


完整示例如下,可在线直接运行

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>BFW NEW PAGE</title>
    <script id="bfwone" data="dep=curtains.min&err=0" type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/bfwone.js"></script>
    <script type="text/javascript">
        bready(function() {
            var webGLCurtain = new Curtains("canvas");

            // if there's any error during init, we're going to catch it here
            webGLCurtain.onError(function() {
                // we will add a class to the document body to display original images
                document.body.classList.add("no-curtains");
            });

            // get our plane element
            var planeElement = document.getElementsByClassName("plane")[0];

            // set our initial parameters (basic uniforms)
            var params = {
                vertexShaderID: "plane-vs", // our vertex shader ID
                fragmentShaderID: "plane-fs", // our fragment shader ID
                uniforms: {
                    time: {
                        name: "uTime", // uniform name that will be passed to our shaders
                        type: "1f", // this means our uniform is a float
                        value: 0,
                    },
                }
            }

            // create our plane mesh
            var plane = webGLCurtain.addPlane(planeElement, params);

            // if our plane has been successfully created
            // we use the onRender method of our plane fired at each requestAnimationFrame call
            plane && plane.onRender(function() {
                plane.uniforms.time.value++; // update our time uniform value
            });
        });
    </script>
    <style>
        body {
            /* make the body fit our viewport */
            position: relative;
            width: 100%;
            height: 100vh;
            margin: 0;

            /* hide scrollbars */
            overflow: hidden;
        }

        #canvas {
            /* make the canvas wrapper fit the window */
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100vh;
        }

        .plane {
            /* define the size of your plane */
            width: 80%;
            max-width: 1400px;
            height: 80vh;
            position: relative;
            top: 10vh;
            margin: 0 auto;
        }

        .plane img {
            /* hide the img element */
            display: none;
        }

        /*** in case of error show the image ***/

        .no-curtains .plane {
            overflow: hidden;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .no-curtains .plane img {
            display: block;
            max-width: 100%;
            object-fit: cover;
        }
    </style>
</head>
<body>
    <!-- div that will hold our WebGL canvas -->
    <div id="canvas"></div>

    <!-- div used to create our plane -->
    <div class="plane">

        <!-- image that will be used as a texture by our plane -->
        <img src="/bfwrepo/image/slicebox/4.jpg" />

    </div>
    <!-- vertex shader -->
    <script id="plane-vs" type="x-shader/x-vertex">
        #ifdef GL_ES
        precision mediump float;
        #endif

        // those are the mandatory attributes that the lib sets
        attribute vec3 aVertexPosition;
        attribute vec2 aTextureCoord;

        // those are mandatory uniforms that the lib sets and that contain our model view and projection matrix
        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;

        // our texture matrix uniform (this is the lib default name, but it could be changed)
        uniform mat4 uTextureMatrix0;

        // if you want to pass your vertex and texture coords to the fragment shader
        varying vec3 vVertexPosition;
        varying vec2 vTextureCoord;

        void main() {
            // get the vertex position from its attribute
            vec3 vertexPosition = aVertexPosition;
            // set its position based on projection and model view matrix
            gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);

            // set the varying variables
            // thanks to the texture matrix we will be able to calculate accurate texture coords
            // so that our texture will always fit our plane without being distorted
            vTextureCoord = (uTextureMatrix0 * vec4(aTextureCoord, 0.0, 1.0)).xy;
            vVertexPosition = vertexPosition;
        }
    </script>
    <!-- fragment shader -->
    <script id="plane-fs" type="x-shader/x-fragment">
        #ifdef GL_ES
        precision mediump float;
        #endif

        // get our varying variables
        varying vec3 vVertexPosition;
        varying vec2 vTextureCoord;

        // the uniform we declared inside our javascript
        uniform float uTime;

        // our texture sampler (this is the lib default name, but it could be changed)
        uniform sampler2D uSampler0;

        void main() {
            // get our texture coords
            vec2 textureCoord = vTextureCoord;

            // displace our pixels along both axis based on our time uniform and texture UVs
            // this will create a kind of water surface effect
            // try to comment a line or change the constants to see how it changes the effect
            // reminder : textures coords are ranging from 0.0 to 1.0 on both axis
            const float PI = 3.141592;

            textureCoord.x += (
                sin(textureCoord.x * 10.0 + ((uTime * (PI / 3.0)) * 0.031))
                + sin(textureCoord.y * 10.0 + ((uTime * (PI / 2.489)) * 0.017))
            ) * 0.0075;

            textureCoord.y += (
                sin(textureCoord.y * 20.0 + ((uTime * (PI / 2.023)) * 0.023))
                + sin(textureCoord.x * 20.0 + ((uTime * (PI / 3.1254)) * 0.037))
            ) * 0.0125;

            gl_FragColor = texture2D(uSampler0, textureCoord);
        }
    </script>
</body>
</html>

官网 https://css-tricks.com/animate-images-and-videos-with-curtains-js/


立即下载curtains.min.js查看所有js插件

网友评论0

程序员在线工具箱