如何修复云旋转木马的插件?

时间:2012-04-20 04:39:44

标签: jquery geometry

我在互联网上发现了这个插件,并将它用于我的任务,但它有一个问题,例如我有4个标志的图像,云旋转木马插件将使这些标志在圆圈转,但当它停止前面旗帜和后旗不停在中心,我的意思是4旗的位置不正确,我不知道如何更清楚地谈论它,但请看图像你会明白我得到的问题。另外,我不擅长数学,我不知道如何像插件一样计算。请看一下建议我一些解决方案。提前谢谢!

这是问题的图像:

http://www.mediafire.com/i/?onvaklt5kbqgxt8

or

http://imageshack.us/photo/my-images/4/imgproblem.png/

这是一个正确的例子:

http://www.mediafire.com/i/?uqk4c1ndyeo50q2

or 

http://imageshack.us/photo/my-images/135/examplecd.jpg/

这里是html代码:

<div class="circle" id="carousel">
            <img class="cloudcarousel" src="images/flag_spain.png" title="Treatment with Baraclude was generally well tolerated and no patients discontinued treatment due to AEs.1"
                alt="ORIENTE Study (n=190)" />
            <img class="cloudcarousel" src="images/flag_italy.png" title="No major safety issues were recorded; none of the patients had to stop or reduce the dose during the study.2 "
                alt="Italian Cohort (n=418) " />
            <img class="cloudcarousel" src="images/flag_eu.png" title="[Baraclude] was safe and didn’t affect renal function or cause lactic acidosis.3"
                alt="VIRGIL Study - Naïve cohort (n=243)" />
            <img class="cloudcarousel" src="images/flag_hongkong.png" title="There were no serious adverse events related to the drug.4"
                alt="Hong Kong Study (n=222)" />
            <p id="title-box">
            </p>
            <div id="all-box">
            </div>
            <span id="alt-box"></span>
        </div>

这是css代码:

.circle {
    background:url(../images/circle.png) no-repeat;
    /*width:445px;
    height:138px;
    position:absolute;
    top:315px;
    left:288px;*/
    width:650px;
    height:475px;
    position:absolute;
    top:165px;
    left:185px;
}

#title-box {
    background-image:url(../images/title_bg.png);
    color: #000;
    font-size: 2em;
    height: 100px;
    padding: 24px 20px 20px 20px;
    text-align: center;
    width: 610px;
}

#alt-box 
{
    bottom: 0;
    height: 25px;
    left: 0;
    position: absolute;
    width: 650px;
}

.cloudcarousel {
    opacity: 0;
}

这是插件的代码,我编辑了一些。

//////////////////////////////////////////////////////////////////////////////////
// CloudCarousel V1.0.5
// (c) 2011 by R Cecco. <http://www.professorcloud.com>
// MIT License
//
// reflection code based on plugin by Christophe Beyls <http://www.digitalia.be>
//
// Please retain this copyright header in all versions of the software
//////////////////////////////////////////////////////////////////////////////////

(function ($) {

    // START reflection object.
    // Creates a reflection for underneath an image.
    // IE uses an image with IE specific filter properties, other browsers use the Canvas tag.  
    // The position and size of the reflection gets updated by updateAll() in controller.
    function reflection(img, reflHeight, opacity) {

        var reflect, cntx, imageWidth = img.width, imageHeight = img.width, gradient, parent;

        parent = $(img.parentNode);
        this.element = reflect = parent.append("<canvas class='reflection' style='position:absolute'/>").find(':last')[0];
        if (!reflection.getContext && $.browser.msie) {
            this.element = reflection = parent.append("<img class='reflection' style='position:absolute'/>").find(':last')[0];
            reflect.src = img.src;
            reflect.style.filter = "flipv progid:DXImageTransform.Microsoft.Alpha(opacity=" + (opacity * 100) + ", style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy=" + (reflHeight / imageHeight * 100) + ")";

        } else {
            cntx = reflection.getContext("2d");
            try {


                $(reflect).attr({ width: imageWidth, height: reflHeight });
                cntx.save();
                cntx.translate(0, imageHeight - 1);
                cntx.scale(1, -1);
                cntx.drawImage(img, 0, 0, imageWidth, imageHeight);
                cntx.restore();
                cntx.globalCompositeOperation = "destination-out";
                gradient = cntx.createLinearGradient(0, 0, 0, reflHeight);
                gradient.addColorStop(0, "rgba(255, 255, 255, " + (1 - opacity) + ")");
                gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");
                cntx.fillStyle = gradient;
                cntx.fillRect(0, 0, imageWidth, reflHeight);
            } catch (e) {
                return;
            }
        }
        // Store a copy of the alt and title attrs into the reflection
        $(reflect).attr({ 'alt': $(img).attr('alt'), title: $(img).attr('title') });

    } //END reflection object

    // START item object.
    // A wrapper object for items within the carousel.
    var item = function (imgIn, options) {
        this.orgWidth = imgIn.width;
        this.orgHeight = imgIn.height;
        this.image = imgIn;
        this.reflection = null;
        this.alt = imgIn.alt;
        this.title = imgIn.title;
        this.imageOK = false;
        this.options = options;

        this.imageOK = true;

        if (this.options.reflHeight > 0) {
            this.reflection = new reflection(this.image, this.options.reflHeight, this.options.reflOpacity);
        }
        $(this.image).css('position', 'absolute'); // Bizarre. This seems to reset image width to 0 on webkit!                  
    }; // END item object


    // controller object.
    // This handles moving all the items, dealing with mouse clicks etc.    
    var controller = function (container, images, options) {

        var items = [], funcSin = Math.sin, funcCos = Math.cos, ctx = this;
        this.controlTimer = 0;
        this.stopped = false;
        //this.imagesLoaded = 0;
        this.container = container;
        this.xRadius = options.xRadius;
        this.yRadius = options.yRadius;
        this.showFrontTextTimer = 0;
        this.autoRotateTimer = 0;
        if (options.xRadius === 0) {
            this.xRadius = ($(container).width() / 2.3);
            console.log(this.xRadius);
        }
        if (options.yRadius === 0) {
            this.yRadius = ($(container).height() / 6);
        }

        this.xCentre = options.xPos;
        this.yCentre = options.yPos;
        this.frontIndex = 0; // Index of the item at the front

        // Start with the first item at the front.
        this.rotation = this.destRotation = Math.PI / 2;
        this.timeDelay = 1000 / options.FPS;

        // Turn on the infoBox
        if (options.altBox !== null) {
            $(options.altBox).css('display', 'block');
            $(options.titleBox).css('display', 'block');
        }
        // Turn on relative position for container to allow absolutely positioned elements
        // within it to work.
        $(container).css({ position: 'relative', overflow: 'hidden' });

        $(options.buttonLeft).css('display', 'inline');
        $(options.buttonRight).css('display', 'inline');

        // Setup the buttons.
        $(options.buttonLeft).bind('mouseup', this, function (event) {
            event.data.rotate(-1);
            return false;
        });
        $(options.buttonRight).bind('mouseup', this, function (event) {
            event.data.rotate(1);
            return false;
        });

        // You will need this plugin for the mousewheel to work: http://plugins.jquery.com/project/mousewheel
        //        if (options.mouseWheel) {
        //            $(container).bind('mousewheel', this, function (event, delta) {
        //                event.data.rotate(delta);
        //                return false;
        //            });
        //        }
        $(container).bind('click', this, function (event) {

            clearInterval(event.data.autoRotateTimer);  // Stop auto rotation if mouse over.
            var text = $(event.target).attr('alt');
            // If we have moved over a carousel item, then show the alt and title text.

            if (text !== undefined && text !== null) {

                clearTimeout(event.data.showFrontTextTimer);
                //if (event.type == 'click') {
                $(options.altBox).html(($(event.target).attr('alt')));
                $(options.titleBox).html(($(event.target).attr('title')));
                //}

                //if (options.bringToFront && event.type == 'click') {
                if (options.bringToFront) {
                    var idx = $(event.target).data('itemIndex');
                    var frontIndex = event.data.frontIndex;
                    //var   diff = idx - frontIndex;                    
                    var diff = (idx - frontIndex) % images.length;
                    if (Math.abs(diff) > images.length / 2) {
                        diff += (diff > 0 ? -images.length : images.length);
                    }
                    event.data.rotate(-diff);
                    console.log(-diff);
                }
            }
        });

        $(options.specialBox).bind('click', this, function (event) {
            event.data.rotate(0.5);
        });

        // If we have moved out of a carousel item (or the container itself),
        // restore the text of the front item in 1 second.
        //        $(container).bind('mouseout', this, function (event) {
        //            var context = event.data;
        //            clearTimeout(context.showFrontTextTimer);
        //            context.showFrontTextTimer = setTimeout(function () { context.showFrontText(); }, 1000);
        //            context.autoRotate(); // Start auto rotation.
        //        });

        // Prevent items from being selected as mouse is moved and clicked in the container.
        $(container).bind('mousedown', this, function (event) {
            event.data.container.focus();
            return false;
        });
        container.onselectstart = function () { return false; };    // For IE.

        this.innerWrapper = $(container).wrapInner('<div style="position:absolute;width:100%;height:100%;"/>').children()[0];

        // Shows the text from the front most item.
        this.showFrontText = function () {
            if (items[this.frontIndex] === undefined) { return; } // Images might not have loaded yet.
            $(options.titleBox).html($(items[this.frontIndex].image).attr('title'));
            $(options.altBox).html($(items[this.frontIndex].image).attr('alt'));
        };

        this.go = function () {
            if (this.controlTimer !== 0) { return; }
            var context = this;
            this.controlTimer = setTimeout(function () { context.updateAll(); }, this.timeDelay);
        };

        this.stop = function () {
            clearTimeout(this.controlTimer);
            this.controlTimer = 0;
        };


        // Starts the rotation of the carousel. Direction is the number (+-) of carousel items to rotate by.
        this.rotate = function (direction) {
            this.frontIndex -= direction;
            this.frontIndex %= items.length;
            this.destRotation += (Math.PI / items.length) * (2 * direction);
            this.showFrontText();
            this.go();
        };


        this.autoRotate = function () {
            if (options.autoRotate !== 'no') {
                var dir = (options.autoRotate === 'right') ? 1 : -1;
                this.autoRotateTimer = setInterval(function () { ctx.rotate(dir); }, options.autoRotateDelay);
            }
        };

        // This is the main loop function that moves everything.
        this.updateAll = function () {
            var minScale = options.minScale; // This is the smallest scale applied to the furthest item.
            var smallRange = (1 - minScale) * 0.4;
            var w, h, x, y, scale, item, sinVal;

            var change = (this.destRotation - this.rotation);
            var absChange = Math.abs(change);

            this.rotation += change * options.speed;
            if (absChange < 0.001) { this.rotation = this.destRotation; }
            var itemsLen = items.length;
            var spacing = (Math.PI / itemsLen) * 2;
            //var   wrapStyle = null;
            var radians = this.rotation;
            var isMSIE = $.browser.msie;

            // Turn off display. This can reduce repaints/reflows when making style and position changes in the loop.
            // See http://dev.opera.com/articles/view/efficient-javascript/?page=3          
            this.innerWrapper.style.display = 'none';

            var style;
            var px = 'px', reflHeight;
            var context = this;
            for (var i = 0; i < itemsLen; i++) {
                item = items[i];

                sinVal = funcSin(radians);

                scale = ((sinVal + 1) * smallRange) + minScale;

                x = this.xCentre + (((funcCos(radians) * this.xRadius) - (item.orgWidth * 0.5)) * scale);
                y = this.yCentre + (((sinVal * this.yRadius)) * scale);

                if (item.imageOK) {
                    var img = item.image;

                    //w = img.width = item.orgWidth * scale;
                    //h = img.height = item.orgHeight * scale;
                    img.style.webkittransition = 'transform 0.5s linear, left 0.5s linear, top 0.5s linear';
                    img.style.webkitTransform = 'scale(' + scale + ')';
                    w = item.orgWidth * scale;
                    h = item.orgHeight * scale;
                    //x = x == 214 ? 235 : x;
                    //x = x == 249 ? 235 : x;
                    if (i == 0) {
                        console.log('x : ' + x);
                        console.log('absChange : ' + absChange);
                    }
                    img.style.left = x + px;
                    img.style.top = y + px;
                    img.style.zIndex = "" + (scale * 100) >> 0; // >>0 = Math.foor(). Firefox doesn't like fractional decimals in z-index.

                    if (item.reflection !== null) {
                        reflHeight = options.reflHeight * scale;
                        style = item.reflection.element.style;
                        style.left = x + px;
                        style.top = y + h + options.reflGap * scale + px;
                        style.width = w + px;
                        if (isMSIE) {
                            style.filter.finishy = (reflHeight / h * 100);
                        } else {
                            style.height = reflHeight + px;
                        }
                    }
                }
                radians += spacing;
            }
            // Turn display back on.                    
            this.innerWrapper.style.display = 'block';

            // If we have a preceptable change in rotation then loop again next frame.
            if (absChange >= 0.001) {
                this.controlTimer = setTimeout(function () { context.updateAll(); }, this.timeDelay);
            } else {
                // Otherwise just stop completely.              
                this.stop();
            }
        }; // END updateAll     

        // Create an item object for each image 
        //      func = function(){return;ctx.updateAll();} ;

        // Check if images have loaded. We need valid widths and heights for the reflections.
        this.checkImagesLoaded = function () {

            var i;
            for (i = 0; i < images.length; i++) {
                if ((images[i].width === undefined) || ((images[i].complete !== undefined) && (!images[i].complete))) {
                    return;
                }
            }
            for (i = 0; i < images.length; i++) {
                items.push(new item(images[i], options));
                $(images[i]).data('itemIndex', i);
            }
            // If all images have valid widths and heights, we can stop checking.           
            clearInterval(this.tt);
            this.showFrontText();
            this.autoRotate();
            this.updateAll();

            for (i = 0; i < images.length; i++) {
                images[i].style.opacity = 1;
            }
        };

        this.tt = setInterval(function () { ctx.checkImagesLoaded(); }, 50);
    }; // END controller object

    // The jQuery plugin part. Iterates through items specified in selector and inits a controller class for each one.
    $.fn.CloudCarousel = function (options) {

        this.each(function () {

            options = $.extend({}, {
                reflHeight: 0,
                reflOpacity: 0.5,
                reflGap: 0,
                minScale: 0.5,
                xPos: 0,
                yPos: 0,
                xRadius: 0,
                yRadius: 0,
                specialBox: null,
                altBox: null,
                titleBox: null,
                FPS: 30,
                autoRotate: 'no',
                autoRotateDelay: 1500,
                speed: 0.2,
                mouseWheel: false,
                bringToFront: false
            }, options);
            // Create a controller for each carousel.       
            $(this).data('cloudcarousel', new controller(this, $('.cloudcarousel', $(this)), options));
        });
        return this;
    };

})(jQuery);

// this is my code that implement the plugin above
$(document).bind('ready', function () {

    $("#carousel").CloudCarousel({
        minScale: 0.4,
        xPos: 280,
        yPos: 0,
        xRadius: 260,
        yRadius: 0,
        FPS: 50,
        specialBox: '#all-box',
        titleBox: '#title-box',
        altBox: '#alt-box',
        autoRotate: 'no',
        auted: 0.1,
        bringToFront: true
    });
});

1 个答案:

答案 0 :(得分:3)

请将您正在拨打的电话发给CloudCarousel。您可以在此调用中轻松指定居中参数。

正是关于正确计算xPos的一切。让我试着告诉你如何计算它。

计算轮播容器的宽度(在您的情况下为650);

通常通过将xPos指定为轮播容器宽度的一半,您应该获得正确的结果。

请参阅网站http://www.professorcloud.com/mainsite/carousel-integration.htm上提供的文档。这是不言自明的。