js多张图片绕中心点旋转(远小近大)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    #wrap{
        position: relative;
    }
    #container{
        position: absolute;
        /* top: 50%; */
        /* right: 50%; */
    }
</style>
<body>
    <div id="wrap"
        style="width: 100%; height: 97vh">
        <div id="container">
            <img src="https://lmg.jj20.com/up/allimg/4k/s/02/210924233115O14-0-lp.jpg" /> 
            <img src="https://lmg.jj20.com/up/allimg/4k/s/02/210924233115O14-0-lp.jpg" />
            <img src="https://lmg.jj20.com/up/allimg/4k/s/02/210924233115O14-0-lp.jpg" /> 
            <img src="https://lmg.jj20.com/up/allimg/4k/s/02/210924233115O14-0-lp.jpg" /> 
            <img src="https://lmg.jj20.com/up/allimg/4k/s/02/210924233115O14-0-lp.jpg" /> 
            <img src="https://lmg.jj20.com/up/allimg/4k/s/02/210924233115O14-0-lp.jpg" />
            <img src="https://lmg.jj20.com/up/allimg/4k/s/02/210924233115O14-0-lp.jpg" />
            <img src="https://lmg.jj20.com/up/allimg/4k/s/02/210924233115O14-0-lp.jpg" />
        </div>
    </div>
    <p>手动模式:<input id="select" onclick="rp.setPattern('hand');" type="radio" name="sel" value="手动模式" /> 自动模式:<input
            id="select" onclick="rp.setPattern('auto');" type="radio" name="sel" value="自动模式" /></p>
    <p><input id="pre" type="button" value="上一张" /> <input id="next" type="button" value="下一张" /></p>
    <p>
        <script type="text/javascript">
            var rotatePhos = (function () {
                var util = {
                    $: function (sId) { return document.getElementById(sId); },
                    $$: function (tagName, parent) { parent = parent || document; return parent.getElementsByTagName(tagName); },
                    addEventHandler: function (elem, type, handler) {
                        if (elem.addEventListener) {
                            elem.addEventListener(type, handler, false);
                        }
                        else {
                            elem.attachEvent("on" + type, handler);
                        }
                    },
                    removeEventHandler: function (elem, type, handler) {
                        if (elem.removeEventListener) {
                            elem.removeEventListener(type, handler, false);
                        }
                        else {
                            elem.detachEvent("on" + type, handler);
                        }
                    },
                    getComputedStyle: function (elem) {
                        if (elem.currentStyle)
                            return elem.currentStyle;
                        else {
                            return document.defaultView.getComputedStyle(elem, null);
                        }
                    },
                    emptyFunction: function () { },
                    getElementsByClassName: function (className, parentElement) {
                        var elems = (parentElement || document.body).getElementsByTagName("*");
                        var result = [];
                        for (i = 0; j = elems[i]; i++) {
                            if ((" " + j.className + " ").indexOf(" " + className + " ") != -1) {
                                result.push(j);
                            }
                        }
                        return result;
                    },
                    extend: function (destination, source) {
                        for (var name in source) {
                            destination[name] = source[name];
                        }
                        return destination;
                    }
                };
                var rp = function (id, options) {
                    this.init(id, options); //初始化 
                }
                rp.prototype = (function () {
                    var rotate;
                    var imgWidth;
                    var imgHeight;
                    var scaleMargin;
                    var con;
                    var handler;
                    var Tween = {//缓动类 默认提供三种缓动模式:linear easein easeout 
                        linear: function (t, b, c, d, dir) { return c * t / d * dir + b; },
                        easeIn: function (t, b, c, d, dir) {
                            return c * (t /= d) * t * dir + b;
                        },
                        easeOut: function (t, b, c, d, dir) {
                            return -c * (t /= d) * (t - 2) * dir + b;
                        }
                    };
                    /* 改变椭圆旋转轨迹的横半轴长,竖半轴长*/
                    var changeRotateWH = function (width, height) {
                        var halfScale = (this.maxScale - this.minScale) / 2; //旋转到中间位置时的图片的缩放大小 
                        rotate = {};
                        rotate.originX = width / 2; //旋转原点X轴坐标 
                        rotate.originY = height / 2; //旋转原点Y轴坐标 
                        rotate.halfRotateWidth = (width - this.imgWidth) / 2; //旋转横半轴长 
                        rotate.halfRotateHeight = (height - this.imgHeight) / 2; //旋转竖半轴长 
                    }
                    /* 设置图片旋转角和初始位置,大小 */
                    var initImgRC = function (imgs) {
                        var len = imgs.length;
                        con = (2 * Math.PI) / len;
                        for (var i = 0; i < len; i++) {
                            imgs[i].RC = i * con;
                            imgs[i].style.width = imgWidth + 'px';
                            imgs[i].style.height = imgHeight + 'px';
                            setImgPositionAndSize(imgs[i], 0);
                        }
                    }
                    /* 设置图片大小 */
                    var setImgSize = function (img) {
                        var left = rotate.originX + rotate.halfRotateWidth * Math.cos(img.RC) - imgWidth / 2;
                        var top = rotate.originY - rotate.halfRotateHeight * Math.sin(img.RC) - imgHeight / 2;
                        var scale = 0.5 + scaleMargin * (rotate.halfRotateHeight - rotate.halfRotateHeight * Math.sin(img.RC)) / (2 * rotate.halfRotateHeight); //图片在该时刻的缩放比 
                        img.style.cssText = 'position:absolute;left:' + left + 'px;'
                            + 'top:' + top + 'px;'
                            + 'width:' + imgWidth * scale + 'px;'
                            + 'height:' + imgHeight * scale + 'px;'
                            + 'cursor:pointer;'
                            + 'z-index:' + Math.round(scale * 100);
                    }
                    /* 设置图片位置和大小的匀速变化 */
                    var setImgPositionAndSize = function (img, path, direction) {
                        direction = direction || 'CW';
                        var dir = direction == 'CW' ? -1 : 1;
                        img.RC += (path * dir);
                        modifyImgAngle(img);
                        setImgSize(img);
                    }
                    /* 修改图片旋转角度(保证在0-2pai之间) */
                    var modifyImgAngle = function (img) {
                        (img.RC > (2 * Math.PI)) && (img.RC -= 2 * Math.PI);
                        (img.RC < 0) && (img.RC += 2 * Math.PI);
                    }
                    /* 设置图片的新位置 */
                    var setPos = function (img, path) {
                        img.RC = path;
                        modifyImgAngle(img);
                        var left = rotate.originX + rotate.halfRotateWidth * Math.cos(img.RC) - imgWidth / 2;
                        var top = rotate.originY - rotate.halfRotateHeight * Math.sin(img.RC) - imgHeight / 2;
                        var scale = 0.5 + scaleMargin * (rotate.halfRotateHeight - rotate.halfRotateHeight * Math.sin(img.RC)) / (2 * rotate.halfRotateHeight); //图片在该时刻的缩放比 
                        img.style.cssText = 'position:absolute;left:' + left + 'px;'
                            + 'top:' + top + 'px;'
                            + 'width:' + imgWidth * scale + 'px;'
                            + 'height:' + imgHeight * scale + 'px;'
                            + 'z-index:' + Math.round(scale * 100);
                    }
                    /* 旋转指定角度 */
                    var rotateAngle = function (imgs, angle, dir, tween, onSelected) {
                        console.log(99999)
                        var duration = 1000;
                        var startTime = (new Date()).getTime();
                        dir == 'CW' ? dir = -1 : dir = 1;
                        for (var i = 0, len = imgs.length; i < len; i++) {
                            imgs[i].startAngle = imgs[i].RC;
                        }
                        timeId = window.setInterval(function () {
                            var now = (new Date()).getTime();
                            if ((now - startTime) >= duration) {
                                window.clearInterval(timeId);
                                timeId = undefined;
                                onSelected = onSelected || util.emptyFunction;
                                onSelected(); //触发回调函数; 
                            }
                            for (var i = 0, len = imgs.length; i < len; i++) {
                                var path = tween(now - startTime, imgs[i].startAngle, angle, duration, dir); //通过缓动公式计算新角度(RC) 
                                setPos(imgs[i], path, dir);
                            }
                        }, 20);
                    }
                    /* 图片选择事件处理程序 */
                    var imgSelectedHandler = function (imgs, path, tween, onSelected) {
                        return function (eve) {
                            eve = eve || window.event;
                            var dir;
                            var angle;
                            var target = eve.target || eve.srcElement;
                            var RC = target.RC;
                            if (RC >= Math.PI / 2 && RC <= Math.PI * 3 / 2) {
                                dir = 'ACW';
                                angle = 3 * Math.PI / 2 - RC;
                            }
                            else {
                                dir = 'CW';
                                Math.sin(RC) >= 0 ? angle = Math.PI / 2 + RC : angle = RC - 3 * Math.PI / 2;
                            }
                            (typeof timeId != 'undefined') && window.clearInterval(timeId);
                            rotateAngle(imgs, angle, dir, tween, onSelected);
                        }
                    }
                    /* 为图片绑定点击事件处理程序 */
                    var bindHandlerForImgs = function (imgs, path, onSelected) {
                        for (var i = 0, len = imgs.length; i < len; i++) {
                            imgs[i].handler = imgSelectedHandler(imgs, path, onSelected);
                            util.addEventHandler(imgs[i], 'click', imgs[i].handler);
                        }
                    }
                    /* 为图片绑定鼠标移入移出事件处理程序 */
                    // var mouseenterHandlerForImgs = function (imgs, path, onSelected) {
                    //     for (var i = 0, len = imgs.length; i < len; i++) {
                    //         imgs[i].handler = imgSelectedHandler(imgs, path, onSelected);
                    //         util.addEventHandler(imgs[i], 'mouseenter', imgs[i].handler);
                    //     }
                    // }
                    /* 删除图片上的点击事件处理程序 */
                    var removeImgsHandler = function (imgs) {
                        for (var i = 0, len = imgs.length; i < len; i++) {
                            if (imgs[i].handler) {
                                util.removeEventHandler(imgs[i], 'click', imgs[i].handler);
                            }
                        }
                    }
                    return {
                        /* 初始化 */
                        init: function (id, options) {
                            var defaultOptions = {
                                width: 700, //容器宽 
                                height: 300, //容器高 
                                imgWidth: 130, //图片宽 
                                imgHeight: 80, //图片高 
                                maxScale: 1.5, //最大缩放倍数 
                                minScale: 0.5, //最小缩放倍数 
                                rotateSpeed: 10 //运转速度 
                            }
                            options = util.extend(defaultOptions, options); //参数设置 
                            this.container = util.$(id);
                            this.width = options.width;
                            this.height = options.height;
                            imgWidth = this.imgWidth = options.imgWidth;
                            imgHeight = this.imgHeight = options.imgHeight;
                            this.maxScale = options.maxScale;
                            this.minScale = options.minScale;
                            scaleMargin = this.maxScale - this.minScale;
                            this.rotateSpeed = options.rotateSpeed;
                            this.imgs = util.$$('img', this.container);
                            this.setContainerSize(this.width, this.height);
                            initImgRC(this.imgs);
                        },
                        /* 设置容器尺寸 */
                        setContainerSize: function (width, height) {
                            width = width || this.width;
                            height = height || this.height;
                            this.container.style.position = 'relative';
                            this.container.style.width = width + 'px';
                            this.container.style.height = height + 'px';
                            changeRotateWH.call(this, width, height); //改变容器尺寸后改变旋转轨迹 
                        },
                        /* 选择上一幅图片 */
                        prePho: function (onSelected) {
                            if (this.pattern == 'hand') {
                                onSelected = onSelected || util.emptyFunction;
                                var tween = tween || Tween['easeOut'];
                                if (typeof timeId != 'undefined') {
                                    return;
                                } else {
                                    rotateAngle(this.imgs, con, 'ACW', tween, onSelected);
                                }
                            }
                        },
                        /* 选择下一幅图片 */
                        nextPho: function (onSelected) {
                            if (this.pattern == 'hand') {
                                onSelected = onSelected || util.emptyFunction;
                                var tween = tween || Tween['easeOut'];
                                if (typeof timeId != 'undefined') {
                                    return;
                                } else {
                                    rotateAngle(this.imgs, con, 'CW', tween, onSelected);
                                }
                            }
                        },
                        /* 添加缓动模式 */
                        addTweenFunction: function (name, func) {
                            if (typeof func == 'Function' || typeof func == 'Object') {
                                Tween[name] = func;
                            }
                        },
                        /* 设置旋转模式(自动/手动)*/
                        setPattern: function (patternName, option) {
                            option = option || {};
                            this.pattern = patternName;
                            var rotateSpeed = option.rotateSpeed || 10;
                            this.path = Math.PI / 1000 * rotateSpeed;
                            (typeof timeId != 'undefined') && window.clearInterval(timeId);
                            if (patternName === 'auto') {//自动模式 可传入旋转方向:option.rotateDir 旋转速度:option.rotateSpeed 
                                var self = this;
                                var direction = option.rotateDir || 'CW'; //顺时针:CW 逆时针:ACW 
                                removeImgsHandler(this.imgs);
                                timeId = window.setInterval(function () {
                                    for (var i = 0, len = self.imgs.length; i < len; i++) {
                                        setImgPositionAndSize(self.imgs[i], self.path, direction);
                                    }
                                }, 20);
                            }
                            else if (patternName === 'hand') {//手动模式,可传回调函数:option.onSelected 缓动模式:option.tween 
                                var onSelected = option.onSelected || util.emptyFunction;
                                var tween = Tween[tween] || Tween['easeOut']; //缓动模式默认为easeout 
                                removeImgsHandler(this.imgs);
                                (typeof timeId != 'undefined') && window.clearInterval(timeId);
                                timeId = undefined;
                                bindHandlerForImgs(this.imgs, this.path, tween, onSelected);
                            }
                        },
                        //鼠标移入事件
                        
                    }
                })();
                return rp;
            })();
            var rp = new rotatePhos('container');
            // rp.setPattern('auto', { rotateSpeed: 1 });
            rp.setPattern('hand');
            document.getElementById('pre').onclick = function () { rp.prePho(); };
            document.getElementById('next').onclick = function () { rp.nextPho(); };
    // ]]></script>



</body>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容