zoukankan      html  css  js  c++  java
  • css3+js旗帜飘动

    效果一:(css+dom实现)

      

    代码:

    <!doctype html>
    <html lang="zh-cn">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
            content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>飘动的旗帜~</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            html,
            body {
                height: 100%;
                 100%;
                background-color: lightgrey;
            }
    
            body {
                text-align: center;
                position: relative;
            }
    
            ul,
            li {
                list-style: none;
            }
    
            #flag {
                position: absolute;
                left: 50%;
                top: 50%;
                transform: translate3d(-50%, -50%, 0);
                animation: flag-reverse ease-in-out infinite;
            }
    
            /* 这里是核心css样式 */
            #flag>li {
                height: 100%;
                float: left;
                background-image: url("https://oscimg.oschina.net/oscnet/4073613a5ab7bb799829aa83a67e9f46b7d.jpg");
                background-size: auto 100%;
                animation: flag ease-in-out infinite;
            }
        </style>
    </head>
    
    <body>
        <ul id="flag"></ul>
        <script>
            (function () {
                // 这里是js代码
                var flagEle = document.getElementById('flag')
                var image = new Image()
                image.src = 'https://oscimg.oschina.net/oscnet/4073613a5ab7bb799829aa83a67e9f46b7d.jpg'
    
                var IMG_MAX_WIDTH = 600
                var IMG_MAX_HEIGHT = 600
                var imgHeight
                var imgWidth
                image.onload = function () {
                    imgWidth = image.width
                    imgHeight = image.height
                    var ratio = image.width / image.height
                    if (imgWidth > IMG_MAX_WIDTH) {
                        imgWidth = IMG_MAX_WIDTH
                        imgHeight = imgWidth / ratio
                    }
                    if (imgHeight > IMG_MAX_HEIGHT) {
                        imgHeight = IMG_MAX_HEIGHT
                        imgWidth = imgHeight * ratio
                    }
    
                    flagEle.style.width = imgWidth + 'px'
                    flagEle.style.height = imgHeight + 'px'
                    flagEle.style.marginLeft = -imgWidth / 2 + 'px'
                    flagEle.style.marginTop = -imgHeight / 2 + 'px'
    
                    splitImg(100, 20, 1.5, 2)
    
                    function splitImg(sliceCount, amplitude, period, duration) {
                        var styleEle = document.createElement('style')
                        // styleEle.innerHTML = 'body{background: red}'
                        var styleHtmlAry = []
                        var sliceCountPerPeriod = Math.floor(sliceCount / period)
                        var sliceWidth = imgWidth / sliceCount
                        var formula = sliceCountPerPeriod + 'n+'
                        var interval = duration * period / sliceCount
    
                        // 添加动画延时
                        for (var i = 0; i < sliceCount; i++) {
                            if (i < sliceCountPerPeriod) {
                                styleHtmlAry.push('#flag > li:nth-child(' + formula + i + ') { ')
                                styleHtmlAry.push('animation-delay: -' + (interval * (sliceCountPerPeriod - i)) +
                                    's;')
                                styleHtmlAry.push('}')
                            }
                            styleHtmlAry.push('#flag > li:nth-child(' + i + ') { background-position: -' + (i *
                                sliceWidth) + 'px 0; }') // 设置切片背景
                        }
    
                        // 添加关键帧动画
                        styleHtmlAry.push('@keyframes flag {')
                        styleHtmlAry.push('0% { transform: translate3d(0, ' + amplitude + 'px, 0); }')
                        styleHtmlAry.push('50% { transform: translate3d(0, -' + amplitude + 'px, 0); }')
                        styleHtmlAry.push('100% { transform: translate3d(0, ' + amplitude + 'px, 0); }')
                        styleHtmlAry.push('}')
    
                        // 添加反向关键帧动画
                        styleHtmlAry.push('@keyframes flag-reverse {')
                        styleHtmlAry.push('0% { transform: translate3d(0, ' + (-amplitude) + 'px, 0); }')
                        styleHtmlAry.push('50% { transform: translate3d(0, ' + amplitude + 'px, 0); }')
                        styleHtmlAry.push('100% { transform: translate3d(0, ' + (-amplitude) + 'px, 0); }')
                        styleHtmlAry.push('}')
    
                        // 容器应用flag-reverse动画
                        styleHtmlAry.push('#flag {')
                        styleHtmlAry.push('animation-duration: ' + duration + 's;') // 添加周期时长
                        styleHtmlAry.push('animation-delay: -' + (interval * sliceCountPerPeriod) + 's;')
                        styleHtmlAry.push('}')
    
                        // 切片样式
                        styleHtmlAry.push('#flag > li {')
                        styleHtmlAry.push('animation-duration: ' + duration + 's;') // 添加周期时长
                        styleHtmlAry.push(' ' + (imgWidth / sliceCount) + 'px;') // 设置切片宽度
                        styleHtmlAry.push('}')
    
                        styleEle.innerHTML = styleHtmlAry.join('')
    
                        // 创建切片元素
                        flagEle.innerHTML = new Array(sliceCount + 1).join('<li></li>')
                        document.documentElement.appendChild(styleEle)
                    }
                }
            })();
        </script>
    </body>
    
    </html>

    效果二:(比较有质感,canvas实现)

      

    代码:

    <!DOCTYPE html>
    <html lang="zh-cn">
    
    <head>
        <meta charset="UTF-8">
        <title>旗帜飘飘</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            html,
            body {
                 100%;
                height: 100%;
            }
    
            body {
                position: relative;
                background: lightgrey;
            }
    
            #flagCanvas {
                position: absolute;
                top: 50%;
                left: 50%;
                transform-origin: center;
                transform: translate3d(-50%, -50%, 0);
            }
        </style>
    </head>
    
    <body>
        <canvas id="flagCanvas"></canvas>
        <script>
            var canvas = document.getElementById('flagCanvas')
            var ctx = canvas.getContext('2d')
    
            var IMG_MAX_WIDTH = 600
            var IMG_MAX_HEIGHT = 600
            var imgWidth, imgHeight
    
            var image = new Image()
            image.src = 'https://oscimg.oschina.net/oscnet/4073613a5ab7bb799829aa83a67e9f46b7d.jpg'
    
            var amplitude = 30 // 振幅
            var period = 2 // 周期数
            var frequency = 1 // 频率
            var wavelength // 波长
            var v // 波速
            var cftX // x系数
            var cftA // 振幅系数
    
            image.onload = function (ev) {
    
                imgWidth = Math.floor(image.width)
                imgHeight = Math.floor(image.height)
    
                var canvas = document.getElementById('flagCanvas')
                var scale = 1
                if (imgWidth > IMG_MAX_WIDTH) {
                    scale = IMG_MAX_WIDTH / imgWidth
                }
                if (imgHeight > IMG_MAX_HEIGHT) {
                    scale = scale * IMG_MAX_HEIGHT / imgHeight
                }
    
                canvasWidth = imgWidth
                canvasHeight = imgHeight + amplitude * 2
                canvas.width = canvasWidth
                canvas.height = canvasHeight
                canvas.style.transform = 'translate3d(-50%,-50%,0) scale(' + scale + ')'
    
                wavelength = imgWidth / period
                cftX = 2 * Math.PI / wavelength
                cftA = amplitude / imgWidth
                v = wavelength * frequency
    
                tick()
            }
    
            var fps = 70 // 每秒帧数
            var interval = 1000 / fps // 连续帧之间间隔(理论)
            var stop = false // 停止动画
            var timeNow = Date.now() // 当前时间
            var timeLast = timeNow // 上一帧时间
            var delta = 0 // 连续帧之间间隔(实际)
    
            var y = 0
            var lastY = 0
            var distance = 0
            var tick = function () {
                if (stop) return false
                timeNow = Date.now()
                delta = timeNow - timeLast
                if (delta > interval) {
                    timeLast = timeNow
                    distance += (delta / 1000 * v)
                    ctx.clearRect(0, 0, canvasWidth, canvasHeight)
                    for (var x = 0; x < imgWidth; x++) {
                        // var y = cftA * x * Math.sin(cftX * (x - distance)) + amplitude
                        // ctx.drawImage(image, x, 0, 1, imgHeight, x, y, 1, imgHeight)
                        y = cftA * x * Math.sin(cftX * (x - distance)) + amplitude
                        ctx.drawImage(image, x, 0, 1, imgHeight, x, y, 1, imgHeight)
                        ctx.fillStyle = 'rgba(255,255,255,' + (x === 0 ? 0 : (y - lastY) * 0.5) + ')'
                        ctx.fillRect(x, y, 1, imgHeight)
                        lastY = y
                    }
                }
                requestAnimationFrame(tick)
            }
        </script>
    </body>
    
    </html>
  • 相关阅读:
    Echarts柱状图,颜色随机改变
    输入地名查询出经纬度
    简单的JS数组所有重复元素抽出到一个新数组
    zTree 树形中的搜索定位节点
    vue js 中简单的搜索功能
    百度地图,多边形覆盖物区域,加标签
    pyspider 介绍
    网站的免责声明应当如何撰写才能保护自己的权益
    sftp 设置默认权限
    【聚类算法】谱聚类(Spectral Clustering)
  • 原文地址:https://www.cnblogs.com/wuqilang/p/12172186.html
Copyright © 2011-2022 走看看