canvas噪点悬浮动画效果

代码语言:html

所属分类:悬停

代码描述:canvas噪点悬浮动画效果

代码标签: 动画 效果

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">

    <style>
@import url("https://fonts.googleapis.com/css2?family=Red+Rose:wght@400;700&display=swap");
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            width: 100%;
            height: 100vh;
            display: grid;
            place-items: center;
            background: #161616;
        }

        main {
            width: 100%;
            height: 100%;
            display: grid;
            place-items: center;
            padding: 4rem;
        }

        .cards {
            width: 100%;
            display: flex;
            flex-wrap: wrap;
            justify-content: center;
            align-items: center;
        }
        .cards .card {
            position: relative;
            width: 260px;
            height: 360px;
            margin: 2rem 4rem;
        }
        .cards .card__image {
            position: relative;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }
        .cards .card__image--inner {
            width: 100%;
            height: 100%;
            overflow: hidden;
        }
        .cards .card__image--inner canvas {
            transform: scale(1.02);
        }
        .cards .card__text {
            position: absolute;
            left: 0;
            bottom: 25%;
            transform: translateX(-50%);
            pointer-events: none;
            user-select: none;
            overflow: hidden;
        }
        .cards .card__text--inner {
            display: inline-block;
            color: #fff;
            font-size: 3rem;
            font-family: "Red Rose", Roboto;
            font-weight: 700;
        }

        .loading__wrapper {
            position: fixed;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            background: #000;
            z-index: 200;
            transition: opacity 500ms ease-in;
        }
        .loading__wrapper .loader__text {
            color: #fff;
            font-family: "Red Rose", Roboto;
            font-weight: 400;
            margin-bottom: 1.4rem;
        }
        .loading__wrapper.hide {
            pointer-events: none;
            user-select: none;
            opacity: 0;
        }

        .support {
            position: fixed;
            right: 10px;
            bottom: 10px;
            padding: 10px;
            display: flex;
        }
        .support a {
            margin: 0 10px;
            color: #fff;
            font-size: 1.8rem;
            backface-visibility: hidden;
            transition: all 150ms ease;
        }
        .support a:hover {
            transform: scale(1.1);
        }

        .github-corner {
            position: fixed;
            right: 0;
            top: 0;
        }
        .github-corner svg {
            color: #353;
            fill: #fff;
            clip-path: polygon(0 0, 100% 0, 100% 100%);
        }
        .github-corner:hover .octo-arm {
            animation: octocat-wave 0.56s;
        }

@keyframes octocat-wave {
            0%,
            100% {
                transform: rotate(0);
            }
            20%,
            60% {
                transform: rotate(-20deg);
            }
            40%,
            80% {
                transform: rotate(10deg);
            }
        }
    </style>

</head>
<body translate="no">
    <main>
        <div class="cards">
            <div class="card">
                <div class="card__image">
                    <div class="card__image--inner"></div>
                </div>
                <div class="card__text">
                    <span class="card__text--inner">DESERT</span>
                </div>
            </div>
          
        </div>
    </main>
    <div class="loading__wrapper">
        <div class="loader__text">
            Loading...
        </div>
    </div>
    <div class="support">
        <a href="" target="_blank"><i class="fab fa-twitter-square"></i></a>
        <a href="" target="_blank"><i class="fab fa-dribbble"></i></a>
    </div>

    <script type="text/javascript" src="http://repo.bfw.wiki/bfwrepo/js/gsap.3.3.1.js"></script>
    <script>
        // this might look cluttery on codepen, you can check the repo (below)
        // GITHUB LINK --> https://github.com/devloop01/canvas-image-interaction

        // I added comments just in case you are exploring through the code.

        // ALL THE CARD OPTIONS LISTED BELOW -->
        // 1. jumpToRandomPosition: If `true` the particles on every frame will jump to random position. Else the particles will move randomly without jumping. Defaults to `false`
        // 2. growAndShrink: If `true` the particles will grow & shrink, it will grow .8 times larger than the radius. Defaults to `false`
        // 3. fill: If `true` the particles are filled with the current pixel color that they are on, else they will be stroked for that same color. Defaults to `true`
        // 4. bounceFromEdges: If `true` the particles will bounce back when they hit the (specified) edges, or else thay will continue their path from the opposite edges/walls. Defaults to `true`.
        // 5. shape: You can specify what shape of the particles. Currently you can specify any one from the following, i.e. "circle", "square", "hexagon". If not specified then it defaults to "circle"
        // 6. radius: You can specity the radius of the particles, defaults to "5" if not specified.
        // 7. randomRadius: If `true` then the particles will have random radius, else defaults to `false`
        // 8. maxRadius: You can specify the minimum radius of the particles, else defaults to "2"
        // 9. minRadius: You can specify the maximum radius of the particles, else defaults to "5"
        // 10. maxVelocity: You can specify the maximum velocity of the particles, else defaults to "8"

        // Okay that's it, that's all the options I could add. Play around and see what fits for you.
        // Also please STAR this project if you think it's interesting, you can even fork it and make/add something new.

        console.clear();

        const cards = Array.from(document.querySelectorAll(".card"));
        const cardOptions = [{

            imageURL: {
                default: "http://repo.bfw.wiki/bfwrepo/image/5d65eaff5a217.png?x-oss-process=image/auto-orient,1/resize,m_fill,w_400,h_600,/quality,q_90",
                    hovered: "http://repo.bfw.wiki/bfwrepo/image/5e6831472e8f7.png"
                },

                totalParticles: 1500,
                mouseRange: 80,
                particlesConfig: {
                    jumpToRandomPosition: false,
                    fill: true,
                    randomRadius: true,
                    minRadius: 1,
                    maxRadius: 2
                }
            },


           ];




                const imageURLS = cardOptions.
                map(option => Object.values(option.imageURL)).
                flat();

                // --------------------- CLASSES ----------------------------

                class App {
                    init() {
                        // after all images are loaded remove loader
                        // (this is not the best way to do so but it gets the job done)
                        loadImages(imageURLS, images => {
                            // this array holds the images in a sub array
                            // i.e [img, img, img, img, img, img] ==> [[img, img], [img, img], [img, img]]
                            const splitedImagesArray = splitArray(images, 2);

                            cards.forEach((card, index) => {
                                new Canvas({
                                    parent: card.querySelector(".card__image--inner"),
                                    dimensions: {
                                        width: card.getBoundingClientRect().width,
                                        height: card.getBoundingClientRect().height
                                    },

                                    ...cardOptions[index],
                                    images: {
                                        default: splitedImagesArray[index][0],
                                            hovered: splitedImagesArray[index][1]
                                        }
                                    });


                                });

                                // hide the loading wrapper
                                document.querySelector(".loading__wrapper").classList.add("hide");

                                // let the gsap animation begin
                                gsap.
                                timeline({
                                    delay: 0.8,
                                    defaults: {
                                        duration: 1.5,
                                        stagger: 0.1,
                                        ease: "expo.out"
                                    }
                                }).


                                fromTo(
                                    cards.map(card => card.querySelector(".card__image")),
                                    {
                                        translateY: "-100%"
                                    },

                                    {
                                        translateY: "0%"
                                    }).


                                fromTo(
                                    cards.map(card => card.querySelector(".card__image--inner")),
                                    {
                                        translateY: "100%"
                                    },

                                    {
                                        translateY: "0%"
                                    },

                                    0).

                                fromTo(
                                    cards.map(card => card.querySelector(".card__text--inner")),
                                    {
                                        translateY: "100%"
                                    },

                                    {
                                        duration: 1.2,
                                        translateY: "0%"
                                    },

                                    0.4);

                            });
                        }}


                    class Canvas {
                        constructor(options = {}) {
                            // the parent where the canvas will be appended
                            this.parent = options.parent;

                            // canvas dimensions
                            this.dimensions = options.dimensions;

                            // all imageURL's, images(optional) & imagesData that are required
                            this.imageURL = options.imageURL || {};
                            this.images = options.images || {};
                            this.imagesData = options.imagesData || {
                                default: null,
                                    hovered: null
                                };

                                this.currentImageData = null;

                                // Array where all the particles will be stored
                                this.particles = null;
                                this.totalParticles = options.totalParticles || 400;

                                // boolean which changes to 'true' when hovered, oe else false
                                this.hovered = false;

                                // particles configs
                                this.particlesConfig = options.particlesConfig;

                                // mouse range and mouse particle instance
                                this.mouseRange = options.mouseRange || null;
                                this.mouse = null;

                                // initialize the canvas
                                this.init();
                            }

                            init() {
                                // create the canvas element
                                this.canvas = document.createElement("canvas");
                                // get the canvas context
                                this.ctx = this.canvas.getContext("2d");
                                // set the canvas dimensions
                                this.canvas.width = this.dimensions.width;
                                this.canvas.height = this.dimensions.height;

                                const initialize = () => {
                                    // this variable holds the current image data
                                    this.currentImageData = this.imagesData.default;

                                    // add many Particle instances
                                    this.addParticles(this.totalParticles);
                                    // start rendering the canvas
                                    this.startRender();
                                    // initialize all the canvas events
                                    this.initEvents();
                                    // append the canvas on the parent
                                    this.parent.appendChild(this.canvas);
                                };

                                // what happens here is if the user/dev provides the loaded image directly then use the images provided by the use directly
                                // and if the user provides the URL for the image then load the images from the URL and initialize
                                if (
                                    !this.images.hasOwnProperty("default") &&
                                    !this.images.hasOwnProperty("hovered")) {
                                    // load all the images that are required and after all the images are loaded the callback is called.
                                    loadImages([this.imageURL.default, this.imageURL.hovered], images => {
                                        // set the image data so that they can be accessed later when needed
                                        this.imagesData.default = returnImageData(images[0], this.dimensions);
                                        this.imagesData.hovered = returnImageData(images[1], this.dimensions);
                                        initialize();
                                    });
                                } else {
                                    // set the image data so that they can be accessed later when needed
                                    this.imagesData.default = returnImageData(
                                        this.images.default,
                                        this.dimensions);

                                    this.imagesData.hovered = returnImageData(
                                        this.images.hovered,
                                        this.dimensions);

                                    initialize();
                                }

                                // init mouse particle
                                if (this.mouseRange != null) {
                                    this.mouse = new Particle({
                                        ctx: this.ctx,
                                        position: {
                                            x: 0,
                                            y: 0
                                        },

                                        radius: this.mouseRange,
                                        color: "#000",
                                        avoisEdges: true,
                                        shape: "circle"
                                    });

                                }
                            }

                            initEvents() {
                                const onMouseEnter = () => {
                                    this.hovered = true;
                                    this.currentImageData = this.imagesData.hovered;
                                };
                                const onMouseLeave = () => {
                                    this.hovered = false;
                                    this.currentImageData = this.imagesData.default;
                                };
                                const onMouseMove = e => {
                                    if (this.mouse != null && this.hovered) {
                                        this.mouse.position.x = e.offsetX;
                                        this.mouse.position.y = e.offsetY;
                                    }
                                };

                                this.canvas.addEventListener("mouseenter", onMouseEnter);
                                this.canvas.addEventListener("mouseleave", onMouseLeave);
                                this.canvas.addEventListener("mousemove", onMouseMove);
                            }

                            addParticles(n) {
                                this.particles = new Particles({
                                    ctx: this.ctx,
                                    totalParticles: n,
                                    maxBounds: {
                                        width: this.dimensions.width, height: this.dimensions.height
                                    },
                                    imageData: this.currentImageData,
                                    particlesConfig: this.particlesConfig
                             .........完整代码请登录后点击上方下载按钮下载查看

网友评论0