how to make famo.us recalculate sizes?

扶醉桌前 提交于 2019-12-04 18:24:44

I too owe johntraver a beer for his excellent answers on famo.us questions here. This is work derived from one of his previous answers, I use it for surfaces on scrollviews with dynamic html content (and height):

/* AutoSurface.js */

define(function(require, exports, module) {
    var Surface = require('famous/core/Surface');
    var Entity = require('famous/core/Entity');

    function AutoSurface(options) {
        Surface.apply(this, arguments);
        this.hasTrueSize = false;
        this._superCommit = Surface.prototype.commit;
    }

    AutoSurface.prototype = Object.create(Surface.prototype);

    AutoSurface.prototype.constructor = AutoSurface;

    AutoSurface.prototype.commit = function commit(context) {
        this._superCommit(context);
        if (!this.hasTrueSize) {
            this.trueHeight = Entity.get(this.id)._currTarget.clientHeight;
            this.setSize([undefined,this.trueHeight]);
            this.hasTrueSize = true;
        }
    }

    module.exports = AutoSurface;
});

Commit is called every tick so you should be able to wait until you have a height > 0 or what you need before you set hasTrueSize = true.

johntraver

This is very similar to the answer I just posted here.

how best to create a single scrollable view in famo.us?

You can wrap your true-sized surfaces in a sized modifier. This allows for scrollview to know the actual height of the surfaces within, and thus properly scroll. I am using the _currTarget of surface in the Modifiers sizeFrom method. The ternary operation is to prevent errors pre-deploy of the surface.

Here is that example revised for multiple cells in scrollview.. Hope it helps!

var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var RenderNode = require('famous/core/RenderNode');
var Modifier = require('famous/core/Modifier');
var Scrollview  = require('famous/views/Scrollview');

var context = Engine.createContext();

var content = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod \
                tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, \
                quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo \
                consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse \
                cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non \
                proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

var scrollview = new Scrollview();

var surfaces = [];
scrollview.sequenceFrom(surfaces);

for (var i = 0; i < 10; i++) {
    var surface = new Surface({
        size:[undefined,true],
        content: content,
        properties:{
            fontSize:'24px',
            backgroundColor:'hsl('+(i*360/20)+',100%,50%)'
        }
    })

    surface.pipe(scrollview);

    surface.node = new RenderNode();
    surface.mod = new Modifier();

    surface.mod.sizeFrom(function(){
        target = this._currTarget;
        return target ? [undefined,target.offsetHeight] : [undefined,true];
    }.bind(surface));

    surface.node.add(surface.mod).add(surface);

    surfaces.push(surface.node);
};

context.add(scrollview);

Instead of hacking deploy of using a sizeFrom-modifier, there is a much easier hack:

Let a surface return it's actual calculated height instead of it's specified height.

Override the default getSize function with this:

surface.getSize = function() { return this._size || this.size }

Full example in a JSFiddle

Warning: This breaks setting the Size with a modifier higher up the rendering tree. (But since you set size explictly anyway, this should not be a problem)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!