在pixi.js中由鼠标激活的绿色补间错误的错误

时间:2015-05-31 04:55:39

标签: javascript canvas greensock pixi.js

我正在尝试在pixi中滚动一个greensock补间。我试图挂钩用我的补间获取鼠标/箭头输入(trackpad.value)的代码时遇到错误。

这是我正在运行的greensock测试补间,以确保我在pixi中使用greensock :(必须补间pixi中的position元素):

var t1 = new TimelineMax({onUpdate:animate, onUpdateScope:stage});
 t1.to(bg.position, 3, {y:100});

这是我的代码,我试图将trackpad.value挂钩到greensock代码中(我收到以下错误:Uncaught TypeError: bg.position is not a function)

trackpad = new Trackpad(document);
var t1 = new TimelineMax({paused:true, onUpdate:animate, onUpdateScope:stage});   
  t1.progress(bg.position( Math.abs( trackpad.value ) / 3240));

然后我尝试了以下内容 - 它没有用(但我没有收到错误):

var moveIt = trackpad.value / 3240;
  t1.progress(bg.position, moveIt, {});

以下是定义触控板值的代码:

/*
 *  param: the html element that will be scrolled
 */
Trackpad = function(target)
{
    this.target = target;
    this.value = 0;
    this.easingValue = 00;
    this.dragOffset = 0;
    this.dragging;
    this.speed= 0;
    this.prevPosition = 0;

    $(this.target).mousedown($.proxy(this.onMouseDown, this));
    this.target.onmousewheel = $.proxy(this.onMouseWheel, this);

    // not forgetting touchs!
    this.target.ontouchstart = $.proxy(this.onTouchStart, this);

    // stop dragging!
    $(document).keydown( $.proxy(this.onArrow, this))//function(e){

    //this.target.ondragstart = function(){return false;}
}

// set constructor
Trackpad.constructor = Trackpad;

// create the functions

Trackpad.prototype.unlock = function()
{
    this.locked = false;
    this.speed = 0;
    this.easingValue = this.value;
}

Trackpad.prototype.lock = function()
{
    this.locked = true;
}

Trackpad.prototype.update = function()
{
    if(this.easingValue > 0)this.easingValue = 0;
    if(this.easingValue < -10700)this.easingValue = -10700;
    this.value = this.easingValue;

    if(this.dragging)
    {
        var newSpeed = this.easingValue - this.prevPosition;
        newSpeed *= 0.7;

        this.speed += (newSpeed - this.speed) *0.5;//+= (newSpeed - this.speed) * 0.5;
        this.prevPosition = this.easingValue;
    }
    else
    {
        this.speed *= 0.9;
        this.easingValue +=  this.speed;

        if(Math.abs(this.speed) < 1)this.speed = 0;
    }
}

Trackpad.prototype.onArrow = function(event)
{
     if (event.keyCode == 38) { 
     // UP
     this.speed = 4;
       return false;
    }
    else  if (event.keyCode == 40) { 
     // UP
     this.speed -= 4
       return false;
    }
}

Trackpad.prototype.onMouseWheel = function(event)
{
    event.preventDefault();
    this.speed = event.wheelDelta * 0.1;
}


Trackpad.prototype.startDrag = function(newPosition)
{
    if(this.locked)return;
    this.dragging = true;
    this.dragOffset = newPosition - this.value; 
}

Trackpad.prototype.endDrag = function(newPosition)
{
    if(this.locked)return;
    this.dragging = false;
}

Trackpad.prototype.updateDrag = function(newPosition)
{
    if(this.locked)return;
    this.easingValue = (newPosition - this.dragOffset);
}

/*
 * MOUSE
 */
Trackpad.prototype.onMouseDown = function(event)
{
    if(event)event.preventDefault();

    event.returnValue = false;

    $(document).mousemove($.proxy(this.onMouseMove, this));
    $(document).mouseup($.proxy(this.onMouseUp, this));

    this.startDrag(event.pageY);    
}

Trackpad.prototype.onMouseMove = function(event)
{
    if(event)event.preventDefault();
    this.updateDrag(event.pageY);
}

Trackpad.prototype.onMouseUp = function(event)
{   
    //$(this.target).mousemove(null);
    $(document).unbind('mousemove');
    $(document).unbind('mouseup');
    //this.target.onmousemove = null;

    this.endDrag();// = false;
}

/*
 * TOUCH!
 */
Trackpad.prototype.onTouchStart = function(event)
{
    //event.preventDefault();

    this.target.ontouchmove = $.proxy(this.onTouchMove, this);
    this.target.ontouchend = $.proxy(this.onTouchEnd, this);

    this.startDrag(event.touches[0].clientY);
}

Trackpad.prototype.onTouchMove = function(event)
{

    event.preventDefault();
    this.updateDrag(event.touches[0].clientY);
}

Trackpad.prototype.onTouchEnd = function(event)
{
    this.target.ontouchmove = null;
    this.target.ontouchend = null;
    this.endDrag();
}

**编辑

tl = new TimelineLite( { paused: true } );

 // respond to scroll event - in this case using jquery
 $(window).scroll();
//apply whatever math makes the most sense to progress the timeline progress from 0 to 1 within those parameters. Something like,
$(window).scroll( function() {
    var st = $(this).scrollTop();
    if ( st < someArbitraryValue ) { // someArbitraryValue, where to start
        // Here, "someOtherArbitaryValue" would be the
        // "height" of the scroll to react to
        tl.progress( Math.abs( st ) / someOtherArbitaryValue );
     }
 });

2 个答案:

答案 0 :(得分:2)

this的效果是什么?

JavaScript:

window.requestAnimFrame=(function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(callback){window.setTimeout(callback,1000/60);};})(); //http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
var stageWidth=$(window).innerWidth();
var stageHeight=$(window).innerHeight();
var renderer=PIXI.autoDetectRenderer(stageWidth,stageHeight);
var bg,cat,moon,blue,trackpad,texture1,texture2,texture3;
document.body.appendChild(renderer.view);
texture1=PIXI.Texture.fromImage('https://dl.dropboxusercontent.com/u/45891870/Experiments/StackOverflow/1.5/cat.jpg');
texture2=PIXI.Texture.fromImage('https://dl.dropboxusercontent.com/u/45891870/Experiments/StackOverflow/1.5/moon.jpg');
texture3=PIXI.Texture.fromImage('https://dl.dropboxusercontent.com/u/45891870/Experiments/StackOverflow/1.5/blue.jpg');
bg=new PIXI.Container();
cat=new PIXI.Sprite(texture1);
moon=new PIXI.Sprite(texture2);
blue=new PIXI.Sprite(texture3);
cat.anchor.x=cat.anchor.y=moon.anchor.x=moon.anchor.y=blue.anchor.x=blue.anchor.y=0;
cat.position.x=cat.position.y=moon.position.x=blue.position.x=bg.position.x=bg.position.y=0;
cat.width=moon.width=blue.width=stageWidth;
moon.position.y=1080;
blue.position.y=2160;
bg.addChild(cat);
bg.addChild(blue);
bg.addChild(moon);
bg.vy=bg.vx=0;//what are those?
trackpad=new Trackpad(document);
requestAnimFrame(animate);
function animate(){
    requestAnimFrame(animate);
    bg.position.y=trackpad.value;
    trackpad.update();
    renderer.render(bg);
}

让我知道这是否正是您正在寻找的东西&amp;然后,我会根据与您的代码相比发生的变化为您分解。

备注:

  1. 第一&amp;最重要的是,我在上面的示例中使用了 Pixi.JS 的最新版本(v3.0.6)。此 v3 更新带来了一些重大更改。他们的几个突出你的问题是:
    • 不再需要Stage对象用于渲染目的。任何Container类型对象都可以直接用于在画布上呈现。
    • 将名称DisplayObjectContainer简化为Container。这可能是您在注释中提到的环境中尝试实现我的代码时出现错误的原因,因为我认为您使用的是旧版本之一。
    • 阅读有关此更新的所有信息herehere&amp; here
  2. 我总是喜欢使用最新的&amp;最大的 GSAP v1.17.0‏)。即使是这个框架的点发布也带来了重大更新,这就是为什么我想让它保持最新。阅读有关此更新的重要说明here。话虽如此,当前的实现并没有真正使用TweenMax
  3. TweenMax 捆绑EasePackCSSPlugin&amp;其他一些事情。无需单独加载它们。相应地更新您的HTML。使用GSAP CheatSheet Peter Tichy这个方便的requestAnimationFrame polyfill来获取此类信息以及有关此工具的更多信息。
  4. Trackpad.js中的更改:
    • update方法中,定义了页面可以向上滚动的最大滚动限制。此值之前 -10700 。我将其更改为 -2160 。您可能希望将其设置为 -3240 我认为,基于我能够理解到您想要实现的目标。
    • 格式化更改。
  5. main.js中的更改(您为主脚本文件指定的名称):
    • 感谢 Paul Irish
    • 添加了https://docs.angularjs.org/api/ng/directive/ngStyle
    • 删除了var stage= new PIXI.Stage(0xff00ff);行。请阅读上面的#1 了解详情。
    • DisplayObjectContainer重命名为已分配给Container的{​​{1}}。请阅读上面的#1 了解详情。
    • bg循环中添加了bg.position.y=trackpad.value;。你错过了这个。您需要使用animate来定位trackpad.value
    • 在同一个bg循环中添加了trackpad.update();。这是最重要的一个和恕我直言,这是你没有理解的目的。总而言之,animate需要及时更新其Trackpad.js&amp;由于value,您运行的唯一循环是animate循环。因此,调用requestAnimFrame方法。
    • 渲染update();而不是bg。请阅读上面的#1 了解详情。
    • 格式化更改。
  6. 如果有什么不清楚,请告诉我。

    Ť

答案 1 :(得分:1)

我想要编辑旧的答案,但决定反对它,因为我认为它回答了你原来的问题。

请查看此Codepen demo以获取解决同一问题的新方法。我真的希望听听社区关于我在这里采取的方法,听取事件并使用它们来调整GSAP时间表。

我的示例中使用了 4 个JS文件:app.jsconstants.jstimeline.js&amp; listeners.js。链接可以在演示的JavaScript编辑器的设置齿轮图标中找到。所有这些文件都经过大量注释,并附有我在互联网上发现的针对特定问题的解决方案的链接。

在这些文件中,app.js的代码如下:

<强> JavaScript的:

function Application(){}
Application.prototype.init=function(){
    this.constants=Constants.getInstance();
    this.BASE_URL=this.constants.BASE_URL;
    this.IMAGE_JS_URL=this.constants.IMAGE_JS_URL;
    this.IMAGE_PIXI_URL=this.constants.IMAGE_PIXI_URL;
    this.IMAGE_GSAP_URL=this.constants.IMAGE_GSAP_URL;
    this.createPolyfillForBind();
    this.setupRenderer();
    this.loadImages();
};
Application.prototype.setupRenderer=function(){
    this.stageWidth=window.innerWidth;
    this.stageHeight=window.innerHeight;
    //this.renderer=PIXI.autoDetectRenderer(this.stageWidth,this.stageHeight);
    this.renderer=new PIXI.CanvasRenderer(this.stageWidth,this.stageHeight);
    document.body.appendChild(this.renderer.view);
};
Application.prototype.loadImages=function(){
    var self=this;
    this.loader=new PIXI.loaders.Loader(this.BASE_URL,1,{crossOrigin:''}); // PIXI Loader class [http://pixijs.github.io/docs/PIXI.loaders.Loader.html]
    this.loader.add(this.IMAGE_JS_URL); // Loader extends ResourceLoader [http://adireddy.github.io/docs/haxe-pixi/v3/types/pixi/plugins/resourceloader/ResourceLoader.html]
    this.loader.add(this.IMAGE_PIXI_URL);
    this.loader.add(this.IMAGE_GSAP_URL);
    //this.loader.once('complete',function(){self.onImagesLoaded.apply(self);}); // Vanilla JS alternative to jQuery's proxy() method [http://stackoverflow.com/a/4986536]
    this.loader.once('complete',this.onImagesLoaded.bind(this)); // bind() polyfill [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill]
    this.loader.load();
};
Application.prototype.onImagesLoaded=function(){
    this.setupSprites();
    this.initTimeline();
    this.initListeners();
    this.startTicker();
};
Application.prototype.setupSprites=function(){
    this.containerBg=new PIXI.Container();
    this.spriteJS=new PIXI.Sprite(PIXI.utils.TextureCache[this.BASE_URL+this.IMAGE_JS_URL]); // TextureCache in action [http://www.html5gamedevs.com/topic/7674-load-textures-synchronously/?p=45836]
    this.spritePIXI=new PIXI.Sprite(PIXI.utils.TextureCache[this.BASE_URL+this.IMAGE_PIXI_URL]); // PIXI.TextureCache became PIXI.utils.TextureCache in v3 [http://www.html5gamedevs.com/topic/14144-v3-utilstexturecache-utils-is-not-defined/?p=80524]
    this.spriteGSAP=new PIXI.Sprite(PIXI.utils.TextureCache[this.BASE_URL+this.IMAGE_GSAP_URL]);
    this.containerBg.addChild(this.spriteJS);
    this.containerBg.addChild(this.spritePIXI);
    this.containerBg.addChild(this.spriteGSAP);
    this.spriteJS.anchor.x=this.spriteJS.anchor.y=this.spritePIXI.anchor.x=this.spritePIXI.anchor.y=this.spriteGSAP.anchor.x=this.spriteGSAP.anchor.y=0;
    this.spriteJS.position.x=this.spriteJS.position.y=this.spritePIXI.position.x=this.spriteGSAP.position.x=this.containerBg.position.x=this.containerBg.position.y=0;
    this.scaleImage(this.spriteJS);
    this.scaleImage(this.spritePIXI);
    this.scaleImage(this.spriteGSAP);
    this.spritePIXI.alpha=this.spriteGSAP.alpha=0;
    this.spriteJS.position.y=this.constants.GUTTER;
    this.spritePIXI.position.y=this.spriteJS.height*2+this.constants.GUTTER;
    this.spriteGSAP.position.y=this.spriteJS.height+this.spritePIXI.height*2+this.constants.GUTTER;
};
Application.prototype.scaleImage=function(sprite){
    //var scale=Math.min(this.stageWidth/sprite.width,this.stageHeight/sprite.height); // resize with aspect ratio [http://community.createjs.com/discussions/createjs/547-resizing-canvas-and-its-content-proportionally-cross-platform#comment_27266530] and [https://opensourcehacker.com/2011/12/01/calculate-aspect-ratio-conserving-resize-for-images-in-javascript/]
    var scale=this.stageWidth/sprite.width;
    sprite.scale.x=sprite.scale.y=scale;
};
Application.prototype.initTimeline=function(){
    this.timeline=new Timeline();
    this.timeline.init(this.containerBg,this.spriteJS,this.spritePIXI,this.spriteGSAP,this.stageWidth,this.stageHeight);
};
Application.prototype.initListeners=function(){
    var self=this;
    //this.listeners=new Listeners();
    //this.constants.setListenersObject(this.listeners);
    //this.listeners.init();
    this.listeners=Listeners.getInstance();
    this.listeners.addListeners();
    document.addEventListener(this.constants.SCROLLED,this.onScroll.bind(this),false);
    document.addEventListener(this.constants.STARTED_DRAG,this.onStartDrag.bind(this),false);
    document.addEventListener(this.constants.DRAGGED,this.onDrag.bind(this),false);
    document.addEventListener(this.constants.END_DRAG,this.onEndDrag.bind(this),false);
};
Application.prototype.onScroll=function(e){ this.timeline.onScroll(e); };
Application.prototype.onStartDrag=function(e){ this.timeline.onStartDrag(e); };
Application.prototype.onDrag=function(e){ this.timeline.onDrag(e); };
Application.prototype.onEndDrag=function(e){ this.timeline.onEndDrag(e); };
Application.prototype.startTicker=function(){
    var self=this;
    //TweenLite.ticker.addEventListener('tick',function(){self.render.apply(self);},false); // Vanilla JS alternative to jQuery's proxy() method [http://stackoverflow.com/a/4986536]
    TweenLite.ticker.addEventListener('tick',this.render.bind(this),false);
};
Application.prototype.render=function(){this.renderer.render(this.containerBg);};
Application.prototype.createPolyfillForBind=function(){ // [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill]
    if(!Function.prototype.bind){
        Function.prototype.bind=function(oThis){
            if(typeof this!=='function'){
                // closest thing possible to the ECMAScript 5
                // internal IsCallable function
                throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
            }
            var aArgs=Array.prototype.slice.call(arguments,1),
                fToBind=this,
                fNOP=function(){},
                fBound=function(){
                    return fToBind.apply(this instanceof fNOP
                            ?this
                            :oThis,
                        aArgs.concat(Array.prototype.slice.call(arguments)));
                };
            fNOP.prototype=this.prototype;
            fBound.prototype=new fNOP();
            return fBound;
        };
    }
};
//
var app=new Application();
app.init();

P.S。我也在同一个例子中大量尝试了设计模式,主要是PrototypeSingleton模式。我也期待社区对他们的评论。

Ť